mirror of https://github.com/helix-editor/helix
Add filter ability to picker
Inspired by doom emacs. Able to filter picker options multiple times.pull/262/head
parent
7c2fb92c91
commit
002f1ad397
|
@ -169,3 +169,17 @@ This layer is a kludge of mappings I had under leader key in neovim.
|
||||||
| s | Open symbol picker (current document)|
|
| s | Open symbol picker (current document)|
|
||||||
| w | Enter window mode |
|
| w | Enter window mode |
|
||||||
| space | Keep primary selection TODO: it's here because space mode replaced it |
|
| 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 |
|
||||||
|
|
|
@ -23,6 +23,8 @@ pub struct Picker<T> {
|
||||||
matcher: Box<Matcher>,
|
matcher: Box<Matcher>,
|
||||||
/// (index, score)
|
/// (index, score)
|
||||||
matches: Vec<(usize, i64)>,
|
matches: Vec<(usize, i64)>,
|
||||||
|
/// Filter over original options.
|
||||||
|
filters: Vec<usize>, // could be optimized into bit but not worth it now
|
||||||
|
|
||||||
cursor: usize,
|
cursor: usize,
|
||||||
// pattern: String,
|
// pattern: String,
|
||||||
|
@ -50,6 +52,7 @@ impl<T> Picker<T> {
|
||||||
options,
|
options,
|
||||||
matcher: Box::new(Matcher::default()),
|
matcher: Box::new(Matcher::default()),
|
||||||
matches: Vec::new(),
|
matches: Vec::new(),
|
||||||
|
filters: Vec::new(),
|
||||||
cursor: 0,
|
cursor: 0,
|
||||||
prompt,
|
prompt,
|
||||||
format_fn: Box::new(format_fn),
|
format_fn: Box::new(format_fn),
|
||||||
|
@ -68,6 +71,7 @@ impl<T> Picker<T> {
|
||||||
ref mut options,
|
ref mut options,
|
||||||
ref mut matcher,
|
ref mut matcher,
|
||||||
ref mut matches,
|
ref mut matches,
|
||||||
|
ref filters,
|
||||||
ref format_fn,
|
ref format_fn,
|
||||||
..
|
..
|
||||||
} = *self;
|
} = *self;
|
||||||
|
@ -81,6 +85,10 @@ impl<T> Picker<T> {
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.filter_map(|(index, option)| {
|
.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
|
// TODO: maybe using format_fn isn't the best idea here
|
||||||
let text = (format_fn)(option);
|
let text = (format_fn)(option);
|
||||||
// TODO: using fuzzy_indices could give us the char idx for match highlighting
|
// TODO: using fuzzy_indices could give us the char idx for match highlighting
|
||||||
|
@ -114,6 +122,14 @@ impl<T> Picker<T> {
|
||||||
.get(self.cursor)
|
.get(self.cursor)
|
||||||
.map(|(index, _score)| &self.options[*index])
|
.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:
|
// process:
|
||||||
|
@ -205,6 +221,12 @@ impl<T: 'static> Component for Picker<T> {
|
||||||
}
|
}
|
||||||
return close_fn;
|
return close_fn;
|
||||||
}
|
}
|
||||||
|
KeyEvent {
|
||||||
|
code: KeyCode::Char(' '),
|
||||||
|
modifiers: KeyModifiers::CONTROL,
|
||||||
|
} => {
|
||||||
|
self.save_filter();
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if let EventResult::Consumed(_) = self.prompt.handle_event(event, cx) {
|
if let EventResult::Consumed(_) = self.prompt.handle_event(event, cx) {
|
||||||
// TODO: recalculate only if pattern changed
|
// TODO: recalculate only if pattern changed
|
||||||
|
|
|
@ -106,6 +106,13 @@ impl Prompt {
|
||||||
self.exit_selection();
|
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) {
|
pub fn change_completion_selection(&mut self, direction: CompletionDirection) {
|
||||||
if self.completion.is_empty() {
|
if self.completion.is_empty() {
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in New Issue