From 0cb595e226c9970989ee1e680ae6b8011d188cbf Mon Sep 17 00:00:00 2001
From: Pascal Kuthe
Date: Wed, 30 Aug 2023 06:26:21 +0200
Subject: transition to nucleo for fuzzy matching (#7814)

* transition to nucleo for fuzzy matching

* drop flakey test case

since the picker streams in results now any test that relies
on the picker containing results is potentially flakely

* use crates.io version of nucleo

* Fix typo in commands.rs

Co-authored-by: Skyler Hawthorne <skyler@dead10ck.com>

---------

Co-authored-by: Skyler Hawthorne <skyler@dead10ck.com>---
 helix-core/Cargo.toml   |  3 +++
 helix-core/src/fuzzy.rs | 43 +++++++++++++++++++++++++++++++++++++++++++
 helix-core/src/lib.rs   |  1 +
 3 files changed, 47 insertions(+)
 create mode 100644 helix-core/src/fuzzy.rs

(limited to 'helix-core')

diff --git a/helix-core/Cargo.toml b/helix-core/Cargo.toml
index b434fbf3..515443e0 100644
--- a/helix-core/Cargo.toml
+++ b/helix-core/Cargo.toml
@@ -48,6 +48,9 @@ chrono = { version = "0.4", default-features = false, features = ["alloc", "std"
 etcetera = "0.8"
 textwrap = "0.16.0"
 
+nucleo.workspace = true
+parking_lot = "0.12"
+
 [dev-dependencies]
 quickcheck = { version = "1", default-features = false }
 indoc = "2.0.3"
diff --git a/helix-core/src/fuzzy.rs b/helix-core/src/fuzzy.rs
new file mode 100644
index 00000000..e40a2d06
--- /dev/null
+++ b/helix-core/src/fuzzy.rs
@@ -0,0 +1,43 @@
+use std::ops::DerefMut;
+
+use nucleo::pattern::{AtomKind, CaseMatching, Pattern};
+use nucleo::Config;
+use parking_lot::Mutex;
+
+pub struct LazyMutex<T> {
+    inner: Mutex<Option<T>>,
+    init: fn() -> T,
+}
+
+impl<T> LazyMutex<T> {
+    pub const fn new(init: fn() -> T) -> Self {
+        Self {
+            inner: Mutex::new(None),
+            init,
+        }
+    }
+
+    pub fn lock(&self) -> impl DerefMut<Target = T> + '_ {
+        parking_lot::MutexGuard::map(self.inner.lock(), |val| val.get_or_insert_with(self.init))
+    }
+}
+
+pub static MATCHER: LazyMutex<nucleo::Matcher> = LazyMutex::new(nucleo::Matcher::default);
+
+/// convenience function to easily fuzzy match
+/// on a (relatively small list of inputs). This is not recommended for building a full tui
+/// application that can match large numbers of matches as all matching is done on the current
+/// thread, effectively blocking the UI
+pub fn fuzzy_match<T: AsRef<str>>(
+    pattern: &str,
+    items: impl IntoIterator<Item = T>,
+    path: bool,
+) -> Vec<(T, u32)> {
+    let mut matcher = MATCHER.lock();
+    matcher.config = Config::DEFAULT;
+    if path {
+        matcher.config.set_match_paths();
+    }
+    let pattern = Pattern::new(pattern, CaseMatching::Smart, AtomKind::Fuzzy);
+    pattern.match_list(items, &mut matcher)
+}
diff --git a/helix-core/src/lib.rs b/helix-core/src/lib.rs
index 9a512eae..0acdb238 100644
--- a/helix-core/src/lib.rs
+++ b/helix-core/src/lib.rs
@@ -7,6 +7,7 @@ pub mod config;
 pub mod diagnostic;
 pub mod diff;
 pub mod doc_formatter;
+pub mod fuzzy;
 pub mod graphemes;
 pub mod history;
 pub mod increment;
-- 
cgit v1.2.3-70-g09d2