diff --git a/Cargo.lock b/Cargo.lock index 20f6667672..c228424fa1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -239,6 +239,12 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +[[package]] +name = "cov-mark" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ffa3d3e0138386cd4361f63537765cac7ee40698028844635a54495a92f67f3" + [[package]] name = "crc32fast" version = "1.3.2" @@ -688,13 +694,13 @@ dependencies = [ "dirs", "easy-cast", "filetreelist", - "fuzzy-matcher", "gh-emoji", "indexmap", "itertools", "log", "notify", "notify-debouncer-mini", + "nucleo", "once_cell", "pretty_assertions", "ratatui", @@ -1031,6 +1037,28 @@ dependencies = [ "notify", ] +[[package]] +name = "nucleo" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ccab936f2c8ad271bb31430944d98d358f74153566ea323265497f5639b11b6" +dependencies = [ + "nucleo-matcher", + "parking_lot", + "rayon", +] + +[[package]] +name = "nucleo-matcher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b702b402fe286162d1f00b552a046ce74365d2ac473a2607ff36ba650f9bd57" +dependencies = [ + "cov-mark", + "memchr", + "unicode-segmentation", +] + [[package]] name = "num-traits" version = "0.2.15" @@ -1258,6 +1286,16 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "rayon" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +dependencies = [ + "either", + "rayon-core", +] + [[package]] name = "rayon-core" version = "1.11.0" diff --git a/Cargo.toml b/Cargo.toml index 3e856ccd5f..25200bfa32 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,13 +28,13 @@ crossterm = { version = "0.26.1", features = ["serde"] } dirs = "5.0" easy-cast = "0.5" filetreelist = { path = "./filetreelist", version = "0.5" } -fuzzy-matcher = "0.3" gh-emoji = { version = "1.0", optional = true } indexmap = "1.9" itertools = "0.11" log = "0.4" notify = "5.1" notify-debouncer-mini = "0.2" +nucleo = "0.2" once_cell = "1" ratatui = { version = "0.21", default-features = false, features = ['crossterm', 'serde'] } rayon-core = "1.11" diff --git a/src/components/fuzzy_find_popup.rs b/src/components/fuzzy_find_popup.rs index cb9bfd8ace..bfa04a0be0 100644 --- a/src/components/fuzzy_find_popup.rs +++ b/src/components/fuzzy_find_popup.rs @@ -12,7 +12,7 @@ use crate::{ }; use anyhow::Result; use crossterm::event::Event; -use fuzzy_matcher::FuzzyMatcher; +use nucleo::{Matcher, Utf32Str}; use ratatui::{ backend::Backend, layout::{Constraint, Direction, Layout, Margin, Rect}, @@ -35,6 +35,9 @@ pub struct FuzzyFindPopup { filtered: Vec<(usize, Vec)>, key_config: SharedKeyConfig, target: Option, + matcher: Matcher, + matcher_haystack_buf: Vec, + matcher_needle_buf: Vec, } impl FuzzyFindPopup { @@ -65,6 +68,9 @@ impl FuzzyFindPopup { key_config, selection: 0, target: None, + matcher: Matcher::default(), + matcher_haystack_buf: Vec::new(), + matcher_needle_buf: Vec::new(), } } @@ -88,17 +94,37 @@ impl FuzzyFindPopup { self.filtered.clear(); if let Some(q) = &self.query { - let matcher = - fuzzy_matcher::skim::SkimMatcherV2::default(); + let query = + Utf32Str::new(q, &mut self.matcher_needle_buf); + let mut matched_indicies = Vec::new(); let mut contents = self .contents .iter() .enumerate() - .filter_map(|a| { - matcher - .fuzzy_indices(a.1, q) - .map(|(score, indices)| (score, a.0, indices)) + .filter_map(|(index, line_content)| { + matched_indicies.clear(); + self.matcher + .fuzzy_indices( + Utf32Str::new( + line_content, + &mut self.matcher_haystack_buf, + ), + query, + &mut matched_indicies, + ) + .map(|score| { + ( + score, + index, + matched_indicies + .iter() + .filter_map(|a| { + (*a).try_into().ok() + }) + .collect(), + ) + }) }) .collect::>();