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 crate::{app::App, cache::CacheApp, projects_list::ProjectsListApp};
use crate::{
app::App, cache::CacheApp, fuzzy_matcher::FuzzyMatcherApp, projects_list::ProjectsListApp,
};
#[derive(Debug, Clone)]
pub struct RootCommand {
@ -26,28 +28,23 @@ impl RootCommand {
repositories
}
};
let haystack = repositories
.iter()
.map(|r| r.to_rel_path().display().to_string());
let needle = match search {
Some(needle) => needle.into(),
None => todo!(),
};
let pattern = Pattern::new(
&needle,
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 = pattern.match_list(haystack, &mut matcher);
let haystack = repositories
.iter()
.map(|r| r.to_rel_path().display().to_string())
.collect::<Vec<_>>();
let haystack = haystack.as_str_vec();
let res = self.app.fuzzy_matcher().match_pattern(&needle, &haystack);
let res = res.iter().take(10).rev().collect::<Vec<_>>();
for (repo, _score) in res {
for repo in res {
tracing::debug!("repo: {:?}", repo);
}
@ -56,3 +53,13 @@ impl RootCommand {
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 commands;
mod config;
mod fuzzy_matcher;
mod git_provider;
mod projects_list;