Skip to content

Commit

Permalink
Add filter ability to picker
Browse files Browse the repository at this point in the history
Inspired by doom emacs. Able to filter picker options multiple times.
  • Loading branch information
pickfire committed Jun 12, 2021
1 parent 45793d7 commit 2468b9d
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 0 deletions.
14 changes: 14 additions & 0 deletions book/src/keymap.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,17 @@ This layer is a kludge of mappings I had under leader key in neovim.
| b | Open buffer picker |
| w | Enter window mode |
| space | Keep primary selection TODO: it's here because space mode replaced it |

# Picker

Keys to use within picker.

| Key | Description |
|-----|-------------|
| up, ctrl-p | Previous entry |
| down, ctrl-n | Next entry |
| ctrl-space | Filter options |
| enter | Open selected |
| ctrl-h | Open horizontally |
| ctrl-v | Open vertically |
| escape, ctrl-c | Close picker |
22 changes: 22 additions & 0 deletions helix-term/src/ui/picker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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),
Expand All @@ -68,6 +71,7 @@ impl<T> Picker<T> {
ref mut options,
ref mut matcher,
ref mut matches,
ref filters,
ref format_fn,
..
} = *self;
Expand All @@ -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
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down
7 changes: 7 additions & 0 deletions helix-term/src/ui/prompt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,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;
Expand Down

0 comments on commit 2468b9d

Please sign in to comment.