@@ -133,33 +133,45 @@ impl App<'_> {
133133 }
134134 }
135135
136- match self . keybind . get ( & key) {
137- Some ( UserEvent :: ForceQuit ) => {
136+ let user_event = self . keybind . get ( & key) ;
137+
138+ if let Some ( UserEvent :: Cancel ) = user_event {
139+ if !self . numeric_prefix . is_empty ( ) {
140+ // Clear numeric prefix and cancel the event
138141 self . numeric_prefix . clear ( ) ;
142+ continue ;
143+ }
144+ }
145+
146+ match user_event {
147+ Some ( UserEvent :: ForceQuit ) => {
139148 self . tx . send ( AppEvent :: Quit ) ;
140149 }
141150 Some ( ue) => {
142- let event_with_count = self . process_numeric_prefix ( * ue, key) ;
143- if let Some ( event_with_count) = event_with_count {
144- self . view . handle_event_with_count ( event_with_count, key) ;
145- self . numeric_prefix . clear ( ) ;
146- }
151+ let event_with_count =
152+ process_numeric_prefix ( & self . numeric_prefix , * ue, key) ;
153+ self . view . handle_event ( event_with_count, key) ;
154+ self . numeric_prefix . clear ( ) ;
147155 }
148156 None => {
149- if let KeyCode :: Char ( c) = key. code {
157+ if let StatusLine :: Input ( _, _, _) = self . status_line {
158+ // In input mode, pass all key events to the view
159+ // fixme: currently, the only thing that processes key_event is searching the list,
160+ // so this probably works, but it's not the right process...
161+ self . numeric_prefix . clear ( ) ;
162+ self . view . handle_event (
163+ UserEventWithCount :: from_event ( UserEvent :: Unknown ) ,
164+ key,
165+ ) ;
166+ } else if let KeyCode :: Char ( c) = key. code {
167+ // Accumulate numeric prefix
150168 if c. is_ascii_digit ( )
151169 && ( c != '0' || !self . numeric_prefix . is_empty ( ) )
152170 {
153171 self . numeric_prefix . push ( c) ;
154172 continue ;
155173 }
156174 }
157-
158- self . numeric_prefix . clear ( ) ;
159- self . view . handle_event_with_count (
160- UserEventWithCount :: from_event ( UserEvent :: Unknown ) ,
161- key,
162- ) ;
163175 }
164176 }
165177 }
@@ -235,7 +247,13 @@ impl App<'_> {
235247impl App < ' _ > {
236248 fn render_status_line ( & self , f : & mut Frame , area : Rect ) {
237249 let text: Line = match & self . status_line {
238- StatusLine :: None => "" . into ( ) ,
250+ StatusLine :: None => {
251+ if self . numeric_prefix . is_empty ( ) {
252+ Line :: raw ( "" )
253+ } else {
254+ Line :: raw ( self . numeric_prefix . as_str ( ) ) . fg ( self . color_theme . status_input_fg )
255+ }
256+ }
239257 StatusLine :: Input ( msg, _, transient_msg) => {
240258 let msg_w = console:: measure_text_width ( msg. as_str ( ) ) ;
241259 if let Some ( t_msg) = transient_msg {
@@ -287,38 +305,6 @@ impl App<'_> {
287305}
288306
289307impl App < ' _ > {
290- fn process_numeric_prefix (
291- & self ,
292- user_event : UserEvent ,
293- _key : KeyEvent ,
294- ) -> Option < UserEventWithCount > {
295- let count = if self . numeric_prefix . is_empty ( ) {
296- 1
297- } else {
298- self . numeric_prefix . parse :: < usize > ( ) . unwrap_or ( 1 )
299- } ;
300-
301- match user_event {
302- UserEvent :: NavigateUp
303- | UserEvent :: NavigateDown
304- | UserEvent :: NavigateLeft
305- | UserEvent :: NavigateRight
306- | UserEvent :: ScrollUp
307- | UserEvent :: ScrollDown
308- | UserEvent :: PageUp
309- | UserEvent :: PageDown
310- | UserEvent :: HalfPageUp
311- | UserEvent :: HalfPageDown => Some ( UserEventWithCount :: new ( user_event, count) ) ,
312- _ => {
313- if self . numeric_prefix . is_empty ( ) {
314- Some ( UserEventWithCount :: new ( user_event, 1 ) )
315- } else {
316- None
317- }
318- }
319- }
320- }
321-
322308 fn open_detail ( & mut self ) {
323309 if let View :: List ( ref mut view) = self . view {
324310 let commit_list_state = view. take_list_state ( ) ;
@@ -452,150 +438,46 @@ impl App<'_> {
452438 }
453439}
454440
455- #[ cfg( test) ]
456- mod tests {
457- use super :: * ;
458-
459- // Helper function to test numeric prefix parsing logic
460- fn test_process_numeric_prefix_logic (
461- numeric_prefix : & str ,
462- user_event : UserEvent ,
463- ) -> Option < UserEventWithCount > {
441+ fn process_numeric_prefix (
442+ numeric_prefix : & str ,
443+ user_event : UserEvent ,
444+ _key_event : KeyEvent ,
445+ ) -> UserEventWithCount {
446+ if user_event. is_countable ( ) {
464447 let count = if numeric_prefix. is_empty ( ) {
465448 1
466449 } else {
467450 numeric_prefix. parse :: < usize > ( ) . unwrap_or ( 1 )
468451 } ;
469-
470- match user_event {
471- UserEvent :: NavigateUp
472- | UserEvent :: NavigateDown
473- | UserEvent :: NavigateLeft
474- | UserEvent :: NavigateRight
475- | UserEvent :: ScrollUp
476- | UserEvent :: ScrollDown
477- | UserEvent :: PageUp
478- | UserEvent :: PageDown
479- | UserEvent :: HalfPageUp
480- | UserEvent :: HalfPageDown => Some ( UserEventWithCount :: new ( user_event, count) ) ,
481- _ => {
482- if numeric_prefix. is_empty ( ) {
483- Some ( UserEventWithCount :: new ( user_event, 1 ) )
484- } else {
485- None
486- }
487- }
488- }
489- }
490-
491- #[ test]
492- fn test_process_numeric_prefix_no_prefix ( ) {
493- let result = test_process_numeric_prefix_logic ( "" , UserEvent :: NavigateDown ) ;
494-
495- assert ! ( result. is_some( ) ) ;
496- let event_with_count = result. unwrap ( ) ;
497- assert_eq ! ( event_with_count. event, UserEvent :: NavigateDown ) ;
498- assert_eq ! ( event_with_count. count, 1 ) ;
499- }
500-
501- #[ test]
502- fn test_process_numeric_prefix_with_prefix ( ) {
503- let result = test_process_numeric_prefix_logic ( "5" , UserEvent :: NavigateDown ) ;
504-
505- assert ! ( result. is_some( ) ) ;
506- let event_with_count = result. unwrap ( ) ;
507- assert_eq ! ( event_with_count. event, UserEvent :: NavigateDown ) ;
508- assert_eq ! ( event_with_count. count, 5 ) ;
509- }
510-
511- #[ test]
512- fn test_process_numeric_prefix_invalid_number ( ) {
513- let result = test_process_numeric_prefix_logic ( "abc" , UserEvent :: NavigateDown ) ;
514-
515- assert ! ( result. is_some( ) ) ;
516- let event_with_count = result. unwrap ( ) ;
517- assert_eq ! ( event_with_count. event, UserEvent :: NavigateDown ) ;
518- assert_eq ! ( event_with_count. count, 1 ) ; // Should fallback to 1
519- }
520-
521- #[ test]
522- fn test_process_numeric_prefix_countable_events ( ) {
523- let countable_events = [
524- UserEvent :: NavigateUp ,
525- UserEvent :: NavigateDown ,
526- UserEvent :: NavigateLeft ,
527- UserEvent :: NavigateRight ,
528- UserEvent :: ScrollUp ,
529- UserEvent :: ScrollDown ,
530- UserEvent :: PageUp ,
531- UserEvent :: PageDown ,
532- UserEvent :: HalfPageUp ,
533- UserEvent :: HalfPageDown ,
534- ] ;
535-
536- for event in countable_events {
537- let result = test_process_numeric_prefix_logic ( "3" , event) ;
538- assert ! ( result. is_some( ) ) ;
539- let event_with_count = result. unwrap ( ) ;
540- assert_eq ! ( event_with_count. event, event) ;
541- assert_eq ! ( event_with_count. count, 3 ) ;
542- }
543- }
544-
545- #[ test]
546- fn test_process_numeric_prefix_non_countable_events ( ) {
547- let non_countable_events = [
548- UserEvent :: Quit ,
549- UserEvent :: Confirm ,
550- UserEvent :: Cancel ,
551- UserEvent :: HelpToggle ,
552- UserEvent :: Search ,
553- UserEvent :: ShortCopy ,
554- UserEvent :: FullCopy ,
555- ] ;
556-
557- for event in non_countable_events {
558- let result = test_process_numeric_prefix_logic ( "5" , event) ;
559- assert ! ( result. is_none( ) ) ; // Should return None when prefix exists but event isn't countable
560- }
561- }
562-
563- #[ test]
564- fn test_process_numeric_prefix_non_countable_events_no_prefix ( ) {
565- let result = test_process_numeric_prefix_logic ( "" , UserEvent :: Confirm ) ;
566- assert ! ( result. is_some( ) ) ;
567- let event_with_count = result. unwrap ( ) ;
568- assert_eq ! ( event_with_count. event, UserEvent :: Confirm ) ;
569- assert_eq ! ( event_with_count. count, 1 ) ;
570- }
571-
572- #[ test]
573- fn test_process_numeric_prefix_large_numbers ( ) {
574- let result = test_process_numeric_prefix_logic ( "999" , UserEvent :: NavigateDown ) ;
575-
576- assert ! ( result. is_some( ) ) ;
577- let event_with_count = result. unwrap ( ) ;
578- assert_eq ! ( event_with_count. event, UserEvent :: NavigateDown ) ;
579- assert_eq ! ( event_with_count. count, 999 ) ;
452+ UserEventWithCount :: new ( user_event, count)
453+ } else {
454+ UserEventWithCount :: from_event ( user_event)
580455 }
456+ }
581457
582- #[ test]
583- fn test_process_numeric_prefix_zero ( ) {
584- let result = test_process_numeric_prefix_logic ( "0" , UserEvent :: NavigateUp ) ;
585-
586- assert ! ( result. is_some( ) ) ;
587- let event_with_count = result. unwrap ( ) ;
588- assert_eq ! ( event_with_count. event, UserEvent :: NavigateUp ) ;
589- assert_eq ! ( event_with_count. count, 1 ) ; // UserEventWithCount::new converts 0 to 1
590- }
458+ #[ cfg( test) ]
459+ mod tests {
460+ use rstest:: rstest;
591461
592- #[ test]
593- fn test_process_numeric_prefix_multi_digit ( ) {
594- let result = test_process_numeric_prefix_logic ( "42" , UserEvent :: ScrollDown ) ;
462+ use super :: * ;
595463
596- assert ! ( result. is_some( ) ) ;
597- let event_with_count = result. unwrap ( ) ;
598- assert_eq ! ( event_with_count. event, UserEvent :: ScrollDown ) ;
599- assert_eq ! ( event_with_count. count, 42 ) ;
464+ #[ rustfmt:: skip]
465+ #[ rstest]
466+ #[ case( "" , UserEvent :: NavigateDown , UserEventWithCount :: new( UserEvent :: NavigateDown , 1 ) ) ] // no prefix
467+ #[ case( "5" , UserEvent :: NavigateUp , UserEventWithCount :: new( UserEvent :: NavigateUp , 5 ) ) ] // with prefix
468+ #[ case( "0" , UserEvent :: PageDown , UserEventWithCount :: new( UserEvent :: PageDown , 1 ) ) ] // zero should be converted to 1
469+ #[ case( "42" , UserEvent :: ScrollDown , UserEventWithCount :: new( UserEvent :: ScrollDown , 42 ) ) ] // multi-digit number
470+ #[ case( "999" , UserEvent :: PageDown , UserEventWithCount :: new( UserEvent :: PageDown , 999 ) ) ] // large number
471+ #[ case( "abc" , UserEvent :: ScrollUp , UserEventWithCount :: new( UserEvent :: ScrollUp , 1 ) ) ] // should fallback to 1
472+ #[ case( "5" , UserEvent :: Quit , UserEventWithCount :: new( UserEvent :: Quit , 1 ) ) ] // non-countable event with prefix
473+ #[ case( "" , UserEvent :: Confirm , UserEventWithCount :: new( UserEvent :: Confirm , 1 ) ) ] // non-countable event without prefix
474+ fn test_process_numeric_prefix (
475+ #[ case] numeric_prefix : & str ,
476+ #[ case] user_event : UserEvent ,
477+ #[ case] expected : UserEventWithCount ,
478+ ) {
479+ let dummy_key_event = KeyEvent :: from ( KeyCode :: Enter ) ; // KeyEvent is not used in the logic
480+ let actual = process_numeric_prefix ( numeric_prefix, user_event, dummy_key_event) ;
481+ assert_eq ! ( actual, expected) ;
600482 }
601483}
0 commit comments