diff options
-rw-r--r-- | readme.md | 10 | ||||
-rw-r--r-- | src/choice.rs | 949 | ||||
-rw-r--r-- | src/config.rs | 141 | ||||
-rw-r--r-- | src/errors.rs | 23 | ||||
-rw-r--r-- | src/main.rs | 5 | ||||
-rw-r--r-- | src/opt.rs | 15 | ||||
-rw-r--r-- | src/parse.rs | 270 | ||||
-rw-r--r-- | src/parse_error.rs | 14 |
8 files changed, 965 insertions, 462 deletions
@@ -43,11 +43,11 @@ Please see our guidelines in [contributing.md](contributing.md). ``` $ choose --help -choose 1.1.1 +choose 1.1.2 `choose` sections from each line of files USAGE: - choose [FLAGS] [OPTIONS] <choice>... + choose [FLAGS] [OPTIONS] <choices>... FLAGS: -c, --character-wise Choose fields by character number @@ -65,8 +65,10 @@ OPTIONS: -o, --output-field-separator <output-field-separator> Specify output field separator ARGS: - <choice>... Fields to print. Either x, x:, :y, or x:y, where x and y are integers, colons indicate a range, - and an empty field on either side of the colon continues to the beginning or end of the line. + <choices>... Fields to print. Either a, a:b, a..b, or a..=b, where a and b are integers. The beginning or end + of a range can be omitted, resulting in including the beginning or end of the line, + respectively. a:b is inclusive of b (unless overridden by -x). a..b is exclusive of b and a..=b + is inclusive of b ``` ### Examples diff --git a/src/choice.rs b/src/choice.rs index bf193f6..a2ce12a 100644 --- a/src/choice.rs +++ b/src/choice.rs @@ -10,17 +10,27 @@ use crate::writer::WriteReceiver; pub struct Choice { pub start: isize, pub end: isize, + pub kind: ChoiceKind, negative_index: bool, reversed: bool, } +#[derive(Debug, PartialEq)] +pub enum ChoiceKind { + Single, + RustExclusiveRange, + RustInclusiveRange, + ColonRange, +} + impl Choice { - pub fn new(start: isize, end: isize) -> Self { + pub fn new(start: isize, end: isize, kind: ChoiceKind) -> Self { let negative_index = start < 0 || end < 0; - let reversed = end < start; + let reversed = end < start && !(start >= 0 && end < 0); Choice { start, end, + kind, negative_index, reversed, } @@ -236,35 +246,26 @@ mod tests { mod print_choice_tests { use super::*; - #[test] - fn print_0() { - let config = Config::from_iter(vec!["choose", "0"]); + fn test_fn(vec: Vec<&str>, input: &str, output: &str) { + let config = Config::from_iter(vec); let mut handle = BufWriter::new(MockStdout::new()); - config.opt.choice[0].print_choice( - &String::from("rust is pretty cool"), - &config, - &mut handle, - ); + config.opt.choices[0].print_choice(&String::from(input), &config, &mut handle); assert_eq!( - String::from("rust"), + String::from(output), MockStdout::str_from_buf_writer(handle) ); } #[test] - fn print_after_end() { - let config = Config::from_iter(vec!["choose", "10"]); - let mut handle = BufWriter::new(MockStdout::new()); - - config.opt.choice[0].print_choice( - &String::from("rust is pretty cool"), - &config, - &mut handle, - ); + fn print_0() { + test_fn(vec!["choose", "0"], "rust is pretty cool", "rust"); + } - assert_eq!(String::new(), MockStdout::str_from_buf_writer(handle)); + #[test] + fn print_after_end() { + test_fn(vec!["choose", "10"], "rust is pretty cool", ""); } #[test] @@ -273,7 +274,7 @@ mod tests { let mut handle = BufWriter::new(MockStdout::new()); let mut handle1 = BufWriter::new(MockStdout::new()); - config.opt.choice[0].print_choice( + config.opt.choices[0].print_choice( &String::from("rust is pretty cool"), &config, &mut handle, @@ -284,7 +285,7 @@ mod tests { MockStdout::str_from_buf_writer(handle) ); - config.opt.choice[1].print_choice( + config.opt.choices[1].print_choice( &String::from("rust is pretty cool"), &config, &mut handle1, @@ -295,460 +296,780 @@ mod tests { #[test] fn print_1_to_3_exclusive() { - let config = Config::from_iter(vec!["choose", "1:3", "-x"]); - let mut handle = BufWriter::new(MockStdout::new()); - config.opt.choice[0].print_choice( - &String::from("rust is pretty cool"), - &config, - &mut handle, - ); - assert_eq!( - String::from("is pretty"), - MockStdout::str_from_buf_writer(handle) + test_fn( + vec!["choose", "1:3", "-x"], + "rust is pretty cool", + "is pretty", ); } #[test] fn print_1_to_3() { - let config = Config::from_iter(vec!["choose", "1:3"]); - let mut handle = BufWriter::new(MockStdout::new()); - config.opt.choice[0].print_choice( - &String::from("rust is pretty cool"), - &config, - &mut handle, - ); - assert_eq!( - String::from("is pretty cool"), - MockStdout::str_from_buf_writer(handle) + test_fn( + vec!["choose", "1:3"], + "rust is pretty cool", + "is pretty cool", ); } #[test] fn print_1_to_3_separated_by_hashtag() { - let config = Config::from_iter(vec!["choose", "1:3", "-f", "#"]); - let mut handle = BufWriter::new(MockStdout::new()); - config.opt.choice[0].print_choice( - &String::from("rust#is#pretty#cool"), - &config, - &mut handle, - ); - assert_eq!( - String::from("is pretty cool"), - MockStdout::str_from_buf_writer(handle) + test_fn( + vec!["choose", "1:3", "-f", "#"], + "rust#is#pretty#cool", + "is pretty cool", ); } #[test] fn print_1_to_3_separated_by_varying_multiple_hashtag_exclusive() { - let config = Config::from_iter(vec!["choose", "1:3", "-f", "#", "-x"]); - let mut handle = BufWriter::new(MockStdout::new()); - config.opt.choice[0].print_choice( - &String::from("rust##is###pretty####cool"), - &config, - &mut handle, - ); - assert_eq!( - String::from("is pretty"), - MockStdout::str_from_buf_writer(handle) + test_fn( + vec!["choose", "1:3", "-f", "#", "-x"], + "rust##is###pretty####cool", + "is pretty", ); } #[test] fn print_1_to_3_separated_by_varying_multiple_hashtag() { - let config = Config::from_iter(vec!["choose", "1:3", "-f", "#"]); - let mut handle = BufWriter::new(MockStdout::new()); - config.opt.choice[0].print_choice( - &String::from("rust##is###pretty####cool"), - &config, - &mut handle, - ); - assert_eq!( - String::from("is pretty cool"), - MockStdout::str_from_buf_writer(handle) + test_fn( + vec!["choose", "1:3", "-f", "#"], + "rust##is###pretty####cool", + "is pretty cool", ); } #[test] fn print_1_to_3_separated_by_regex_group_vowels_exclusive() { - let config = Config::from_iter(vec!["choose", "1:3", "-f", "[aeiou]", "-x"]); - let mut handle = BufWriter::new(MockStdout::new()); - config.opt.choice[0].print_choice( - &String::from("the quick brown fox jumped over the lazy dog"), - &config, - &mut handle, - ); - assert_eq!( - String::from(" q ck br"), - MockStdout::str_from_buf_writer(handle) + test_fn( + vec!["choose", "1:3", "-f", "[aeiou]", "-x"], + "the quick brown fox jumped over the lazy dog", + " q ck br", ); } #[test] fn print_1_to_3_separated_by_regex_group_vowels() { - let config = Config::from_iter(vec!["choose", "1:3", "-f", "[aeiou]"]); - let mut handle = BufWriter::new(MockStdout::new()); - config.opt.choice[0].print_choice( - &String::from("the quick brown fox jumped over the lazy dog"), - &config, - &mut handle, - ); - assert_eq!( - String::from(" q ck br wn f"), - MockStdout::str_from_buf_writer(handle) + test_fn( + vec!["choose", "1:3", "-f", "[aeiou]"], + "the quick brown fox jumped over the lazy dog", + " q ck br wn f", ); } #[test] fn print_3_to_1() { - let config = Config::from_iter(vec!["choose", "3:1"]); - let mut handle = BufWriter::new(MockStdout::new()); - config.opt.choice[0].print_choice( - &String::from("rust lang is pretty darn cool"), - &config, - &mut handle, - ); - assert_eq!( - String::from("pretty is lang"), - MockStdout::str_from_buf_writer(handle) + test_fn( + vec!["choose", "3:1"], + "rust lang is pretty darn cool", + "pretty is lang", ); } #[test] fn print_3_to_1_exclusive() { - let config = Config::from_iter(vec!["choose", "3:1", "-x"]); - let mut handle = BufWriter::new(MockStdout::new()); - config.opt.choice[0].print_choice( - &String::from("rust lang is pretty darn cool"), - &config, - &mut handle, - ); - assert_eq!( - String::from("is lang"), - MockStdout::str_from_buf_writer(handle) + test_fn( + vec!["choose", "3:1", "-x"], + "rust lang is pretty darn cool", + "is lang", ); } #[test] fn print_1_to_3_nonexistant_field_separator() { - let config = Config::from_iter(vec!["choose", "1:3", "-f", "#"]); - let mut handle = BufWriter::new(MockStdout::new()); - config.opt.choice[0].print_choice( - &String::from("rust lang is pretty darn cool"), - &config, - &mut handle, + test_fn( + vec!["choose", "1:3", "-f", "#"], + "rust lang is pretty darn cool", + "", ); - assert_eq!(String::from(""), MockStdout::str_from_buf_writer(handle)); } #[test] fn print_0_nonexistant_field_separator() { - let config = Config::from_iter(vec!["choose", "0", "-f", "#"]); - let mut handle = BufWriter::new(MockStdout::new()); - config.opt.choice[0].print_choice( - &String::from("rust lang is pretty darn cool"), - &config, - &mut handle, - ); - assert_eq!( - String::from("rust lang is pretty darn cool"), - MockStdout::str_from_buf_writer(handle) + test_fn( + vec!["choose", "0", "-f", "#"], + "rust lang is pretty darn cool", + "rust lang is pretty darn cool", ); } #[test] fn print_0_to_3_nonexistant_field_separator() { - let config = Config::from_iter(vec!["choose", "0:3", "-f", "#"]); - let mut handle = BufWriter::new(MockStdout::new()); - config.opt.choice[0].print_choice( - &String::from("rust lang is pretty darn cool"), - &config, - &mut handle, - ); - assert_eq!( - String::from("rust lang is pretty darn cool"), - MockStdout::str_from_buf_writer(handle) + test_fn( + vec!["choose", "0:3", "-f", "#"], + "rust lang is pretty darn cool", + "rust lang is pretty darn cool", ); } #[test] fn print_0_with_preceding_separator() { - let config = Config::from_iter(vec!["choose", "0"]); - let mut handle = BufWriter::new(MockStdout::new()); - config.opt.choice[0].print_choice( - &String::from(" rust lang is pretty darn cool"), - &config, - &mut handle, - ); - assert_eq!( - String::from("rust"), - MockStdout::str_from_buf_writer(handle) + test_fn( + vec!["choose", "0"], + " rust lang is pretty darn cool", + "rust", ); } #[test] fn print_neg3_to_neg1() { - let config = Config::from_iter(vec!["choose", "-3:-1"]); - let mut handle = BufWriter::new(MockStdout::new()); - config.opt.choice[0].print_choice( - &String::from("rust lang is pretty darn cool"), - &config, - &mut handle, - ); - assert_eq!( - String::from("pretty darn cool"), - MockStdout::str_from_buf_writer(handle) + test_fn( + vec!["choose", "-3:-1"], + "rust lang is pretty darn cool", + "pretty darn cool", ); } #[test] fn print_neg1_to_neg3() { - let config = Config::from_iter(vec!["choose", "-1:-3"]); - let mut handle = BufWriter::new(MockStdout::new()); - config.opt.choice[0].print_choice( - &String::from("rust lang is pretty darn cool"), - &config, - &mut handle, - ); - assert_eq!( - String::from("cool darn pretty"), - MockStdout::str_from_buf_writer(handle) + test_fn( + vec!["choose", "-1:-3"], + "rust lang is pretty darn cool", + "cool darn pretty", ); } #[test] fn print_neg2_to_end() { - let config = Config::from_iter(vec!["choose", "-2:"]); - let mut handle = BufWriter::new(MockStdout::new()); - config.opt.choice[0].print_choice( - &String::from("rust lang is pretty darn cool"), - &config, - &mut handle, - ); - assert_eq!( - String::from("darn cool"), - MockStdout::str_from_buf_writer(handle) + test_fn( + vec!["choose", "-2:"], + "rust lang is pretty darn cool", + "darn cool", ); } #[test] fn print_start_to_neg3() { - let config = Config::from_iter(vec!["choose", ":-3"]); - let mut handle = BufWriter::new(MockStdout::new()); - config.opt.choice[0].print_choice( - &String::from("rust lang is pretty darn cool"), - &config, - &mut handle, - ); - assert_eq!( - String::from("rust lang is pretty"), - MockStdout::str_from_buf_writer(handle) + test_fn( + vec!["choose", ":-3"], + "rust lang is pretty darn cool", + "rust lang is pretty", ); } #[test] fn print_1_to_neg3() { - let config = Config::from_iter(vec!["choose", "1:-3"]); - let mut handle = BufWriter::new(MockStdout::new()); - config.opt.choice[0].print_choice( - &String::from("rust lang is pretty darn cool"), - &config, - &mut handle, - ); - assert_eq!( - String::from("lang is pretty"), - MockStdout::str_from_buf_writer(handle) + test_fn( + vec!["choose", "1:-3"], + "rust lang is pretty darn cool", + "lang is pretty", ); } #[test] fn print_5_to_neg3_empty() { - let config = Config::from_iter(vec!["choose", "5:-3"]); - let mut handle = BufWriter::new(MockStdout::new()); - config.opt.choice[0].print_choice( - &String::from("rust lang is pretty darn cool"), - &config, - &mut handle, - ); - assert_eq!(String::from(""), MockStdout::str_from_buf_writer(handle)); + test_fn(vec!["choose", "5:-3"], "rust lang is pretty darn cool", ""); } #[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(vec!["choose", "0:2", "-f", ":"], "a:b::c:::d", "a b c"); } #[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(vec!["choose", "0:2", "-n", "-f", ":"], "a:b::c:::d", "a b"); } #[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(vec!["choose", "2:-1", "-n", "-f", ":"], "a:b::c:::d", "c d"); } #[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(vec!["choose", "2:0", "-n", "-f", ":"], "a:b::c:::d", "b a"); } #[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)); + test_fn(vec!["choose", "-1:-3", "-n", "-f", ":"], "a:b::c:::d", "d"); } #[test] fn print_1_to_3_with_output_field_separator() { - let config = Config::from_iter(vec!["choose", "1:3", "-o", "#"]); - 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#c#d"), - MockStdout::str_from_buf_writer(handle) - ); + test_fn(vec!["choose", "1:3", "-o", "#"], "a b c d", "b#c#d"); } #[test] fn print_1_and_3_with_output_field_separator() { - let config = Config::from_iter(vec!["choose", "1", "3", "-o", "#"]); - let mut handle = BufWriter::new(MockStdout::new()); - config.opt.choice[0].print_choice(&String::from("a b c d"), &config, &mut handle); - handle.write(&config.output_separator).unwrap(); - config.opt.choice[1].print_choice(&String::from("a b c d"), &config, &mut handle); - assert_eq!(String::from("b#d"), MockStdout::str_from_buf_writer(handle)); + test_fn(vec!["choose", "1", "3", "-o", "#"], "a b c d", "b"); } #[test] fn print_2_to_4_with_output_field_separator() { - let config = Config::from_iter(vec!["choose", "2:4", "-o", "%"]); - let mut handle = BufWriter::new(MockStdout::new()); - config.opt.choice[0].print_choice( - &String::from("Lorem ipsum dolor sit amet, consectetur"), - &config, - &mut handle, - ); - assert_eq!( - String::from("dolor%sit%amet,"), - MockStdout::str_from_buf_writer(handle) + test_fn( + vec!["choose", "2:4", "-o", "%"], + "Lorem ipsum dolor sit amet, consectetur", + "dolor%sit%amet,", ); } #[test] fn print_3_to_1_with_output_field_separator() { - let config = Config::from_iter(vec!["choose", "3:1", "-o", "#"]); - 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#c#b"), - MockStdout::str_from_buf_writer(handle) - ); + test_fn(vec!["choose", "3:1", "-o", "#"], "a b c d", "d#c#b"); } #[test] fn print_0_to_neg_2_with_output_field_separator() { - let config = Config::from_iter(vec!["choose", "0:-2", "-o", "#"]); - 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(vec!["choose", "0:-2", "-o", "#"], "a b c d", "a#b#c"); } #[test] fn print_0_to_2_with_empty_output_field_separator() { - let config = Config::from_iter(vec!["choose", "0:2", "-o", ""]); - 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("abc"), MockStdout::str_from_buf_writer(handle)); + test_fn(vec!["choose", "0:2", "-o", ""], "a b c d", "abc"); } #[test] fn print_0_to_2_character_wise() { - let config = Config::from_iter(vec!["choose", "0:2", "-c"]); - let mut handle = BufWriter::new(MockStdout::new()); - config.opt.choice[0].print_choice(&String::from("abcd\n"), &config, &mut handle); - assert_eq!(String::from("abc"), MockStdout::str_from_buf_writer(handle)); + test_fn(vec!["choose", "0:2", "-c"], "abcd\n", "abc"); } #[test] fn print_2_to_end_character_wise() { - let config = Config::from_iter(vec!["choose", "2:", "-c"]); - let mut handle = BufWriter::new(MockStdout::new()); - config.opt.choice[0].print_choice(&String::from("abcd\n"), &config, &mut handle); - assert_eq!(String::from("cd"), MockStdout::str_from_buf_writer(handle)); + test_fn(vec!["choose", "2:", "-c"], "abcd\n", "cd"); } #[test] fn print_start_to_2_character_wise() { - let config = Config::from_iter(vec!["choose", ":2", "-c"]); - let mut handle = BufWriter::new(MockStdout::new()); - config.opt.choice[0].print_choice(&String::from("abcd\n"), &config, &mut handle); - assert_eq!(String::from("abc"), MockStdout::str_from_buf_writer(handle)); + test_fn(vec!["choose", ":2", "-c"], "abcd\n", "abc"); } #[test] fn print_0_to_2_character_wise_exclusive() { - let config = Config::from_iter(vec!["choose", "0:2", "-c", "-x"]); - let mut handle = BufWriter::new(MockStdout::new()); - config.opt.choice[0].print_choice(&String::from("abcd\n"), &config, &mut handle); - assert_eq!(String::from("ab"), MockStdout::str_from_buf_writer(handle)); + test_fn(vec!["choose", "0:2", "-c", "-x"], "abcd\n", "ab"); } #[test] fn print_0_to_2_character_wise_with_output_delimeter() { - let config = Config::from_iter(vec!["choose", "0:2", "-c", "-o", ":"]); - let mut handle = BufWriter::new(MockStdout::new()); - config.opt.choice[0].print_choice(&String::from("abcd\n"), &config, &mut handle); - assert_eq!( - String::from("a:b:c"), - MockStdout::str_from_buf_writer(handle) - ); + test_fn(vec!["choose", "0:2", "-c", "-o", ":"], "abcd\n", "a:b:c"); } #[test] fn print_after_end_character_wise() { - let config = Config::from_iter(vec!["choose", "0:9", "-c"]); - let mut handle = BufWriter::new(MockStdout::new()); - config.opt.choice[0].print_choice(&String::from("abcd\n"), &config, &mut handle); - assert_eq!( - String::from("abcd"), - MockStdout::str_from_buf_writer(handle) - ); + test_fn(vec!["choose", "0:9", "-c"], "abcd\n", "abcd"); } #[test] fn print_2_to_0_character_wise() { - let config = Config::from_iter(vec!["choose", "2:0", "-c"]); - let mut handle = BufWriter::new(MockStdout::new()); - config.opt.choice[0].print_choice(&String::from("abcd\n"), &config, &mut handle); - assert_eq!(String::from("cba"), MockStdout::str_from_buf_writer(handle)); + test_fn(vec!["choose", "2:0", "-c"], "abcd\n", "cba"); } #[test] fn print_neg_2_to_end_character_wise() { - let config = Config::from_iter(vec!["choose", "-2:", "-c"]); + test_fn(vec!["choose", "-2:", "-c"], "abcd\n", "cd"); + } + + #[test] + fn print_1_to_3_exclusive_rust_syntax_inclusive() { + test_fn( + vec!["choose", "1..=3", "-x"], + "rust is pretty cool", + "is pretty cool", + ); + } + + #[test] + fn print_1_to_3_rust_syntax_inclusive() { + test_fn( + vec!["choose", "1..=3"], + "rust is pretty cool", + "is pretty cool", + ); + } + + #[test] + fn print_1_to_3_separated_by_hashtag_rust_syntax_inclusive() { + test_fn( + vec!["choose", "1..=3", "-f", "#"], + "rust#is#pretty#cool", + "is pretty cool", + ); + } + + #[test] + fn print_1_to_3_separated_by_varying_multiple_hashtag_exclusive_rust_syntax_inclusive() { + test_fn( + vec!["choose", "1..=3", "-f", "#", "-x"], + "rust##is###pretty####cool", + "is pretty cool", + ); + } + + #[test] + fn print_1_to_3_separated_by_varying_multiple_hashtag_rust_syntax_inclusive() { + test_fn( + vec!["choose", "1..=3", "-f", "#"], + "rust##is###pretty####cool", + "is pretty cool", + ); + } + + #[test] + fn print_1_to_3_separated_by_regex_group_vowels_exclusive_rust_syntax_inclusive() { + test_fn( + vec!["choose", "1..=3", "-f", "[aeiou]", "-x"], + "the quick brown fox jumped over the lazy dog", + " q ck br wn f", + ); + } + + #[test] + fn print_1_to_3_separated_by_regex_group_vowels_rust_syntax_inclusive() { + test_fn( + vec!["choose", "1..=3", "-f", "[aeiou]"], + "the quick brown fox jumped over the lazy dog", + " q ck br wn f", + ); + } + + #[test] + fn print_3_to_1_rust_syntax_inclusive() { + test_fn( + vec!["choose", "3..=1"], + "rust lang is pretty darn cool", + "pretty is lang", + ); + } + + #[test] + fn print_3_to_1_exclusive_rust_syntax_inclusive() { + test_fn( + vec!["choose", "3..=1", "-x"], + "rust lang is pretty darn cool", + "pretty is lang", + ); + } + + #[test] + fn print_1_to_3_nonexistant_field_separator_rust_syntax_inclusive() { + test_fn( + vec!["choose", "1..=3", "-f", "#"], + "rust lang is pretty darn cool", + "", + ); + } + + #[test] + fn print_0_to_3_nonexistant_field_separator_rust_syntax_inclusive() { + test_fn( + vec!["choose", "0..=3", "-f", "#"], + "rust lang is pretty darn cool", + "rust lang is pretty darn cool", + ); + } + + #[test] + fn print_neg1_to_neg1_rust_syntax_inclusive() { + test_fn( + vec!["choose", "-3..=-1"], + "rust lang is pretty darn cool", + "pretty darn cool", + ); + } + + #[test] + fn print_neg1_to_neg3_rust_syntax_inclusive() { + test_fn( + vec!["choose", "-1..=-3"], + "rust lang is pretty darn cool", + "cool darn pretty", + ); + } + + #[test] + fn print_neg2_to_end_rust_syntax_inclusive() { + test_fn( + vec!["choose", "-2..="], + "rust lang is pretty darn cool", + "darn cool", + ); + } + + #[test] + fn print_start_to_neg3_rust_syntax_inclusive() { + test_fn( + vec!["choose", "..=-3"], + "rust lang is pretty darn cool", + "rust lang is pretty", + ); + } + + #[test] + fn print_1_to_neg3_rust_syntax_inclusive() { + test_fn( + vec!["choose", "1..=-3"], + "rust lang is pretty darn cool", + "lang is pretty", + ); + } + + #[test] + fn print_5_to_neg3_empty_rust_syntax_inclusive() { + test_fn( + vec!["choose", "5..=-3"], + "rust lang is pretty darn cool", + "", + ); + } + + #[test] + fn print_0_to_2_greedy_rust_syntax_inclusive() { + test_fn(vec!["choose", "0..=2", "-f", ":"], "a:b::c:::d", "a b c"); + } + + #[test] + fn print_0_to_2_non_greedy_rust_syntax_inclusive() { + test_fn( + vec!["choose", "0..=2", "-n", "-f", ":"], + "a:b::c:::d", + "a b", + ); + } + + #[test] + fn print_2_to_neg_1_non_greedy_negative_rust_syntax_inclusive() { + test_fn( + vec!["choose", "2..=-1", "-n", "-f", ":"], + "a:b::c:::d", + "c d", + ); + } + + #[test] + fn print_2_to_0_non_greedy_reversed_rust_syntax_inclusive() { + test_fn( + vec!["choose", "2..=0", "-n", "-f", ":"], + "a:b::c:::d", + "b a", + ); + } + + #[test] + fn print_neg_1_to_neg_3_non_greedy_negative_reversed_rust_syntax_inclusive() { + test_fn( + vec!["choose", "-1..=-3", "-n", "-f", ":"], + "a:b::c:::d", + "d", + ); + } + + #[test] + fn print_1_to_3_with_output_field_separator_rust_syntax_inclusive() { + test_fn(vec!["choose", "1..=3", "-o", "#"], "a b c d", "b#c#d"); + } + + #[test] + fn print_1_and_3_with_output_field_separator_rust_syntax_inclusive() { + let config = Config::from_iter(vec!["choose", "1", "3", "-o", "#"]); let mut handle = BufWriter::new(MockStdout::new()); - config.opt.choice[0].print_choice(&String::from("abcd\n"), &config, &mut handle); - assert_eq!(String::from("cd"), MockStdout::str_from_buf_writer(handle)); + config.opt.choices[0].print_choice(&String::from("a b c d"), &config, &mut handle); + handle.write(&config.output_separator).unwrap(); + config.opt.choices[1].print_choice(&String::from("a b c d"), &config, &mut handle); + assert_eq!(String::from("b#d"), MockStdout::str_from_buf_writer(handle)); + } + + #[test] + fn print_2_to_4_with_output_field_separator_rust_syntax_inclusive() { + test_fn( + vec!["choose", "2..=4", "-o", "%"], + "Lorem ipsum dolor sit amet, consectetur", + "dolor%sit%amet,", + ); + } + + #[test] + fn print_3_to_1_with_output_field_separator_rust_syntax_inclusive() { + test_fn(vec!["choose", "3..=1", "-o", "#"], "a b c d", "d#c#b"); + } + + #[test] + fn print_0_to_neg_2_with_output_field_separator_rust_syntax_inclusive() { + test_fn(vec!["choose", "0..=-2", "-o", "#"], "a b c d", "a#b#c"); + } + + #[test] + fn print_0_to_2_with_empty_output_field_separator_rust_syntax_inclusive() { + test_fn(vec!["choose", "0..=2", "-o", ""], "a b c d", "abc"); + } + + #[test] + fn print_0_to_2_character_wise_rust_syntax_inclusive() { + test_fn(vec!["choose", "0..=2", "-c"], "abcd\n", "abc"); + } + + #[test] + fn print_2_to_end_character_wise_rust_syntax_inclusive() { + test_fn(vec!["choose", "2..=", "-c"], "abcd\n", "cd"); + } + + #[test] + fn print_start_to_2_character_wise_rust_syntax_inclusive() { + test_fn(vec!["choose", "..=2", "-c"], "abcd\n", "abc"); + } + + #[test] + fn print_0_to_2_character_wise_exclusive_rust_syntax_inclusive() { + test_fn(vec!["choose", "0..=2", "-c", "-x"], "abcd\n", "abc"); |