Actually add fuzzy matcher

This commit is contained in:
Kasper Juul Hermansen 2024-09-15 21:44:20 +02:00
parent ff8103c805
commit 102af558f5
3 changed files with 57 additions and 15 deletions

View File

@ -1,6 +1,8 @@
use nucleo_matcher::{pattern::Pattern, Matcher, Utf32Str}; use nucleo_matcher::{pattern::Pattern, Matcher, Utf32Str};
use crate::{app::App, cache::CacheApp, projects_list::ProjectsListApp}; use crate::{
app::App, cache::CacheApp, fuzzy_matcher::FuzzyMatcherApp, projects_list::ProjectsListApp,
};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct RootCommand { pub struct RootCommand {
@ -26,28 +28,23 @@ impl RootCommand {
repositories repositories
} }
}; };
let haystack = repositories
.iter()
.map(|r| r.to_rel_path().display().to_string());
let needle = match search { let needle = match search {
Some(needle) => needle.into(), Some(needle) => needle.into(),
None => todo!(), None => todo!(),
}; };
let pattern = Pattern::new( let haystack = repositories
&needle, .iter()
nucleo_matcher::pattern::CaseMatching::Ignore, .map(|r| r.to_rel_path().display().to_string())
nucleo_matcher::pattern::Normalization::Smart, .collect::<Vec<_>>();
nucleo_matcher::pattern::AtomKind::Fuzzy,
); let haystack = haystack.as_str_vec();
let mut matcher = Matcher::new(nucleo_matcher::Config::DEFAULT);
let res = pattern.match_list(haystack, &mut matcher); let res = self.app.fuzzy_matcher().match_pattern(&needle, &haystack);
let res = res.iter().take(10).rev().collect::<Vec<_>>(); let res = res.iter().take(10).rev().collect::<Vec<_>>();
for (repo, _score) in res { for repo in res {
tracing::debug!("repo: {:?}", repo); tracing::debug!("repo: {:?}", repo);
} }
@ -56,3 +53,13 @@ impl RootCommand {
Ok(()) Ok(())
} }
} }
trait StringExt {
fn as_str_vec<'a>(&'a self) -> Vec<&'a str>;
}
impl StringExt for Vec<String> {
fn as_str_vec<'a>(&'a self) -> Vec<&'a str> {
self.iter().map(|r| r.as_ref()).collect()
}
}

View File

@ -0,0 +1,34 @@
use nucleo_matcher::{pattern::Pattern, Matcher};
use crate::app::App;
pub struct FuzzyMatcher {}
impl FuzzyMatcher {
pub fn new() -> Self {
Self {}
}
pub fn match_pattern<'a>(&self, pattern: &'a str, items: &'a [&'a str]) -> Vec<&'a str> {
let pat = Pattern::new(
&pattern,
nucleo_matcher::pattern::CaseMatching::Ignore,
nucleo_matcher::pattern::Normalization::Smart,
nucleo_matcher::pattern::AtomKind::Fuzzy,
);
let mut matcher = Matcher::new(nucleo_matcher::Config::DEFAULT);
let res = pat.match_list(items, &mut matcher);
res.into_iter().map(|((item, _))| *item).collect::<Vec<_>>()
}
}
pub trait FuzzyMatcherApp {
fn fuzzy_matcher(&self) -> FuzzyMatcher;
}
impl FuzzyMatcherApp for &'static App {
fn fuzzy_matcher(&self) -> FuzzyMatcher {
FuzzyMatcher::new()
}
}

View File

@ -12,6 +12,7 @@ mod cache;
mod cache_codec; mod cache_codec;
mod commands; mod commands;
mod config; mod config;
mod fuzzy_matcher;
mod git_provider; mod git_provider;
mod projects_list; mod projects_list;