Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'helix-term/src/ui/menu.rs')
| -rw-r--r-- | helix-term/src/ui/menu.rs | 72 |
1 files changed, 19 insertions, 53 deletions
diff --git a/helix-term/src/ui/menu.rs b/helix-term/src/ui/menu.rs index 612832ce..76e50229 100644 --- a/helix-term/src/ui/menu.rs +++ b/helix-term/src/ui/menu.rs @@ -1,12 +1,7 @@ -use std::{borrow::Cow, cmp::Reverse}; - use crate::{ compositor::{Callback, Component, Compositor, Context, Event, EventResult}, ctrl, key, shift, }; -use helix_core::fuzzy::MATCHER; -use nucleo::pattern::{Atom, AtomKind, CaseMatching, Normalization}; -use nucleo::{Config, Utf32Str}; use tui::{buffer::Buffer as Surface, widgets::Table}; pub use tui::widgets::{Cell, Row}; @@ -19,16 +14,6 @@ pub trait Item: Sync + Send + 'static { type Data: Sync + Send + 'static; fn format(&self, data: &Self::Data) -> Row; - - fn sort_text(&self, data: &Self::Data) -> Cow<str> { - let label: String = self.format(data).cell_text().collect(); - label.into() - } - - fn filter_text(&self, data: &Self::Data) -> Cow<str> { - let label: String = self.format(data).cell_text().collect(); - label.into() - } } pub type MenuCallback<T> = Box<dyn Fn(&mut Editor, Option<&T>, MenuEvent)>; @@ -77,49 +62,30 @@ impl<T: Item> Menu<T> { } } - pub fn score(&mut self, pattern: &str, incremental: bool) { - let mut matcher = MATCHER.lock(); - matcher.config = Config::DEFAULT; - let pattern = Atom::new( - pattern, - CaseMatching::Ignore, - Normalization::Smart, - AtomKind::Fuzzy, - false, - ); - let mut buf = Vec::new(); - if incremental { - self.matches.retain_mut(|(index, score)| { - let option = &self.options[*index as usize]; - let text = option.filter_text(&self.editor_data); - let new_score = pattern.score(Utf32Str::new(&text, &mut buf), &mut matcher); - match new_score { - Some(new_score) => { - *score = new_score as u32; - true - } - None => false, - } - }) - } else { - self.matches.clear(); - let matches = self.options.iter().enumerate().filter_map(|(i, option)| { - let text = option.filter_text(&self.editor_data); - pattern - .score(Utf32Str::new(&text, &mut buf), &mut matcher) - .map(|score| (i as u32, score as u32)) - }); - self.matches.extend(matches); - } - self.matches - .sort_unstable_by_key(|&(i, score)| (Reverse(score), i)); - - // reset cursor position + pub fn reset_cursor(&mut self) { self.cursor = None; self.scroll = 0; self.recalculate = true; } + pub fn update_options(&mut self) -> (&mut Vec<(u32, u32)>, &mut Vec<T>) { + self.recalculate = true; + (&mut self.matches, &mut self.options) + } + + pub fn ensure_cursor_in_bounds(&mut self) { + if self.matches.is_empty() { + self.cursor = None; + self.scroll = 0; + } else { + self.scroll = 0; + self.recalculate = true; + if let Some(cursor) = &mut self.cursor { + *cursor = (*cursor).min(self.matches.len() - 1) + } + } + } + pub fn clear(&mut self) { self.matches.clear(); |