diff options
Diffstat (limited to 'helix-term/src/ui/fuzzy_match.rs')
-rw-r--r-- | helix-term/src/ui/fuzzy_match.rs | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/helix-term/src/ui/fuzzy_match.rs b/helix-term/src/ui/fuzzy_match.rs new file mode 100644 index 00000000..e25d7328 --- /dev/null +++ b/helix-term/src/ui/fuzzy_match.rs @@ -0,0 +1,74 @@ +use fuzzy_matcher::skim::SkimMatcherV2 as Matcher; +use fuzzy_matcher::FuzzyMatcher; + +#[cfg(test)] +mod test; + +pub struct FuzzyQuery { + queries: Vec<String>, +} + +impl FuzzyQuery { + pub fn new(query: &str) -> FuzzyQuery { + let mut saw_backslash = false; + let queries = query + .split(|c| { + saw_backslash = match c { + ' ' if !saw_backslash => return true, + '\\' => true, + _ => false, + }; + false + }) + .filter_map(|query| { + if query.is_empty() { + None + } else { + Some(query.replace("\\ ", " ")) + } + }) + .collect(); + FuzzyQuery { queries } + } + + pub fn fuzzy_match(&self, item: &str, matcher: &Matcher) -> Option<i64> { + // use the rank of the first query for the rank, because merging ranks is not really possible + // this behaviour matches fzf and skim + let score = matcher.fuzzy_match(item, self.queries.get(0)?)?; + if self + .queries + .iter() + .any(|query| matcher.fuzzy_match(item, query).is_none()) + { + return None; + } + Some(score) + } + + pub fn fuzzy_indicies(&self, item: &str, matcher: &Matcher) -> Option<(i64, Vec<usize>)> { + if self.queries.len() == 1 { + return matcher.fuzzy_indices(item, &self.queries[0]); + } + + // use the rank of the first query for the rank, because merging ranks is not really possible + // this behaviour matches fzf and skim + let (score, mut indicies) = matcher.fuzzy_indices(item, self.queries.get(0)?)?; + + // fast path for the common case of not using a space + // during matching this branch should be free thanks to branch prediction + if self.queries.len() == 1 { + return Some((score, indicies)); + } + + for query in &self.queries[1..] { + let (_, matched_indicies) = matcher.fuzzy_indices(item, query)?; + indicies.extend_from_slice(&matched_indicies); + } + + // deadup and remove duplicate matches + indicies.sort_unstable(); + indicies.dedup(); + + Some((score, indicies)) + } +} |