aboutsummaryrefslogtreecommitdiff
path: root/helix-term/src
diff options
context:
space:
mode:
authorIvan Tham2021-06-12 10:46:05 +0000
committerIvan Tham2021-06-15 04:00:31 +0000
commit002f1ad397a6fff4fec044e05a8784c643a04d48 (patch)
tree07e7fa9435cbef705963fb05575d66b0813d0cd2 /helix-term/src
parent7c2fb92c9170ff108bef244e7aed82e29156ae5c (diff)
Add filter ability to picker
Inspired by doom emacs. Able to filter picker options multiple times.
Diffstat (limited to 'helix-term/src')
-rw-r--r--helix-term/src/ui/picker.rs22
-rw-r--r--helix-term/src/ui/prompt.rs7
2 files changed, 29 insertions, 0 deletions
diff --git a/helix-term/src/ui/picker.rs b/helix-term/src/ui/picker.rs
index eae9d74f..20d51d5d 100644
--- a/helix-term/src/ui/picker.rs
+++ b/helix-term/src/ui/picker.rs
@@ -23,6 +23,8 @@ pub struct Picker<T> {
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
cursor: usize,
// pattern: String,
@@ -50,6 +52,7 @@ impl<T> Picker<T> {
options,
matcher: Box::new(Matcher::default()),
matches: Vec::new(),
+ filters: Vec::new(),
cursor: 0,
prompt,
format_fn: Box::new(format_fn),
@@ -68,6 +71,7 @@ impl<T> Picker<T> {
ref mut options,
ref mut matcher,
ref mut matches,
+ ref filters,
ref format_fn,
..
} = *self;
@@ -81,6 +85,10 @@ impl<T> Picker<T> {
.iter()
.enumerate()
.filter_map(|(index, option)| {
+ // filter options first before matching
+ if !filters.is_empty() {
+ filters.binary_search(&index).ok()?;
+ }
// TODO: maybe using format_fn isn't the best idea here
let text = (format_fn)(option);
// TODO: using fuzzy_indices could give us the char idx for match highlighting
@@ -114,6 +122,14 @@ impl<T> Picker<T> {
.get(self.cursor)
.map(|(index, _score)| &self.options[*index])
}
+
+ pub fn save_filter(&mut self) {
+ self.filters.clear();
+ self.filters
+ .extend(self.matches.iter().map(|(index, _)| *index));
+ self.filters.sort_unstable(); // used for binary search later
+ self.prompt.clear();
+ }
}
// process:
@@ -205,6 +221,12 @@ impl<T: 'static> Component for Picker<T> {
}
return close_fn;
}
+ KeyEvent {
+ code: KeyCode::Char(' '),
+ modifiers: KeyModifiers::CONTROL,
+ } => {
+ self.save_filter();
+ }
_ => {
if let EventResult::Consumed(_) = self.prompt.handle_event(event, cx) {
// TODO: recalculate only if pattern changed
diff --git a/helix-term/src/ui/prompt.rs b/helix-term/src/ui/prompt.rs
index 433de15e..c388c315 100644
--- a/helix-term/src/ui/prompt.rs
+++ b/helix-term/src/ui/prompt.rs
@@ -106,6 +106,13 @@ impl Prompt {
self.exit_selection();
}
+ pub fn clear(&mut self) {
+ self.line.clear();
+ self.cursor = 0;
+ self.completion = (self.completion_fn)(&self.line);
+ self.exit_selection();
+ }
+
pub fn change_completion_selection(&mut self, direction: CompletionDirection) {
if self.completion.is_empty() {
return;