Skip to main content

matchmaker/nucleo/
mod.rs

1pub mod injector;
2pub mod query;
3pub mod variants;
4mod worker;
5
6use std::{
7    borrow::Cow,
8    fmt::{self, Display, Formatter},
9    hash::{Hash, Hasher},
10};
11
12use arrayvec::ArrayVec;
13pub use variants::*;
14pub use worker::*;
15
16pub use nucleo;
17pub use ratatui::prelude::*;
18
19use crate::{MAX_SPLITS, SegmentableItem};
20
21// ------------- Wrapper structs
22
23/// This struct implements ColumnIndexable, and can instantiate a worker with columns.
24#[derive(Debug, Clone, Hash, Eq, PartialEq)]
25pub struct Segmented<T: SegmentableItem> {
26    pub inner: T,
27    ranges: ArrayVec<(usize, usize), MAX_SPLITS>,
28}
29
30impl<T: SegmentableItem> ColumnIndexable for Segmented<T> {
31    fn get_str(&self, index: usize) -> Cow<'_, str> {
32        if let Some((start, end)) = self.ranges.get(index) {
33            &self.inner[*start..*end]
34        } else {
35            ""
36        }
37        .into()
38    }
39}
40
41impl<T: SegmentableItem> Segmented<T> {
42    pub fn len(&self) -> usize {
43        // Find the last range that is nonempty (start != end)
44        self.ranges
45            .iter()
46            .rposition(|&(start, end)| start != end)
47            .map_or(0, |idx| idx + 1)
48    }
49
50    pub fn is_empty(&self) -> bool {
51        self.len() == 0
52    }
53
54    pub fn map_to_vec<U, F>(&self, f: F) -> ArrayVec<U, MAX_SPLITS>
55    where
56        F: Fn(&T, usize, usize) -> U,
57    {
58        self.ranges
59            .iter()
60            .take(self.len()) // only map the "active" ranges
61            .map(|&(start, end)| f(&self.inner, start, end))
62            .collect()
63    }
64}
65
66#[derive(Debug, Clone)]
67pub struct Indexed<T> {
68    pub index: u32,
69    pub inner: T,
70}
71
72impl<T: Clone> Indexed<T> {
73    /// Matchmaker requires a way to identify and store selected items from their references in the nucleo matcher. This method simply identifies them by their insertion index and stores the clones of the items.
74    pub fn identifier(&self) -> (u32, T) {
75        (self.index, self.inner.clone())
76    }
77}
78
79impl<T> Indexed<T> {
80    /// Matchmaker requires a way to identify and store selected items from their references in the nucleo matcher. This method simply identifies them by their insertion index and is intended when the output type is not needed (i.e. externally managed).
81    pub fn dummy_identifier(&self) -> (u32, ()) {
82        (self.index, ())
83    }
84}
85
86impl<T: ColumnIndexable> ColumnIndexable for Indexed<T> {
87    fn get_str(&self, index: usize) -> Cow<'_, str> {
88        self.inner.get_str(index)
89    }
90}
91
92impl<T: Render> Render for Indexed<T> {
93    fn as_str(&self) -> Cow<'_, str> {
94        self.inner.as_str()
95    }
96    fn as_text(&self) -> Text<'_> {
97        self.inner.as_text()
98    }
99}
100
101impl<T> std::ops::Deref for Indexed<T> {
102    type Target = T;
103
104    fn deref(&self) -> &Self::Target {
105        &self.inner
106    }
107}
108
109// ------------------------------------------
110impl<T: Display + SegmentableItem> Display for Segmented<T> {
111    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
112        write!(f, "{}", self.inner)
113    }
114}
115
116impl<T: Display> Display for Indexed<T> {
117    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
118        write!(f, "{}", self.inner)
119    }
120}
121
122impl<T> PartialEq for Indexed<T> {
123    fn eq(&self, other: &Self) -> bool {
124        self.index == other.index
125    }
126}
127
128impl<T> Eq for Indexed<T> {}
129
130impl<T> Hash for Indexed<T> {
131    fn hash<H: Hasher>(&self, state: &mut H) {
132        self.index.hash(state)
133    }
134}