@@ -38,6 +38,7 @@ pub struct FuzzySelect<'a> {
38
38
report : bool ,
39
39
clear : bool ,
40
40
highlight_matches : bool ,
41
+ enable_vim_mode : bool ,
41
42
max_length : Option < usize > ,
42
43
theme : & ' a dyn Theme ,
43
44
/// Search string that a fuzzy search with start with.
@@ -118,6 +119,17 @@ impl FuzzySelect<'_> {
118
119
self
119
120
}
120
121
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
+
121
133
/// Sets the maximum number of visible options.
122
134
///
123
135
/// The default is the height of the terminal minus 2.
@@ -209,6 +221,8 @@ impl FuzzySelect<'_> {
209
221
210
222
term. hide_cursor ( ) ?;
211
223
224
+ let mut vim_mode = false ;
225
+
212
226
loop {
213
227
render. clear ( ) ?;
214
228
render. fuzzy_select_prompt ( self . prompt . as_str ( ) , & search_term, position) ?;
@@ -240,16 +254,24 @@ impl FuzzySelect<'_> {
240
254
}
241
255
term. flush ( ) ?;
242
256
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 => {
245
262
if self . clear {
246
263
render. clear ( ) ?;
247
264
term. flush ( ) ?;
248
265
}
249
266
term. show_cursor ( ) ?;
250
267
return Ok ( None ) ;
251
268
}
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
+ {
253
275
if sel == Some ( 0 ) {
254
276
starting_row =
255
277
filtered_list. len ( ) . max ( visible_term_rows) - visible_term_rows;
@@ -266,7 +288,9 @@ impl FuzzySelect<'_> {
266
288
} ;
267
289
term. flush ( ) ?;
268
290
}
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
+ {
270
294
sel = match sel {
271
295
None => Some ( 0 ) ,
272
296
Some ( sel) => {
@@ -280,15 +304,17 @@ impl FuzzySelect<'_> {
280
304
}
281
305
term. flush ( ) ?;
282
306
}
283
- ( Key :: ArrowLeft , _) if position > 0 => {
307
+ ( Key :: ArrowLeft , _, _ ) | ( Key :: Char ( 'h' ) , _ , true ) if position > 0 => {
284
308
position -= 1 ;
285
309
term. flush ( ) ?;
286
310
}
287
- ( Key :: ArrowRight , _) if position < search_term. len ( ) => {
311
+ ( Key :: ArrowRight , _, _) | ( Key :: Char ( 'l' ) , _, true )
312
+ if position < search_term. len ( ) =>
313
+ {
288
314
position += 1 ;
289
315
term. flush ( ) ?;
290
316
}
291
- ( Key :: Enter , Some ( sel) ) if !filtered_list. is_empty ( ) => {
317
+ ( Key :: Enter , Some ( sel) , _ ) if !filtered_list. is_empty ( ) => {
292
318
if self . clear {
293
319
render. clear ( ) ?;
294
320
}
@@ -305,12 +331,12 @@ impl FuzzySelect<'_> {
305
331
term. show_cursor ( ) ?;
306
332
return Ok ( sel_string_pos_in_items) ;
307
333
}
308
- ( Key :: Backspace , _) if position > 0 => {
334
+ ( Key :: Backspace , _, _ ) if position > 0 => {
309
335
position -= 1 ;
310
336
search_term. remove ( position) ;
311
337
term. flush ( ) ?;
312
338
}
313
- ( Key :: Char ( chr) , _) if !chr. is_ascii_control ( ) => {
339
+ ( Key :: Char ( chr) , _, _ ) if !chr. is_ascii_control ( ) => {
314
340
search_term. insert ( position, chr) ;
315
341
position += 1 ;
316
342
term. flush ( ) ?;
@@ -349,6 +375,7 @@ impl<'a> FuzzySelect<'a> {
349
375
report : true ,
350
376
clear : true ,
351
377
highlight_matches : true ,
378
+ enable_vim_mode : false ,
352
379
max_length : None ,
353
380
theme,
354
381
initial_text : "" . into ( ) ,
0 commit comments