From d40c9d5234e4388b6321f9bea2f4b43e748b59fd Mon Sep 17 00:00:00 2001 From: Ryan Geary Date: Sat, 4 Apr 2020 18:05:32 -0400 Subject: 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 --- src/choice.rs | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++------- 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, ) { - 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(handle: &mut BufWriter, 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 { diff --git a/src/opt.rs b/src/opt.rs index 77fc710..4170fb7 100644 --- a/src/opt.rs +++ b/src/opt.rs @@ -12,6 +12,10 @@ pub struct Opt { #[structopt(short, long)] pub field_separator: Option, + /// 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, -- cgit v1.2.3