mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 11:37:44 +00:00
fixup! tr: implement translate and squeeze (-s) mode
This commit is contained in:
parent
0f3bc23739
commit
5674d09327
1 changed files with 42 additions and 47 deletions
|
@ -151,6 +151,35 @@ impl SymbolTranslator for TranslateOperation {
|
|||
}
|
||||
}
|
||||
|
||||
struct TranslateAndSqueezeOperation {
|
||||
translate: TranslateOperation,
|
||||
squeeze: SqueezeOperation,
|
||||
}
|
||||
|
||||
impl TranslateAndSqueezeOperation {
|
||||
fn new(
|
||||
set1: ExpandSet,
|
||||
set2: &mut ExpandSet,
|
||||
set2_: ExpandSet,
|
||||
truncate: bool,
|
||||
complement: bool,
|
||||
) -> TranslateAndSqueezeOperation {
|
||||
TranslateAndSqueezeOperation {
|
||||
translate: TranslateOperation::new(set1, set2, truncate),
|
||||
squeeze: SqueezeOperation::new(set2_, complement),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SymbolTranslator for TranslateAndSqueezeOperation {
|
||||
fn translate(&self, c: char, prev_c: char) -> Option<char> {
|
||||
// `unwrap()` will never panic because `Translate.translate()`
|
||||
// always returns `Some`.
|
||||
self.squeeze
|
||||
.translate(self.translate.translate(c, 0 as char).unwrap(), prev_c)
|
||||
}
|
||||
}
|
||||
|
||||
fn translate_input<T: SymbolTranslator>(
|
||||
input: &mut dyn BufRead,
|
||||
output: &mut dyn Write,
|
||||
|
@ -168,8 +197,11 @@ fn translate_input<T: SymbolTranslator>(
|
|||
// isolation to make borrow checker happy
|
||||
let filtered = buf.chars().filter_map(|c| {
|
||||
let res = translator.translate(c, prev_c);
|
||||
// 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 = c;
|
||||
prev_c = res.unwrap();
|
||||
}
|
||||
res
|
||||
});
|
||||
|
@ -282,53 +314,16 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
|||
let op = SqueezeOperation::new(set1, complement_flag);
|
||||
translate_input(&mut locked_stdin, &mut buffered_stdout, op);
|
||||
} else {
|
||||
// Define a closure that computes the translation using a hash map.
|
||||
//
|
||||
// The `unwrap()` should never panic because the
|
||||
// `TranslateOperation.translate()` method always returns
|
||||
// `Some`.
|
||||
let mut set2 = ExpandSet::new(sets[1].as_ref());
|
||||
let translator = TranslateOperation::new(set1, &mut set2, truncate_flag);
|
||||
let translate = |c| translator.translate(c, 0 as char).unwrap();
|
||||
|
||||
// Prepare some variables to be used for the closure that
|
||||
// computes the squeeze operation.
|
||||
//
|
||||
// The `squeeze()` closure needs to be defined anew for
|
||||
// each line of input, but these variables do not change
|
||||
// while reading the input so they can be defined before
|
||||
// the `while` loop.
|
||||
let set2 = ExpandSet::new(sets[1].as_ref());
|
||||
let squeezer = SqueezeOperation::new(set2, complement_flag);
|
||||
|
||||
// Prepare some memory to read each line of the input (`buf`) and to write
|
||||
let mut buf = String::with_capacity(BUFFER_LEN + 4);
|
||||
|
||||
// Loop over each line of stdin.
|
||||
while let Ok(length) = locked_stdin.read_line(&mut buf) {
|
||||
if length == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
// Define a closure that computes the squeeze operation.
|
||||
//
|
||||
// We keep track of the previously seen character on
|
||||
// each call to `squeeze()`, but we need to reset the
|
||||
// `prev_c` variable at the beginning of each line of
|
||||
// the input. That's why we define the closure inside
|
||||
// the `while` loop.
|
||||
let mut prev_c = 0 as char;
|
||||
let squeeze = |c| {
|
||||
let result = squeezer.translate(c, prev_c);
|
||||
prev_c = c;
|
||||
result
|
||||
};
|
||||
|
||||
// First translate, then squeeze each character of the input line.
|
||||
let filtered: String = buf.chars().map(translate).filter_map(squeeze).collect();
|
||||
buf.clear();
|
||||
buffered_stdout.write_all(filtered.as_bytes()).unwrap();
|
||||
}
|
||||
let set2_ = ExpandSet::new(sets[1].as_ref());
|
||||
let op = TranslateAndSqueezeOperation::new(
|
||||
set1,
|
||||
&mut set2,
|
||||
set2_,
|
||||
complement_flag,
|
||||
truncate_flag,
|
||||
);
|
||||
translate_input(&mut locked_stdin, &mut buffered_stdout, op);
|
||||
}
|
||||
} else {
|
||||
let mut set2 = ExpandSet::new(sets[1].as_ref());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue