Skip to content

Commit c8cdaf3

Browse files
authored
Merge pull request #259 from damymetzke/fuzzy-select-vim
Add vim mode to `FuzzySelect`
2 parents d77d5cd + 4165fcb commit c8cdaf3

File tree

1 file changed

+36
-9
lines changed

1 file changed

+36
-9
lines changed

src/prompts/fuzzy_select.rs

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ pub struct FuzzySelect<'a> {
3838
report: bool,
3939
clear: bool,
4040
highlight_matches: bool,
41+
enable_vim_mode: bool,
4142
max_length: Option<usize>,
4243
theme: &'a dyn Theme,
4344
/// Search string that a fuzzy search with start with.
@@ -118,6 +119,17 @@ impl FuzzySelect<'_> {
118119
self
119120
}
120121

122+
/// Indicated whether to allow the use of vim mode
123+
///
124+
/// Vim mode can be entered by pressing Escape.
125+
/// This then allows the user to navigate using hjkl.
126+
///
127+
/// The default is to disable vim mode.
128+
pub fn vim_mode(mut self, val: bool) -> Self {
129+
self.enable_vim_mode = val;
130+
self
131+
}
132+
121133
/// Sets the maximum number of visible options.
122134
///
123135
/// The default is the height of the terminal minus 2.
@@ -209,6 +221,8 @@ impl FuzzySelect<'_> {
209221

210222
term.hide_cursor()?;
211223

224+
let mut vim_mode = false;
225+
212226
loop {
213227
render.clear()?;
214228
render.fuzzy_select_prompt(self.prompt.as_str(), &search_term, position)?;
@@ -240,16 +254,24 @@ impl FuzzySelect<'_> {
240254
}
241255
term.flush()?;
242256

243-
match (term.read_key()?, sel) {
244-
(Key::Escape, _) if allow_quit => {
257+
match (term.read_key()?, sel, vim_mode) {
258+
(Key::Escape, _, false) if self.enable_vim_mode => {
259+
vim_mode = true;
260+
}
261+
(Key::Escape, _, false) | (Key::Char('q'), _, true) if allow_quit => {
245262
if self.clear {
246263
render.clear()?;
247264
term.flush()?;
248265
}
249266
term.show_cursor()?;
250267
return Ok(None);
251268
}
252-
(Key::ArrowUp | Key::BackTab, _) if !filtered_list.is_empty() => {
269+
(Key::Char('i' | 'a'), _, true) => {
270+
vim_mode = false;
271+
}
272+
(Key::ArrowUp | Key::BackTab, _, _) | (Key::Char('k'), _, true)
273+
if !filtered_list.is_empty() =>
274+
{
253275
if sel == Some(0) {
254276
starting_row =
255277
filtered_list.len().max(visible_term_rows) - visible_term_rows;
@@ -266,7 +288,9 @@ impl FuzzySelect<'_> {
266288
};
267289
term.flush()?;
268290
}
269-
(Key::ArrowDown | Key::Tab, _) if !filtered_list.is_empty() => {
291+
(Key::ArrowDown | Key::Tab, _, _) | (Key::Char('j'), _, true)
292+
if !filtered_list.is_empty() =>
293+
{
270294
sel = match sel {
271295
None => Some(0),
272296
Some(sel) => {
@@ -280,15 +304,17 @@ impl FuzzySelect<'_> {
280304
}
281305
term.flush()?;
282306
}
283-
(Key::ArrowLeft, _) if position > 0 => {
307+
(Key::ArrowLeft, _, _) | (Key::Char('h'), _, true) if position > 0 => {
284308
position -= 1;
285309
term.flush()?;
286310
}
287-
(Key::ArrowRight, _) if position < search_term.len() => {
311+
(Key::ArrowRight, _, _) | (Key::Char('l'), _, true)
312+
if position < search_term.len() =>
313+
{
288314
position += 1;
289315
term.flush()?;
290316
}
291-
(Key::Enter, Some(sel)) if !filtered_list.is_empty() => {
317+
(Key::Enter, Some(sel), _) if !filtered_list.is_empty() => {
292318
if self.clear {
293319
render.clear()?;
294320
}
@@ -305,12 +331,12 @@ impl FuzzySelect<'_> {
305331
term.show_cursor()?;
306332
return Ok(sel_string_pos_in_items);
307333
}
308-
(Key::Backspace, _) if position > 0 => {
334+
(Key::Backspace, _, _) if position > 0 => {
309335
position -= 1;
310336
search_term.remove(position);
311337
term.flush()?;
312338
}
313-
(Key::Char(chr), _) if !chr.is_ascii_control() => {
339+
(Key::Char(chr), _, _) if !chr.is_ascii_control() => {
314340
search_term.insert(position, chr);
315341
position += 1;
316342
term.flush()?;
@@ -349,6 +375,7 @@ impl<'a> FuzzySelect<'a> {
349375
report: true,
350376
clear: true,
351377
highlight_matches: true,
378+
enable_vim_mode: false,
352379
max_length: None,
353380
theme,
354381
initial_text: "".into(),

0 commit comments

Comments
 (0)