diff options
author | Ryan Geary <rtgnj42@gmail.com> | 2019-10-13 21:40:59 -0400 |
---|---|---|
committer | Ryan Geary <rtgnj42@gmail.com> | 2019-10-13 21:40:59 -0400 |
commit | 0be16bf1d99af669497f7125d9e3eb6b8fb09fad (patch) | |
tree | a99a2f62b28501e2f2a91892b24f3565d70e4263 | |
parent | e7169ea2e817874f9a1f71d55906e04a71aec558 (diff) |
Add reverse ranges
-rw-r--r-- | src/choice.rs | 101 | ||||
-rwxr-xr-x | test/e2e_test.sh | 2 |
2 files changed, 86 insertions, 17 deletions
diff --git a/src/choice.rs b/src/choice.rs index 0b48a68..5ee25d1 100644 --- a/src/choice.rs +++ b/src/choice.rs @@ -21,6 +21,16 @@ impl Choice { write!(handle, "{}", self.get_choice_slice(line, config).join(" ")); } + pub fn is_reverse_range(&self) -> bool { + match self { + Choice::Field(_) => false, + Choice::FieldRange(r) => match r { + (Some(start), Some(end)) => end < start, + _ => false, + }, + } + } + fn get_choice_slice<'a>(&self, line: &'a String, config: &Config) -> Vec<&'a str> { let words = config .separator @@ -29,7 +39,7 @@ impl Choice { .filter(|s| !s.is_empty()) .enumerate(); - match self { + let mut slices = match self { Choice::Field(i) => words .filter(|x| x.0 == *i as usize) .map(|x| x.1) @@ -58,32 +68,45 @@ impl Choice { (*end).try_into().unwrap() }; words - .filter(|x| x.0 < e && x.0 >= (*start).try_into().unwrap()) + .filter(|x| { + (x.0 < e && x.0 >= (*start).try_into().unwrap()) + || self.is_reverse_range() + && (x.0 > e && x.0 <= (*start).try_into().unwrap()) + }) .map(|x| x.1) .collect::<Vec<&str>>() } }, - } + }; + + if self.is_reverse_range() { + slices.reverse(); } + + return slices; + +} } #[cfg(test)] mod tests { - mod get_choice_slice_tests { - use crate::config::{Config, Opt}; - use std::ffi::OsString; - use structopt::StructOpt; + use crate::config::{Config, Opt}; + use std::ffi::OsString; + use structopt::StructOpt; - impl Config { - pub fn from_iter<I>(iter: I) -> Self - where - I: IntoIterator, - I::Item: Into<OsString> + Clone, - { - return Config::new(Opt::from_iter(iter)); - } + impl Config { + pub fn from_iter<I>(iter: I) -> Self + where + I: IntoIterator, + I::Item: Into<OsString> + Clone, + { + return Config::new(Opt::from_iter(iter)); } + } + + mod get_choice_slice_tests { + use super::*; #[test] fn print_0() { @@ -194,7 +217,53 @@ mod tests { ); } + #[test] + fn print_3_to_1() { + let config = Config::from_iter(vec!["choose", "3:1"]); + assert_eq!( + vec!["pretty", "is"], + config.opt.choice[0].get_choice_slice( + &String::from("rust lang is pretty darn cool"), + &config + ) + ); + } + } -} + mod is_reverse_range_tests { + use super::*; + + #[test] + fn is_field_reversed() { + let config = Config::from_iter(vec!["choose", "0"]); + assert_eq!(false, config.opt.choice[0].is_reverse_range()); + } + + #[test] + fn is_field_range_no_start_reversed() { + let config = Config::from_iter(vec!["choose", ":2"]); + assert_eq!(false, config.opt.choice[0].is_reverse_range()); + } + + #[test] + fn is_field_range_no_end_reversed() { + let config = Config::from_iter(vec!["choose", "2:"]); + assert_eq!(false, config.opt.choice[0].is_reverse_range()); + } + + #[test] + fn is_field_range_no_start_or_end_reversed() { + let config = Config::from_iter(vec!["choose", ":"]); + assert_eq!(false, config.opt.choice[0].is_reverse_range()); + } + #[test] + fn is_reversed_field_range_reversed() { + let config = Config::from_iter(vec!["choose", "4:2"]); + assert_eq!(true, config.opt.choice[0].is_reverse_range()); + } + + } + +} diff --git a/test/e2e_test.sh b/test/e2e_test.sh index 01f54ec..a76b8a2 100755 --- a/test/e2e_test.sh +++ b/test/e2e_test.sh @@ -13,7 +13,7 @@ diff -w <(cargo run -- :2 -i ${test_dir}/lorem.txt) <(cat "${test_dir}/choose_:2 diff -w <(cargo run -- 9 3 -i ${test_dir}/lorem.txt) <(cat "${test_dir}/choose_9_3.txt") diff -w <(cargo run -- 9 -i ${test_dir}/lorem.txt) <(cat "${test_dir}/choose_9.txt") diff -w <(cargo run -- 12 -i ${test_dir}/lorem.txt) <(cat "${test_dir}/choose_12.txt") -# add test for reverse range +diff -w <(cargo run -- 4:1 -i ${test_dir}/lorem.txt) <(cat "${test_dir}/choose_4:1.txt") # add tests for different delimiters # add tests using piping |