diff options
Diffstat (limited to 'helix-term/src/ui/picker.rs')
-rw-r--r-- | helix-term/src/ui/picker.rs | 64 |
1 files changed, 35 insertions, 29 deletions
diff --git a/helix-term/src/ui/picker.rs b/helix-term/src/ui/picker.rs index a56455d7..c7149c61 100644 --- a/helix-term/src/ui/picker.rs +++ b/helix-term/src/ui/picker.rs @@ -1,7 +1,7 @@ use crate::{ compositor::{Component, Compositor, Context, Event, EventResult}, ctrl, key, shift, - ui::{self, EditorView}, + ui::{self, fuzzy_match::FuzzyQuery, EditorView}, }; use tui::{ buffer::Buffer as Surface, @@ -9,7 +9,6 @@ use tui::{ }; use fuzzy_matcher::skim::SkimMatcherV2 as Matcher; -use fuzzy_matcher::FuzzyMatcher; use tui::widgets::Widget; use std::time::Instant; @@ -161,6 +160,27 @@ impl<T: Item> FilePicker<T> { self.preview_cache.insert(path.to_owned(), preview); Preview::Cached(&self.preview_cache[path]) } + + fn handle_idle_timeout(&mut self, cx: &mut Context) -> EventResult { + // Try to find a document in the cache + let doc = self + .current_file(cx.editor) + .and_then(|(path, _range)| self.preview_cache.get_mut(&path)) + .and_then(|cache| match cache { + CachedPreview::Document(doc) => Some(doc), + _ => None, + }); + + // Then attempt to highlight it if it has no language set + if let Some(doc) = doc { + if doc.language_config().is_none() { + let loader = cx.editor.syn_loader.clone(); + doc.detect_language(loader); + } + } + + EventResult::Consumed(None) + } } impl<T: Item + 'static> Component for FilePicker<T> { @@ -261,6 +281,9 @@ impl<T: Item + 'static> Component for FilePicker<T> { } fn handle_event(&mut self, event: &Event, ctx: &mut Context) -> EventResult { + if let Event::IdleTimeout = event { + return self.handle_idle_timeout(ctx); + } // TODO: keybinds for scrolling preview self.picker.handle_event(event, ctx) } @@ -287,8 +310,6 @@ pub struct Picker<T: Item> { matcher: Box<Matcher>, /// (index, score) matches: Vec<(usize, i64)>, - /// Filter over original options. - filters: Vec<usize>, // could be optimized into bit but not worth it now /// Current height of the completions box completion_height: u16, @@ -323,7 +344,6 @@ impl<T: Item> Picker<T> { editor_data, matcher: Box::new(Matcher::default()), matches: Vec::new(), - filters: Vec::new(), cursor: 0, prompt, previous_pattern: String::new(), @@ -365,13 +385,14 @@ impl<T: Item> Picker<T> { .map(|(index, _option)| (index, 0)), ); } else if pattern.starts_with(&self.previous_pattern) { + let query = FuzzyQuery::new(pattern); // optimization: if the pattern is a more specific version of the previous one // then we can score the filtered set. self.matches.retain_mut(|(index, score)| { let option = &self.options[*index]; let text = option.sort_text(&self.editor_data); - match self.matcher.fuzzy_match(&text, pattern) { + match query.fuzzy_match(&text, &self.matcher) { Some(s) => { // Update the score *score = s; @@ -384,23 +405,17 @@ impl<T: Item> Picker<T> { self.matches .sort_unstable_by_key(|(_, score)| Reverse(*score)); } else { + let query = FuzzyQuery::new(pattern); self.matches.clear(); self.matches.extend( self.options .iter() .enumerate() .filter_map(|(index, option)| { - // filter options first before matching - if !self.filters.is_empty() { - // TODO: this filters functionality seems inefficient, - // instead store and operate on filters if any - self.filters.binary_search(&index).ok()?; - } - let text = option.filter_text(&self.editor_data); - self.matcher - .fuzzy_match(&text, pattern) + query + .fuzzy_match(&text, &self.matcher) .map(|score| (index, score)) }), ); @@ -460,14 +475,6 @@ impl<T: Item> Picker<T> { .map(|(index, _score)| &self.options[*index]) } - pub fn save_filter(&mut self, cx: &Context) { - self.filters.clear(); - self.filters - .extend(self.matches.iter().map(|(index, _)| *index)); - self.filters.sort_unstable(); // used for binary search later - self.prompt.clear(cx.editor); - } - pub fn toggle_preview(&mut self) { self.show_preview = !self.show_preview; } @@ -505,6 +512,9 @@ impl<T: Item + 'static> Component for Picker<T> { compositor.last_picker = compositor.pop(); }))); + // So that idle timeout retriggers + cx.editor.reset_idle_timer(); + match key_event { shift!(Tab) | key!(Up) | ctrl!('p') => { self.move_by(1, Direction::Backward); @@ -545,9 +555,6 @@ impl<T: Item + 'static> Component for Picker<T> { } return close_fn; } - ctrl!(' ') => { - self.save_filter(cx); - } ctrl!('t') => { self.toggle_preview(); } @@ -630,9 +637,8 @@ impl<T: Item + 'static> Component for Picker<T> { } let spans = option.label(&self.editor_data); - let (_score, highlights) = self - .matcher - .fuzzy_indices(&String::from(&spans), self.prompt.line()) + let (_score, highlights) = FuzzyQuery::new(self.prompt.line()) + .fuzzy_indicies(&String::from(&spans), &self.matcher) .unwrap_or_default(); spans.0.into_iter().fold(inner, |pos, span| { |