@@ -6,17 +6,17 @@ use crossterm::{
66 KeyModifiers ,
77 } ,
88 execute,
9- terminal:: { EnterAlternateScreen , LeaveAlternateScreen , disable_raw_mode , enable_raw_mode } ,
9+ terminal:: { disable_raw_mode , enable_raw_mode , EnterAlternateScreen , LeaveAlternateScreen } ,
1010} ;
1111use std:: sync:: Arc ;
1212use std:: time:: { Duration , Instant } ;
1313use tui:: {
14- Terminal ,
1514 backend:: CrosstermBackend ,
1615 layout:: { Constraint , Direction , Layout , Rect } ,
1716 style:: { Color , Modifier , Style } ,
1817 text:: { Span , Spans } ,
1918 widgets:: { Block , Borders , List , ListItem , ListState , Paragraph , Wrap } ,
19+ Terminal ,
2020} ;
2121
2222const PAGE_SIZE : usize = 30 ;
@@ -71,6 +71,14 @@ enum PageSource {
7171 Tldr ,
7272}
7373
74+ fn scroll_to_top ( app : & mut AppState ) {
75+ app. man_page . scroll = 0 ;
76+ }
77+
78+ fn scroll_to_bottom ( app : & mut AppState ) {
79+ app. man_page . scroll = app. man_page . content . len ( ) . saturating_sub ( PAGE_SIZE ) ;
80+ }
81+
7482/// Runs the TUI application
7583pub async fn run_tui ( man_db : ManDb ) -> Result < ( ) > {
7684 enable_raw_mode ( ) ?;
@@ -129,10 +137,13 @@ pub async fn run_tui(man_db: ManDb) -> Result<()> {
129137
130138 // Handle Ctrl combinations first
131139 if let KeyEvent {
132- code : KeyCode :: Char ( 'c' ) ,
133- modifiers : KeyModifiers :: CONTROL ,
134- ..
135- } = key { break }
140+ code : KeyCode :: Char ( 'c' ) ,
141+ modifiers : KeyModifiers :: CONTROL ,
142+ ..
143+ } = key
144+ {
145+ break ;
146+ }
136147
137148 match key. code {
138149 KeyCode :: Char ( 'q' ) => break ,
@@ -149,6 +160,20 @@ pub async fn run_tui(man_db: ManDb) -> Result<()> {
149160 }
150161 _ => handle_key ( & mut app, key) . await ,
151162 }
163+
164+ match key {
165+ KeyEvent {
166+ code : KeyCode :: Home ,
167+ modifiers : KeyModifiers :: CONTROL ,
168+ ..
169+ } => scroll_to_top ( & mut app) , // Исправлено: добавлено &mut
170+ KeyEvent {
171+ code : KeyCode :: End ,
172+ modifiers : KeyModifiers :: CONTROL ,
173+ ..
174+ } => scroll_to_bottom ( & mut app) , // Исправлено: добавлено &mut
175+ _ => { }
176+ }
152177 }
153178 }
154179
@@ -224,6 +249,18 @@ async fn handle_command_list_keys(app: &mut AppState, key: KeyEvent) {
224249 app. last_input_time = Instant :: now ( ) ;
225250 }
226251 }
252+ KeyCode :: Home if commands_len > 0 => {
253+ app. command_list . selected_idx = 0 ;
254+ update_list_scroll ( app) ;
255+ app. pending_man_load = true ;
256+ app. last_input_time = Instant :: now ( ) ;
257+ }
258+ KeyCode :: End if commands_len > 0 => {
259+ app. command_list . selected_idx = commands_len - 1 ;
260+ update_list_scroll ( app) ;
261+ app. pending_man_load = true ;
262+ app. last_input_time = Instant :: now ( ) ;
263+ }
227264 KeyCode :: PageUp if commands_len > 0 => {
228265 app. command_list . selected_idx = app
229266 . command_list
@@ -254,7 +291,11 @@ fn update_list_scroll(app: &mut AppState) {
254291 let visible_height = app. command_list . visible_range . 1 - app. command_list . visible_range . 0 ;
255292 let selected_idx = app. command_list . selected_idx ;
256293
257- if selected_idx < app. command_list . list_scroll {
294+ if selected_idx == 0 {
295+ app. command_list . list_scroll = 0 ;
296+ } else if selected_idx == app. command_list . filtered_commands . len ( ) - 1 {
297+ app. command_list . list_scroll = selected_idx. saturating_sub ( visible_height - 1 ) ;
298+ } else if selected_idx < app. command_list . list_scroll {
258299 app. command_list . list_scroll = selected_idx;
259300 } else if selected_idx >= app. command_list . list_scroll + visible_height {
260301 app. command_list . list_scroll = selected_idx - visible_height + 1 ;
@@ -304,8 +345,16 @@ async fn load_current_page(app: &mut AppState) {
304345
305346fn handle_man_page_keys ( app : & mut AppState , key : KeyEvent ) {
306347 match key. code {
348+ KeyCode :: Char ( 'f' ) => {
349+ app. focus = Focus :: Search ;
350+ app. search . query . clear ( ) ;
351+ }
307352 KeyCode :: Up => app. man_page . scroll = app. man_page . scroll . saturating_sub ( 1 ) ,
308353 KeyCode :: Down => app. man_page . scroll = app. man_page . scroll . saturating_add ( 1 ) ,
354+ KeyCode :: Home => app. man_page . scroll = 0 ,
355+ KeyCode :: End => {
356+ app. man_page . scroll = app. man_page . content . len ( ) . saturating_sub ( PAGE_SIZE )
357+ }
309358 KeyCode :: PageUp => app. man_page . scroll = app. man_page . scroll . saturating_sub ( PAGE_SIZE ) ,
310359 KeyCode :: PageDown => {
311360 app. man_page . scroll = ( app. man_page . scroll + PAGE_SIZE )
@@ -319,6 +368,8 @@ fn handle_man_page_keys(app: &mut AppState, key: KeyEvent) {
319368
320369fn handle_search_keys ( app : & mut AppState , key : KeyEvent ) {
321370 match key. code {
371+ KeyCode :: Char ( 'j' ) => next_search_match ( app) ,
372+ KeyCode :: Char ( 'k' ) => prev_search_match ( app) ,
322373 KeyCode :: Enter => {
323374 update_search_matches ( app) ;
324375 app. focus = Focus :: ManPage ;
@@ -396,7 +447,7 @@ fn render_ui<B: tui::backend::Backend>(f: &mut tui::Frame<B>, app: &mut AppState
396447 Constraint :: Length ( 3 ) ,
397448 Constraint :: Min ( 10 ) ,
398449 ]
399- . as_ref ( ) ,
450+ . as_ref ( ) ,
400451 )
401452 . split ( f. size ( ) ) ;
402453
@@ -412,18 +463,19 @@ fn render_status_bar<B: tui::backend::Backend>(f: &mut tui::Frame<B>, app: &AppS
412463 } ;
413464
414465 let status = if app. loading {
415- format ! ( "Loading {source_label }..." )
466+ format ! ( "Loading {}..." , source_label )
416467 } else {
417468 let x = & * format ! (
418- "RTFM // {source_label} PAGE [Tab:Switch /:Search n/N:Next/Prev t:Toggle]"
469+ "RTFM // {} PAGE [Tab:Switch /:Search t:Toggle Home/End]" ,
470+ source_label
419471 ) ;
420472 match app. focus {
421- Focus :: CommandList => "RTFM // COMMAND LIST [Tab:Switch]" ,
473+ Focus :: CommandList => "RTFM // COMMAND LIST [Tab:Switch Home/End ]" ,
422474 Focus :: ManPage => x,
423475 Focus :: Search => "RTFM // SEARCH MODE [Enter:Apply Esc:Cancel]" ,
424476 }
425- . parse ( )
426- . unwrap ( )
477+ . parse ( )
478+ . unwrap ( )
427479 } ;
428480
429481 let status_bar = Paragraph :: new ( status)
@@ -503,7 +555,7 @@ fn render_command_list_items<B: tui::backend::Backend>(
503555 . iter ( )
504556 . map ( |cmd| {
505557 let prefix = { " " } ;
506- ListItem :: new ( format ! ( "{prefix}{cmd}" ) )
558+ ListItem :: new ( format ! ( "{}{}" , prefix , cmd ) )
507559 } )
508560 . collect ( ) ;
509561
@@ -656,4 +708,4 @@ fn syntax_highlight(line: &str) -> Vec<Span> {
656708 }
657709
658710 spans
659- }
711+ }
0 commit comments