1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 11:37:44 +00:00

Merge pull request #2158 from jhscheer/issue2147

tr: implement complement separately from delete or squeeze (#2147)
This commit is contained in:
Sylvestre Ledru 2021-05-02 17:21:21 +02:00 committed by GitHub
commit 79068d231f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 74 additions and 13 deletions

View file

@ -123,10 +123,17 @@ impl SymbolTranslator for DeleteAndSqueezeOperation {
struct TranslateOperation { struct TranslateOperation {
translate_map: FnvHashMap<usize, char>, translate_map: FnvHashMap<usize, char>,
complement: bool,
s2_last: char,
} }
impl TranslateOperation { impl TranslateOperation {
fn new(set1: ExpandSet, set2: &mut ExpandSet, truncate: bool) -> TranslateOperation { fn new(
set1: ExpandSet,
set2: &mut ExpandSet,
truncate: bool,
complement: bool,
) -> TranslateOperation {
let mut map = FnvHashMap::default(); let mut map = FnvHashMap::default();
let mut s2_prev = '_'; let mut s2_prev = '_';
for i in set1 { for i in set1 {
@ -139,14 +146,26 @@ impl TranslateOperation {
map.insert(i as usize, s2_prev); map.insert(i as usize, s2_prev);
} }
} }
TranslateOperation { translate_map: map } TranslateOperation {
translate_map: map,
complement,
s2_last: set2.last().unwrap_or(s2_prev),
}
} }
} }
impl SymbolTranslator for TranslateOperation { impl SymbolTranslator for TranslateOperation {
fn translate(&self, c: char, _prev_c: char) -> Option<char> { fn translate(&self, c: char, _prev_c: char) -> Option<char> {
if self.complement {
Some(if self.translate_map.contains_key(&(c as usize)) {
c
} else {
self.s2_last
})
} else {
Some(*self.translate_map.get(&(c as usize)).unwrap_or(&c)) Some(*self.translate_map.get(&(c as usize)).unwrap_or(&c))
} }
}
} }
struct TranslateAndSqueezeOperation { struct TranslateAndSqueezeOperation {
@ -163,7 +182,7 @@ impl TranslateAndSqueezeOperation {
complement: bool, complement: bool,
) -> TranslateAndSqueezeOperation { ) -> TranslateAndSqueezeOperation {
TranslateAndSqueezeOperation { TranslateAndSqueezeOperation {
translate: TranslateOperation::new(set1, set2, truncate), translate: TranslateOperation::new(set1, set2, truncate, complement),
squeeze: SqueezeOperation::new(set2_, complement), squeeze: SqueezeOperation::new(set2_, complement),
} }
} }
@ -198,8 +217,8 @@ fn translate_input<T: SymbolTranslator>(
// Set `prev_c` to the post-translate character. This // Set `prev_c` to the post-translate character. This
// allows the squeeze operation to correctly function // allows the squeeze operation to correctly function
// after the translate operation. // after the translate operation.
if res.is_some() { if let Some(rc) = res {
prev_c = res.unwrap(); prev_c = rc;
} }
res res
}); });
@ -300,11 +319,6 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
return 1; return 1;
} }
if complement_flag && !delete_flag && !squeeze_flag {
show_error!("-c is only supported with -d or -s");
return 1;
}
let stdin = stdin(); let stdin = stdin();
let mut locked_stdin = stdin.lock(); let mut locked_stdin = stdin.lock();
let stdout = stdout(); let stdout = stdout();
@ -339,8 +353,8 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
} }
} else { } else {
let mut set2 = ExpandSet::new(sets[1].as_ref()); let mut set2 = ExpandSet::new(sets[1].as_ref());
let op = TranslateOperation::new(set1, &mut set2, truncate_flag); let op = TranslateOperation::new(set1, &mut set2, truncate_flag, complement_flag);
translate_input(&mut locked_stdin, &mut buffered_stdout, op) translate_input(&mut locked_stdin, &mut buffered_stdout, op);
} }
0 0

View file

@ -59,6 +59,53 @@ fn test_delete_complement_2() {
.stdout_is("01234567890"); .stdout_is("01234567890");
} }
#[test]
fn test_complement1() {
new_ucmd!()
.args(&["-c", "a", "X"])
.pipe_in("ab")
.run()
.stdout_is("aX");
}
#[test]
fn test_complement2() {
new_ucmd!()
.args(&["-c", "0-9", "x"])
.pipe_in("Phone: 01234 567890")
.run()
.stdout_is("xxxxxxx01234x567890");
}
#[test]
fn test_complement3() {
new_ucmd!()
.args(&["-c", "abcdefgh", "123"])
.pipe_in("the cat and the bat")
.run()
.stdout_is("3he3ca33a3d33he3ba3");
}
#[test]
fn test_complement4() {
// $ echo -n '0x1y2z3' | tr -c '0-@' '*-~'
// 0~1~2~3
new_ucmd!()
.args(&["-c", "0-@", "*-~"])
.pipe_in("0x1y2z3")
.run()
.stdout_is("0~1~2~3");
// TODO: fix this
// $ echo '0x1y2z3' | tr -c '\0-@' '*-~'
// 0a1b2c3
// new_ucmd!()
// .args(&["-c", "\\0-@", "*-~"])
// .pipe_in("0x1y2z3")
// .run()
// .stdout_is("0a1b2c3");
}
#[test] #[test]
fn test_squeeze() { fn test_squeeze() {
new_ucmd!() new_ucmd!()