|
|
@ -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
|
|
|
|