From 5586d4a0a0c95d8e7149834a150fb54bd6281411 Mon Sep 17 00:00:00 2001 From: Reilly Wood <26268125+rgwood@users.noreply.github.com> Date: Sun, 27 Mar 2022 15:11:56 -0700 Subject: [PATCH] did_you_mean: case-insensitive edit distance, tests (#4999) --- crates/nu-protocol/src/shell_error.rs | 40 ++++++++++++++++++++------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/crates/nu-protocol/src/shell_error.rs b/crates/nu-protocol/src/shell_error.rs index 7e1a8fa7b..b0b8ae4ce 100644 --- a/crates/nu-protocol/src/shell_error.rs +++ b/crates/nu-protocol/src/shell_error.rs @@ -360,19 +360,10 @@ impl From> for ShellError { } pub fn did_you_mean(possibilities: &[String], tried: &str) -> Option { - // First see if we can find the same string just cased differently - let great_match_index = possibilities - .iter() - .position(|word| word.to_lowercase() == tried.to_lowercase()); - - if let Some(index) = great_match_index { - return Some(possibilities[index].to_owned()); - } - let mut possible_matches: Vec<_> = possibilities .iter() .map(|word| { - let edit_distance = levenshtein_distance(word, tried); + let edit_distance = levenshtein_distance(&word.to_lowercase(), &tried.to_lowercase()); (edit_distance, word.to_owned()) }) .collect(); @@ -446,3 +437,32 @@ pub fn levenshtein_distance(a: &str, b: &str) -> usize { result } + +#[cfg(test)] +mod tests { + use super::did_you_mean; + + #[test] + fn did_you_mean_works_with_wrong_case() { + let possibilities = &["OS".into(), "PWD".into()]; + let actual = did_you_mean(possibilities, "pwd"); + let expected = Some(String::from("PWD")); + assert_eq!(actual, expected) + } + + #[test] + fn did_you_mean_works_with_typo() { + let possibilities = &["OS".into(), "PWD".into()]; + let actual = did_you_mean(possibilities, "PWF"); + let expected = Some(String::from("PWD")); + assert_eq!(actual, expected) + } + + #[test] + fn did_you_mean_works_with_wrong_case_and_typo() { + let possibilities = &["OS".into(), "PWD".into()]; + let actual = did_you_mean(possibilities, "pwf"); + let expected = Some(String::from("PWD")); + assert_eq!(actual, expected) + } +}