diff --git a/src/main.rs b/src/main.rs index d4057ec..582071b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -34,6 +34,10 @@ fn app_args<'a> () -> clap::ArgMatches<'a> { .help("Reverse the order for assigned hints") .long("reverse") .short("r")) + .arg(Arg::with_name("unique") + .help("Don't show duplicated hints for the same match") + .long("unique") + .short("u")) .arg(Arg::with_name("excluded") .help("Excluded keys from the alphabet") .long("excluded") @@ -46,6 +50,7 @@ fn main() { let args = app_args(); let alphabet = args.value_of("alphabet").unwrap_or("querty"); let reverse = args.is_present("reverse"); + let unique = args.is_present("unique"); let execution = exec_command(format!("tmux capture-pane -e -J -p")); let output = String::from_utf8_lossy(&execution.stdout); @@ -70,7 +75,7 @@ fn main() { } let mut typed_hint: String = "".to_owned(); - let matches = state.matches(reverse); + let matches = state.matches(reverse, unique); let longest_hint = matches.last().unwrap().hint.clone().unwrap().len(); loop { diff --git a/src/state.rs b/src/state.rs index 1aec3b2..bb2177d 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use regex::Regex; pub struct Match<'a> { @@ -28,7 +29,7 @@ impl<'a> State<'a> { } } - pub fn matches(&self, reverse: bool) -> Vec> { + pub fn matches(&self, reverse: bool, unique: bool) -> Vec> { let mut matches = Vec::new(); let mut patterns = Vec::new(); @@ -67,13 +68,27 @@ impl<'a> State<'a> { let alphabet = super::alphabets::get_alphabet(self.alphabet); let mut hints = alphabet.hints(matches.len()); - if reverse { + // This looks wrong but we do a pop after + if !reverse { hints.reverse(); } - for mat in &mut matches { - if let Some(hint) = hints.pop() { - mat.hint = Some(hint.to_string().clone()) + if unique { + let mut previous: HashMap<&str, String> = HashMap::new(); + + for mat in &mut matches { + if let Some(previous_hint) = previous.get(mat.text) { + mat.hint = Some(previous_hint.clone()); + } else if let Some(hint) = hints.pop() { + mat.hint = Some(hint.to_string().clone()); + previous.insert(mat.text, hint.to_string().clone()); + } + } + } else { + for mat in &mut matches { + if let Some(hint) = hints.pop() { + mat.hint = Some(hint.to_string().clone()); + } } } @@ -95,18 +110,44 @@ impl<'a> State<'a> { mod tests { use super::*; - fn match_lines(output: &str) -> Vec { + fn match_lines_flags(output: &str, reverse: bool, unique: bool) -> Vec { let lines = output.split("\n").collect::>(); let state = State::new(lines, "abcd"); - state.matches() + state.matches(reverse, unique) + } + + fn match_lines(output: &str) -> Vec { + match_lines_flags(output, false, false) + } + + #[test] + fn match_reverse () { + let output = "lorem 127.0.0.1 lorem 255.255.255.255 lorem 127.0.0.1 lorem"; + + let results = match_lines_flags(output, false, false); + + assert_eq!(results.len(), 3); + assert_eq!(results.first().unwrap().hint.clone().unwrap(), "a"); + assert_eq!(results.last().unwrap().hint.clone().unwrap(), "c"); + } + + #[test] + fn match_unique () { + let output = "lorem 127.0.0.1 lorem 255.255.255.255 lorem 127.0.0.1 lorem"; + + let results = match_lines_flags(output, false, true); + + assert_eq!(results.len(), 3); + assert_eq!(results.first().unwrap().hint.clone().unwrap(), "a"); + assert_eq!(results.last().unwrap().hint.clone().unwrap(), "a"); } #[test] fn match_paths () { let output = "Lorem /tmp/foo/bar lorem\n Lorem /var/log/bootstrap.log lorem /var/log/kern.log lorem"; - assert_ne!(match_lines(output).len(), 2); // FIXME regex priority + assert_eq!(match_lines(output).len(), 3); } #[test] diff --git a/tmux-thumbs.sh b/tmux-thumbs.sh index 6b24b71..df1d3c8 100755 --- a/tmux-thumbs.sh +++ b/tmux-thumbs.sh @@ -1,3 +1,3 @@ #!/usr/bin/env bash -/home/ubuntu/dev/tmux-thumbs/target/debug/tmux-thumbs -a qwerty -r +/home/ubuntu/dev/tmux-thumbs/target/debug/tmux-thumbs -a qwerty -r -u