diff options
| author | sigoden <sigoden@gmail.com> | 2025-01-23 09:46:25 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-01-23 09:46:25 +0800 |
| commit | 7567478754bfbc4b103b692c6b1574f80a8b453f (patch) | |
| tree | 9cd9d2665710d26d1a0b957ac2d74dfd10dd0498 /src | |
| parent | 5defd0bdb0e68ca26da575c88116313cd48e290d (diff) | |
| download | aichat-7567478754bfbc4b103b692c6b1574f80a8b453f.tar.gz | |
refactor: sort repl autocompletion items by fuzzy-match score (#1119)
Diffstat (limited to 'src')
| -rw-r--r-- | src/config/mod.rs | 11 | ||||
| -rw-r--r-- | src/repl/completer.rs | 2 | ||||
| -rw-r--r-- | src/utils/mod.rs | 25 |
3 files changed, 12 insertions, 26 deletions
diff --git a/src/config/mod.rs b/src/config/mod.rs index 98bcab3..ec6a930 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -1850,10 +1850,15 @@ impl Config { } values.extend(complete_agent_variables(args[0])); }; - values + let mut values_with_score: Vec<_> = values .into_iter() - .filter(|(value, _)| fuzzy_match(value, filter)) - .collect() + .filter_map(|v| { + let score = fuzzy_match(&v.0, filter)?; + Some((v, score)) + }) + .collect(); + values_with_score.sort_unstable_by(|a, b| b.1.cmp(&a.1)); + values_with_score.into_iter().map(|v| v.0).collect() } pub fn sync_models_url(&self) -> String { diff --git a/src/repl/completer.rs b/src/repl/completer.rs index 12e871a..bcce694 100644 --- a/src/repl/completer.rs +++ b/src/repl/completer.rs @@ -45,7 +45,7 @@ impl Completer for ReplCompleter { if line == "." { return true; } - line.starts_with(&cmd.name[..2]) && fuzzy_match(cmd.name, &line) + line.starts_with(&cmd.name[..2]) && fuzzy_match(cmd.name, &line).is_some() }) .collect(); diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 8d66470..f4b98c1 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -24,6 +24,7 @@ pub use self::variables::*; use anyhow::{Context, Result}; use fancy_regex::Regex; +use fuzzy_matcher::{skim::SkimMatcherV2, FuzzyMatcher}; use is_terminal::IsTerminal; use std::{env, path::PathBuf, process}; use unicode_segmentation::UnicodeSegmentation; @@ -118,21 +119,8 @@ pub fn convert_option_string(value: &str) -> Option<String> { } } -pub fn fuzzy_match(text: &str, pattern: &str) -> bool { - let text_chars: Vec<char> = text.chars().collect(); - let pattern_chars: Vec<char> = pattern.chars().collect(); - - let mut pattern_index = 0; - let mut text_index = 0; - - while pattern_index < pattern_chars.len() && text_index < text_chars.len() { - if pattern_chars[pattern_index] == text_chars[text_index] { - pattern_index += 1; - } - text_index += 1; - } - - pattern_index == pattern_chars.len() +pub fn fuzzy_match(choice: &str, pattern: &str) -> Option<i64> { + SkimMatcherV2::default().fuzzy_match(choice, pattern) } pub fn pretty_error(err: &anyhow::Error) -> String { @@ -235,13 +223,6 @@ mod tests { use super::*; #[test] - fn test_fuzzy_match() { - assert!(fuzzy_match("openai:gpt-4-turbo", "gpt4")); - assert!(fuzzy_match("openai:gpt-4-turbo", "oai4")); - assert!(!fuzzy_match("openai:gpt-4-turbo", "4gpt")); - } - - #[test] #[cfg(not(target_os = "windows"))] fn test_safe_join_path() { assert_eq!( |
