@@ -19,49 +19,91 @@ pub(super) enum LoopAction {
1919 Restart ,
2020}
2121
22+ fn pending_main_page_move_count ( state : & mut AppState ) -> u16 {
23+ state. take_pending_main_page_count ( ) . unwrap_or ( 1 )
24+ }
25+
2226fn handle_main_page_navigation_key ( state : & mut AppState , key : KeyEvent ) -> bool {
2327 match state. runtime . ui_keymap {
2428 UiKeymap :: Default | UiKeymap :: Custom => match key. code {
2529 KeyCode :: Char ( 'j' ) => {
30+ state. clear_pending_main_page_count ( ) ;
2631 state. move_focus_previous ( ) ;
2732 true
2833 }
2934 KeyCode :: Char ( 'l' ) => {
35+ state. clear_pending_main_page_count ( ) ;
3036 state. move_focus_next ( ) ;
3137 true
3238 }
3339 KeyCode :: Char ( 'i' ) => {
34- state. move_up ( ) ;
40+ for _ in 0 ..pending_main_page_move_count ( state) {
41+ state. move_up ( ) ;
42+ }
3543 true
3644 }
3745 KeyCode :: Char ( 'k' ) => {
38- state. move_down ( ) ;
46+ for _ in 0 ..pending_main_page_move_count ( state) {
47+ state. move_down ( ) ;
48+ }
3949 true
4050 }
4151 _ => false ,
4252 } ,
4353 UiKeymap :: Vim => match key. code {
4454 KeyCode :: Char ( 'h' ) => {
55+ state. clear_pending_main_page_count ( ) ;
4556 state. move_focus_previous ( ) ;
4657 true
4758 }
4859 KeyCode :: Char ( 'l' ) => {
60+ state. clear_pending_main_page_count ( ) ;
4961 state. move_focus_next ( ) ;
5062 true
5163 }
5264 KeyCode :: Char ( 'k' ) => {
53- state. move_up ( ) ;
65+ for _ in 0 ..pending_main_page_move_count ( state) {
66+ state. move_up ( ) ;
67+ }
5468 true
5569 }
5670 KeyCode :: Char ( 'j' ) => {
57- state. move_down ( ) ;
71+ for _ in 0 ..pending_main_page_move_count ( state) {
72+ state. move_down ( ) ;
73+ }
5874 true
5975 }
6076 _ => false ,
6177 } ,
6278 }
6379}
6480
81+ fn handle_main_page_count_prefix ( state : & mut AppState , key : KeyEvent ) -> bool {
82+ if key
83+ . modifiers
84+ . intersects ( KeyModifiers :: CONTROL | KeyModifiers :: ALT | KeyModifiers :: SUPER )
85+ {
86+ state. clear_pending_main_page_count ( ) ;
87+ return false ;
88+ }
89+
90+ let KeyCode :: Char ( character) = key. code else {
91+ return false ;
92+ } ;
93+ if !character. is_ascii_digit ( ) {
94+ return false ;
95+ }
96+ if character == '0' && !state. has_pending_main_page_count ( ) {
97+ return false ;
98+ }
99+
100+ let digit = character
101+ . to_digit ( 10 )
102+ . expect ( "ascii digit should convert to decimal" ) as u16 ;
103+ state. push_pending_main_page_count_digit ( digit) ;
104+ true
105+ }
106+
65107fn handle_vim_main_page_chord ( state : & mut AppState , key : KeyEvent ) -> Option < LoopAction > {
66108 if !matches ! ( state. runtime. ui_keymap, UiKeymap :: Vim ) {
67109 state. pending_main_page_chord = None ;
@@ -72,7 +114,7 @@ fn handle_vim_main_page_chord(state: &mut AppState, key: KeyEvent) -> Option<Loo
72114 . modifiers
73115 . intersects ( KeyModifiers :: CONTROL | KeyModifiers :: ALT | KeyModifiers :: SUPER )
74116 {
75- state. pending_main_page_chord = None ;
117+ state. clear_pending_main_page_inputs ( ) ;
76118 return None ;
77119 }
78120
@@ -96,15 +138,18 @@ fn handle_vim_main_page_chord(state: &mut AppState, key: KeyEvent) -> Option<Loo
96138
97139 match key. code {
98140 KeyCode :: Char ( 'g' ) => {
141+ state. clear_pending_main_page_count ( ) ;
99142 state. pending_main_page_chord =
100143 Some ( state. pending_main_page_chord_state ( PendingMainPageChord :: VimGoToFirstLine ) ) ;
101144 Some ( LoopAction :: Continue )
102145 }
103146 KeyCode :: Char ( 'G' ) => {
147+ state. clear_pending_main_page_count ( ) ;
104148 state. jump_current_pane_to_end ( ) ;
105149 Some ( LoopAction :: Continue )
106150 }
107151 KeyCode :: Char ( 'q' ) => {
152+ state. clear_pending_main_page_count ( ) ;
108153 state. pending_main_page_chord =
109154 Some ( state. pending_main_page_chord_state ( PendingMainPageChord :: VimQuit ) ) ;
110155 state. status = "press qq to quit or use command palette quit/exit" . to_string ( ) ;
@@ -130,12 +175,12 @@ pub(super) fn handle_key_event(state: &mut AppState, key: KeyEvent) -> LoopActio
130175 // Modal UI surfaces take precedence over the base page shortcuts so keys
131176 // keep local meaning while a dialog, editor, or search interaction is open.
132177 if state. config_editor . open {
133- state. pending_main_page_chord = None ;
178+ state. clear_pending_main_page_inputs ( ) ;
134179 return handle_config_editor_key_event ( state, key) ;
135180 }
136181
137182 if state. palette . open {
138- state. pending_main_page_chord = None ;
183+ state. clear_pending_main_page_inputs ( ) ;
139184 if is_palette_toggle ( key) {
140185 state. close_palette ( ) ;
141186 return LoopAction :: Continue ;
@@ -144,25 +189,30 @@ pub(super) fn handle_key_event(state: &mut AppState, key: KeyEvent) -> LoopActio
144189 }
145190
146191 if state. search . active {
147- state. pending_main_page_chord = None ;
192+ state. clear_pending_main_page_inputs ( ) ;
148193 return handle_search_key_event ( state, key) ;
149194 }
150195
151196 if state. reply_panel . is_some ( ) {
152- state. pending_main_page_chord = None ;
197+ state. clear_pending_main_page_inputs ( ) ;
153198 return handle_reply_key_event ( state, key) ;
154199 }
155200
156201 if state. is_code_edit_active ( ) {
157- state. pending_main_page_chord = None ;
202+ state. clear_pending_main_page_inputs ( ) ;
158203 return handle_code_edit_key_event ( state, key) ;
159204 }
160205
161206 if let Some ( action) = handle_vim_main_page_chord ( state, key) {
162207 return action;
163208 }
164209
210+ if handle_main_page_count_prefix ( state, key) {
211+ return LoopAction :: Continue ;
212+ }
213+
165214 if is_palette_open_shortcut ( key) {
215+ state. clear_pending_main_page_count ( ) ;
166216 state. toggle_palette ( ) ;
167217 return LoopAction :: Continue ;
168218 }
@@ -171,6 +221,8 @@ pub(super) fn handle_key_event(state: &mut AppState, key: KeyEvent) -> LoopActio
171221 return LoopAction :: Continue ;
172222 }
173223
224+ state. clear_pending_main_page_count ( ) ;
225+
174226 match key. code {
175227 KeyCode :: Char ( '/' ) => {
176228 if matches ! ( state. ui_page, UiPage :: Mail ) {
0 commit comments