From 117e84eed3adabb54fa852030712848f08c319f1 Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Sat, 1 May 2021 18:46:13 +0200 Subject: [PATCH 1/4] tr: implement complement separately from delete or squeeze (#2147) --- src/uu/tr/src/tr.rs | 34 ++++++++++++++++++++++++---------- tests/by-util/test_tr.rs | 27 +++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/src/uu/tr/src/tr.rs b/src/uu/tr/src/tr.rs index 6c1c0746a..f8fabd69f 100644 --- a/src/uu/tr/src/tr.rs +++ b/src/uu/tr/src/tr.rs @@ -125,10 +125,17 @@ impl SymbolTranslator for DeleteAndSqueezeOperation { struct TranslateOperation { translate_map: FnvHashMap, + complement: bool, + s2_last: char, } 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 s2_prev = '_'; for i in set1 { @@ -141,13 +148,25 @@ impl TranslateOperation { map.insert(i as usize, s2_prev); } } - TranslateOperation { translate_map: map } + TranslateOperation { + translate_map: map, + complement, + s2_last: s2_prev, + } } } impl SymbolTranslator for TranslateOperation { fn translate(&self, c: char, _prev_c: char) -> Option { - Some(*self.translate_map.get(&(c as usize)).unwrap_or(&c)) + 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)) + } } } @@ -256,11 +275,6 @@ pub fn uumain(args: impl uucore::Args) -> i32 { 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 mut locked_stdin = stdin.lock(); let stdout = stdout(); @@ -282,8 +296,8 @@ pub fn uumain(args: impl uucore::Args) -> i32 { translate_input(&mut locked_stdin, &mut buffered_stdout, op); } else { let mut set2 = ExpandSet::new(sets[1].as_ref()); - let op = TranslateOperation::new(set1, &mut set2, truncate_flag); - translate_input(&mut locked_stdin, &mut buffered_stdout, op) + let op = TranslateOperation::new(set1, &mut set2, truncate_flag, complement_flag); + translate_input(&mut locked_stdin, &mut buffered_stdout, op); } 0 diff --git a/tests/by-util/test_tr.rs b/tests/by-util/test_tr.rs index 630c305c6..637c9b109 100644 --- a/tests/by-util/test_tr.rs +++ b/tests/by-util/test_tr.rs @@ -45,6 +45,33 @@ fn test_delete_complement() { .stdout_is("ac"); } +#[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_squeeze() { new_ucmd!() From 34c22dc3ad359ebdd08ebbfcf6d3651c433de2df Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Sun, 2 May 2021 12:15:16 +0200 Subject: [PATCH 2/4] tr: fix complement if set2 is range --- src/uu/tr/src/tr.rs | 2 +- tests/by-util/test_tr.rs | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/uu/tr/src/tr.rs b/src/uu/tr/src/tr.rs index b1143b4bb..68543229e 100644 --- a/src/uu/tr/src/tr.rs +++ b/src/uu/tr/src/tr.rs @@ -149,7 +149,7 @@ impl TranslateOperation { TranslateOperation { translate_map: map, complement, - s2_last: s2_prev, + s2_last: set2.last().unwrap_or(s2_prev), } } } diff --git a/tests/by-util/test_tr.rs b/tests/by-util/test_tr.rs index 064fbf779..f840dee62 100644 --- a/tests/by-util/test_tr.rs +++ b/tests/by-util/test_tr.rs @@ -86,6 +86,26 @@ fn test_complement3() { .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] fn test_squeeze() { new_ucmd!() From 000bd73edceae756be09693d4f7db9ed5899210a Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Sun, 2 May 2021 12:39:25 +0200 Subject: [PATCH 3/4] tr: fix merge conflict --- src/uu/tr/src/tr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uu/tr/src/tr.rs b/src/uu/tr/src/tr.rs index 5e6c41a86..dcb64a127 100644 --- a/src/uu/tr/src/tr.rs +++ b/src/uu/tr/src/tr.rs @@ -182,7 +182,7 @@ impl TranslateAndSqueezeOperation { complement: bool, ) -> TranslateAndSqueezeOperation { TranslateAndSqueezeOperation { - translate: TranslateOperation::new(set1, set2, truncate), + translate: TranslateOperation::new(set1, set2, truncate, complement), squeeze: SqueezeOperation::new(set2_, complement), } } From acd30526a26ccfaf0a6860c913e552b1f7363729 Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Sun, 2 May 2021 13:53:11 +0200 Subject: [PATCH 4/4] tr: fix clippy warning --- src/uu/tr/src/tr.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/uu/tr/src/tr.rs b/src/uu/tr/src/tr.rs index dcb64a127..a44f2733c 100644 --- a/src/uu/tr/src/tr.rs +++ b/src/uu/tr/src/tr.rs @@ -217,8 +217,8 @@ fn translate_input( // Set `prev_c` to the post-translate character. This // allows the squeeze operation to correctly function // after the translate operation. - if res.is_some() { - prev_c = res.unwrap(); + if let Some(rc) = res { + prev_c = rc; } res });