1
1
use std:: collections:: HashSet ;
2
2
3
3
use crossterm:: {
4
- event:: { KeyCode , KeyEvent , KeyModifiers } ,
4
+ event:: { KeyCode , KeyModifiers } ,
5
5
style:: { Attribute , Attributes , Color , ContentStyle } ,
6
6
} ;
7
7
use derive_builder:: Builder ;
@@ -13,7 +13,7 @@ mod content_style;
13
13
use content_style:: { content_style_serde, option_content_style_serde} ;
14
14
mod duration;
15
15
use duration:: { duration_serde, option_duration_serde} ;
16
- mod event;
16
+ pub mod event;
17
17
use event:: { EventDefSet , KeyEventDef } ;
18
18
19
19
#[ derive( Serialize , Deserialize , Builder ) ]
@@ -104,19 +104,6 @@ pub(crate) struct Config {
104
104
#[ serde( with = "content_style_serde" ) ]
105
105
#[ builder_field_attr( serde( default , with = "option_content_style_serde" ) ) ]
106
106
pub null_value_style : ContentStyle ,
107
-
108
- pub move_to_tail : EventDefSet ,
109
- pub move_to_head : EventDefSet ,
110
- pub backward : EventDefSet ,
111
- pub forward : EventDefSet ,
112
- pub completion : EventDefSet ,
113
- pub move_to_next_nearest : EventDefSet ,
114
- pub move_to_previous_nearest : EventDefSet ,
115
- pub erase : EventDefSet ,
116
- pub erase_all : EventDefSet ,
117
- pub erase_to_previous_nearest : EventDefSet ,
118
- pub erase_to_next_nearest : EventDefSet ,
119
- pub search_up : EventDefSet ,
120
107
}
121
108
122
109
impl Default for Config {
@@ -162,45 +149,11 @@ impl Default for Config {
162
149
focus_active_char_style : StyleBuilder :: new ( ) . bgc ( Color :: Magenta ) . build ( ) ,
163
150
focus_inactive_char_style : StyleBuilder :: new ( ) . build ( ) ,
164
151
inactive_item_style : StyleBuilder :: new ( ) . fgc ( Color :: Grey ) . build ( ) ,
165
- move_to_tail : EventDefSet :: from ( KeyEventDef :: new (
166
- KeyCode :: Char ( 'e' ) ,
167
- KeyModifiers :: CONTROL ,
168
- ) ) ,
169
- move_to_head : EventDefSet :: from ( KeyEventDef :: new (
170
- KeyCode :: Char ( 'a' ) ,
171
- KeyModifiers :: CONTROL ,
172
- ) ) ,
173
- backward : EventDefSet :: from ( KeyEventDef :: new ( KeyCode :: Left , KeyModifiers :: NONE ) ) ,
174
- forward : EventDefSet :: from ( KeyEventDef :: new ( KeyCode :: Right , KeyModifiers :: NONE ) ) ,
175
- completion : EventDefSet :: from ( KeyEventDef :: new ( KeyCode :: Tab , KeyModifiers :: NONE ) ) ,
176
- move_to_next_nearest : EventDefSet :: from ( KeyEventDef :: new (
177
- KeyCode :: Char ( 'f' ) ,
178
- KeyModifiers :: ALT ,
179
- ) ) ,
180
- move_to_previous_nearest : EventDefSet :: from ( KeyEventDef :: new (
181
- KeyCode :: Char ( 'b' ) ,
182
- KeyModifiers :: ALT ,
183
- ) ) ,
184
- erase : EventDefSet :: from ( KeyEventDef :: new ( KeyCode :: Backspace , KeyModifiers :: NONE ) ) ,
185
- erase_all : EventDefSet :: from ( KeyEventDef :: new (
186
- KeyCode :: Char ( 'u' ) ,
187
- KeyModifiers :: CONTROL ,
188
- ) ) ,
189
- erase_to_previous_nearest : EventDefSet :: from ( KeyEventDef :: new (
190
- KeyCode :: Char ( 'w' ) ,
191
- KeyModifiers :: CONTROL ,
192
- ) ) ,
193
- erase_to_next_nearest : EventDefSet :: from ( KeyEventDef :: new (
194
- KeyCode :: Char ( 'd' ) ,
195
- KeyModifiers :: ALT ,
196
- ) ) ,
197
- search_up : EventDefSet :: from ( KeyEventDef :: new ( KeyCode :: Up , KeyModifiers :: NONE ) ) ,
198
152
}
199
153
}
200
154
}
201
155
202
156
impl ConfigFromFile {
203
- /// Load the config from a string.
204
157
pub fn load_from ( content : & str ) -> anyhow:: Result < Self > {
205
158
toml:: from_str ( content) . map_err ( Into :: into)
206
159
}
@@ -287,149 +240,113 @@ impl Config {
287
240
if let Some ( val) = config. word_break_chars {
288
241
self . word_break_chars = val;
289
242
}
290
- if let Some ( val) = config. move_to_tail {
243
+ }
244
+ }
245
+
246
+ #[ derive( Clone , Serialize , Deserialize , Builder ) ]
247
+ #[ builder( derive( Serialize , Deserialize ) ) ]
248
+ #[ builder( name = "KeybindsFromFile" ) ]
249
+ #[ serde( deny_unknown_fields) ]
250
+ pub struct Keybinds {
251
+ pub move_to_tail : EventDefSet ,
252
+ pub backward : EventDefSet ,
253
+ pub forward : EventDefSet ,
254
+ pub completion : EventDefSet ,
255
+ pub move_to_head : EventDefSet ,
256
+ pub move_to_previous_nearest : EventDefSet ,
257
+ pub move_to_next_nearest : EventDefSet ,
258
+ pub erase : EventDefSet ,
259
+ pub erase_all : EventDefSet ,
260
+ pub erase_to_previous_nearest : EventDefSet ,
261
+ pub erase_to_next_nearest : EventDefSet ,
262
+ pub search_up : EventDefSet ,
263
+ }
264
+
265
+ impl Default for Keybinds {
266
+ fn default ( ) -> Self {
267
+ Self {
268
+ move_to_tail : EventDefSet :: from ( KeyEventDef :: new (
269
+ KeyCode :: Char ( 'e' ) ,
270
+ KeyModifiers :: CONTROL ,
271
+ ) ) ,
272
+ move_to_head : EventDefSet :: from ( KeyEventDef :: new (
273
+ KeyCode :: Char ( 'a' ) ,
274
+ KeyModifiers :: CONTROL ,
275
+ ) ) ,
276
+ backward : EventDefSet :: from ( KeyEventDef :: new ( KeyCode :: Left , KeyModifiers :: NONE ) ) ,
277
+ forward : EventDefSet :: from ( KeyEventDef :: new ( KeyCode :: Right , KeyModifiers :: NONE ) ) ,
278
+ completion : EventDefSet :: from ( KeyEventDef :: new ( KeyCode :: Tab , KeyModifiers :: NONE ) ) ,
279
+ move_to_next_nearest : EventDefSet :: from ( KeyEventDef :: new (
280
+ KeyCode :: Char ( 'f' ) ,
281
+ KeyModifiers :: ALT ,
282
+ ) ) ,
283
+ move_to_previous_nearest : EventDefSet :: from ( KeyEventDef :: new (
284
+ KeyCode :: Char ( 'b' ) ,
285
+ KeyModifiers :: ALT ,
286
+ ) ) ,
287
+ erase : EventDefSet :: from ( KeyEventDef :: new ( KeyCode :: Backspace , KeyModifiers :: NONE ) ) ,
288
+ erase_all : EventDefSet :: from ( KeyEventDef :: new (
289
+ KeyCode :: Char ( 'u' ) ,
290
+ KeyModifiers :: CONTROL ,
291
+ ) ) ,
292
+ erase_to_previous_nearest : EventDefSet :: from ( KeyEventDef :: new (
293
+ KeyCode :: Char ( 'w' ) ,
294
+ KeyModifiers :: CONTROL ,
295
+ ) ) ,
296
+ erase_to_next_nearest : EventDefSet :: from ( KeyEventDef :: new (
297
+ KeyCode :: Char ( 'd' ) ,
298
+ KeyModifiers :: ALT ,
299
+ ) ) ,
300
+ search_up : EventDefSet :: from ( KeyEventDef :: new ( KeyCode :: Up , KeyModifiers :: NONE ) ) ,
301
+ }
302
+ }
303
+ }
304
+
305
+ impl KeybindsFromFile {
306
+ /// Load the config from a string.
307
+ pub fn load_from ( content : & str ) -> anyhow:: Result < Self > {
308
+ toml:: from_str ( content) . map_err ( Into :: into)
309
+ }
310
+ }
311
+
312
+ impl Keybinds {
313
+ pub fn patch_with ( & mut self , keybinds : KeybindsFromFile ) {
314
+ // TODO: This is awful verbose. Can we do better?
315
+ if let Some ( val) = keybinds. move_to_tail {
291
316
self . move_to_tail = val;
292
317
}
293
- if let Some ( val) = config . move_to_head {
318
+ if let Some ( val) = keybinds . move_to_head {
294
319
self . move_to_head = val;
295
320
}
296
- if let Some ( val) = config . backward {
321
+ if let Some ( val) = keybinds . backward {
297
322
self . backward = val;
298
323
}
299
- if let Some ( val) = config . forward {
324
+ if let Some ( val) = keybinds . forward {
300
325
self . forward = val;
301
326
}
302
- if let Some ( val) = config . completion {
327
+ if let Some ( val) = keybinds . completion {
303
328
self . completion = val;
304
329
}
305
- if let Some ( val) = config . move_to_next_nearest {
330
+ if let Some ( val) = keybinds . move_to_next_nearest {
306
331
self . move_to_next_nearest = val;
307
332
}
308
- if let Some ( val) = config . move_to_previous_nearest {
333
+ if let Some ( val) = keybinds . move_to_previous_nearest {
309
334
self . move_to_previous_nearest = val;
310
335
}
311
- if let Some ( val) = config . erase {
336
+ if let Some ( val) = keybinds . erase {
312
337
self . erase = val;
313
338
}
314
- if let Some ( val) = config . erase_all {
339
+ if let Some ( val) = keybinds . erase_all {
315
340
self . erase_all = val;
316
341
}
317
- if let Some ( val) = config . erase_to_previous_nearest {
342
+ if let Some ( val) = keybinds . erase_to_previous_nearest {
318
343
self . erase_to_previous_nearest = val;
319
344
}
320
- if let Some ( val) = config . erase_to_next_nearest {
345
+ if let Some ( val) = keybinds . erase_to_next_nearest {
321
346
self . erase_to_next_nearest = val;
322
347
}
323
- if let Some ( val) = config . search_up {
348
+ if let Some ( val) = keybinds . search_up {
324
349
self . search_up = val;
325
350
}
326
351
}
327
352
}
328
-
329
- #[ cfg( test) ]
330
- mod tests {
331
- mod load_from {
332
- use super :: super :: * ;
333
-
334
- #[ test]
335
- fn test ( ) {
336
- let toml = r#"
337
- search_result_chunk_size = 10
338
- query_debounce_duration = "1000ms"
339
- resize_debounce_duration = "2s"
340
- search_load_chunk_size = 5
341
- focus_prefix = "❯ "
342
- spin_duration = "500ms"
343
-
344
- [active_item_style]
345
- foreground = "green"
346
-
347
- [focus_active_char_style]
348
- background = "green"
349
- underline = "red"
350
- attributes = ["Bold", "Underlined"]
351
-
352
- [move_to_tail]
353
- code = { Char = "$" }
354
- modifiers = "CONTROL"
355
- "# ;
356
-
357
- let config = ConfigFromFile :: load_from ( toml) . unwrap ( ) ;
358
-
359
- assert_eq ! ( config. search_result_chunk_size, Some ( 10 ) ) ;
360
- assert_eq ! (
361
- config. query_debounce_duration,
362
- Some ( Duration :: from_millis( 1000 ) )
363
- ) ;
364
- assert_eq ! (
365
- config. resize_debounce_duration,
366
- Some ( Duration :: from_secs( 2 ) )
367
- ) ;
368
- assert_eq ! ( config. spin_duration, Some ( Duration :: from_millis( 500 ) ) ) ;
369
- assert_eq ! ( config. search_load_chunk_size, Some ( 5 ) ) ;
370
- assert_eq ! (
371
- config. active_item_style,
372
- Some ( StyleBuilder :: new( ) . fgc( Color :: Green ) . build( ) ) ,
373
- ) ;
374
-
375
- assert_eq ! (
376
- config. move_to_tail,
377
- Some ( EventDefSet :: from( KeyEventDef :: new(
378
- KeyCode :: Char ( '$' ) ,
379
- KeyModifiers :: CONTROL
380
- ) ) )
381
- ) ;
382
-
383
- assert_eq ! ( config. focus_prefix, Some ( "❯ " . to_string( ) ) ) ;
384
-
385
- assert_eq ! (
386
- config. focus_active_char_style,
387
- Some (
388
- StyleBuilder :: new( )
389
- . bgc( Color :: Green )
390
- . ulc( Color :: Red )
391
- . attrs( Attributes :: from( Attribute :: Bold ) | Attribute :: Underlined )
392
- . build( )
393
- ) ,
394
- ) ;
395
-
396
- // Check the part of the config that was not set in the toml
397
- assert_eq ! ( config. backward, None ) ;
398
- assert_eq ! ( config. forward, None ) ;
399
- assert_eq ! ( config. completion, None ) ;
400
- }
401
-
402
- #[ test]
403
- fn test_with_empty ( ) {
404
- let toml = "" ;
405
- let config = ConfigFromFile :: load_from ( toml) . unwrap ( ) ;
406
-
407
- assert_eq ! ( config. search_result_chunk_size, None ) ;
408
- assert_eq ! ( config. query_debounce_duration, None ) ;
409
- assert_eq ! ( config. resize_debounce_duration, None ) ;
410
- assert_eq ! ( config. spin_duration, None ) ;
411
- assert_eq ! ( config. search_load_chunk_size, None ) ;
412
- assert_eq ! ( config. active_item_style, None ) ;
413
- assert_eq ! ( config. inactive_item_style, None ) ;
414
- assert_eq ! ( config. focus_prefix, None ) ;
415
- assert_eq ! ( config. focus_active_char_style, None ) ;
416
- assert_eq ! ( config. move_to_tail, None ) ;
417
- assert_eq ! ( config. move_to_head, None ) ;
418
- }
419
- }
420
-
421
- mod patch_with {
422
- use super :: super :: * ;
423
-
424
- #[ test]
425
- fn test ( ) {
426
- let mut config = Config :: default ( ) ;
427
- let config_from_file = ConfigFromFile {
428
- focus_prefix : Some ( ":)" . to_string ( ) ) ,
429
- ..Default :: default ( )
430
- } ;
431
- config. patch_with ( config_from_file) ;
432
- assert_eq ! ( config. focus_prefix, ":)" . to_string( ) ) ;
433
- }
434
- }
435
- }
0 commit comments