From c2d995b9e3ac7e3bbdb8b47531b865afcb074f12 Mon Sep 17 00:00:00 2001 From: sigoden Date: Thu, 23 Jan 2025 17:36:38 +0800 Subject: refactor: fuzzy filter REPL autocompletions (#1120) --- src/config/mod.rs | 10 +--------- src/repl/completer.rs | 24 ++++++++++-------------- src/utils/mod.rs | 16 ++++++++++++++-- 3 files changed, 25 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/config/mod.rs b/src/config/mod.rs index ec6a930..20abbae 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -1850,15 +1850,7 @@ impl Config { } values.extend(complete_agent_variables(args[0])); }; - let mut values_with_score: Vec<_> = values - .into_iter() - .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() + fuzzy_filter(values, |v| v.0.as_str(), filter) } pub fn sync_models_url(&self) -> String { diff --git a/src/repl/completer.rs b/src/repl/completer.rs index bcce694..1f4dcc7 100644 --- a/src/repl/completer.rs +++ b/src/repl/completer.rs @@ -1,6 +1,6 @@ use super::{ReplCommand, REPL_COMMANDS}; -use crate::{config::GlobalConfig, utils::fuzzy_match}; +use crate::{config::GlobalConfig, utils::fuzzy_filter}; use reedline::{Completer, Span, Suggestion}; use std::collections::HashMap; @@ -29,25 +29,21 @@ impl Completer for ReplCompleter { let state = self.config.read().state(); + let command_filter = parts + .iter() + .take(2) + .map(|(v, _)| *v) + .collect::>() + .join(" "); let commands: Vec<_> = self .commands .iter() .filter(|cmd| { - if !cmd.is_valid(state) { - return false; - } - let line = parts - .iter() - .take(2) - .map(|(v, _)| *v) - .collect::>() - .join(" "); - if line == "." { - return true; - } - line.starts_with(&cmd.name[..2]) && fuzzy_match(cmd.name, &line).is_some() + cmd.is_valid(state) + && (command_filter.len() == 1 || cmd.name.starts_with(&command_filter[..2])) }) .collect(); + let commands = fuzzy_filter(commands, |v| v.name, &command_filter); if parts_len > 1 { let span = Span::new(parts[parts_len - 1].1, pos); diff --git a/src/utils/mod.rs b/src/utils/mod.rs index f4b98c1..7aa1801 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -119,8 +119,20 @@ pub fn convert_option_string(value: &str) -> Option { } } -pub fn fuzzy_match(choice: &str, pattern: &str) -> Option { - SkimMatcherV2::default().fuzzy_match(choice, pattern) +pub fn fuzzy_filter(values: Vec, get: F, pattern: &str) -> Vec +where + F: Fn(&T) -> &str, +{ + let matcher = SkimMatcherV2::default(); + let mut list: Vec<(T, i64)> = values + .into_iter() + .filter_map(|v| { + let score = matcher.fuzzy_match(get(&v), pattern)?; + Some((v, score)) + }) + .collect(); + list.sort_unstable_by(|a, b| b.1.cmp(&a.1)); + list.into_iter().map(|(v, _)| v).collect() } pub fn pretty_error(err: &anyhow::Error) -> String { -- cgit v1.2.3