diff options
author | Ryan Geary <rtgnj42@gmail.com> | 2020-04-04 18:05:32 -0400 |
---|---|---|
committer | Ryan Geary <rtgnj42@gmail.com> | 2020-04-04 18:09:37 -0400 |
commit | d40c9d5234e4388b6321f9bea2f4b43e748b59fd (patch) | |
tree | 6c69e03c165dff7e89b4ed825b96535af33e8ec4 | |
parent | 024edfc8f405fa2c08350d0caa492e68ad5b7005 (diff) |
Non-greedy String Splitting (#7)
* Add non_greedy flag
* Add non-greedy tests
* Prevent printing spaces for empty fields
* Prevent filtering non-empty fields when non-greedy
-rw-r--r-- | src/choice.rs | 67 | ||||
-rw-r--r-- | src/opt.rs | 4 |
2 files changed, 63 insertions, 8 deletions
diff --git a/src/choice.rs b/src/choice.rs index 63ddb2e..941f512 100644 --- a/src/choice.rs +++ b/src/choice.rs @@ -29,7 +29,10 @@ impl Choice { config: &Config, handle: &mut BufWriter<WriterType>, ) { - let mut line_iter = config.separator.split(line).filter(|s| !s.is_empty()); + let mut line_iter = config + .separator + .split(line) + .filter(|s| !s.is_empty() || config.opt.non_greedy); if self.is_reverse_range() && !self.has_negative_index() { if self.end > 0 { @@ -101,13 +104,18 @@ impl Choice { } fn write_bytes<WriterType: Write>(handle: &mut BufWriter<WriterType>, b: &[u8]) { - match handle.write(b) { - Ok(_) => (), - Err(e) => eprintln!("Failed to write to output: {}", e), - } - match handle.write(b" ") { - Ok(_) => (), - Err(e) => eprintln!("Failed to write to output: {}", e), + let num_bytes_written = match handle.write(b) { + Ok(x) => x, + Err(e) => { + eprintln!("Failed to write to output: {}", e); + 0 + } + }; + if num_bytes_written > 0 { + match handle.write(b" ") { + Ok(_) => (), + Err(e) => eprintln!("Failed to write to output: {}", e), + } } } @@ -513,6 +521,49 @@ mod tests { ); assert_eq!(String::from(""), MockStdout::str_from_buf_writer(handle)); } + + #[test] + fn print_0_to_2_greedy() { + let config = Config::from_iter(vec!["choose", "0:2", "-f", ":"]); + let mut handle = BufWriter::new(MockStdout::new()); + config.opt.choice[0].print_choice(&String::from("a:b::c:::d"), &config, &mut handle); + assert_eq!( + String::from("a b c"), + MockStdout::str_from_buf_writer(handle) + ); + } + + #[test] + fn print_0_to_2_non_greedy() { + let config = Config::from_iter(vec!["choose", "0:2", "-n", "-f", ":"]); + let mut handle = BufWriter::new(MockStdout::new()); + config.opt.choice[0].print_choice(&String::from("a:b::c:::d"), &config, &mut handle); + assert_eq!(String::from("a b"), MockStdout::str_from_buf_writer(handle)); + } + + #[test] + fn print_2_to_neg_1_non_greedy_negative() { + let config = Config::from_iter(vec!["choose", "2:-1", "-n", "-f", ":"]); + let mut handle = BufWriter::new(MockStdout::new()); + config.opt.choice[0].print_choice(&String::from("a:b::c:::d"), &config, &mut handle); + assert_eq!(String::from("c d"), MockStdout::str_from_buf_writer(handle)); + } + + #[test] + fn print_2_to_0_non_greedy_reversed() { + let config = Config::from_iter(vec!["choose", "2:0", "-n", "-f", ":"]); + let mut handle = BufWriter::new(MockStdout::new()); + config.opt.choice[0].print_choice(&String::from("a:b::c:::d"), &config, &mut handle); + assert_eq!(String::from("b a"), MockStdout::str_from_buf_writer(handle)); + } + + #[test] + fn print_neg_1_to_neg_3_non_greedy_negative_reversed() { + let config = Config::from_iter(vec!["choose", "-1:-3", "-n", "-f", ":"]); + let mut handle = BufWriter::new(MockStdout::new()); + config.opt.choice[0].print_choice(&String::from("a:b::c:::d"), &config, &mut handle); + assert_eq!(String::from("d"), MockStdout::str_from_buf_writer(handle)); + } } mod is_reverse_range_tests { @@ -12,6 +12,10 @@ pub struct Opt { #[structopt(short, long)] pub field_separator: Option<String>, + /// Use non-greedy field separators + #[structopt(short, long)] + pub non_greedy: bool, + /// Use exclusive ranges, similar to array indexing in many programming languages #[structopt(short = "x", long)] pub exclusive: bool, |