Skip to main content

j_cli/command/help/
mod.rs

1pub mod app;
2pub mod ui;
3
4use crossterm::{
5    event::{self, Event, KeyCode, KeyModifiers},
6    execute,
7    terminal::{self, EnterAlternateScreen, LeaveAlternateScreen},
8};
9use ratatui::{Terminal, backend::CrosstermBackend};
10use std::io;
11
12use app::HelpApp;
13use ui::draw_help_ui;
14
15/// 处理 help 命令:启动 TUI 帮助界面
16pub fn handle_help() {
17    match run_help_tui() {
18        Ok(_) => {}
19        Err(e) => {
20            eprintln!("TUI 启动失败: {}", e);
21        }
22    }
23}
24
25fn run_help_tui() -> io::Result<()> {
26    terminal::enable_raw_mode()?;
27    let mut stdout = io::stdout();
28    execute!(stdout, EnterAlternateScreen)?;
29
30    let backend = CrosstermBackend::new(stdout);
31    let mut terminal = Terminal::new(backend)?;
32
33    let mut app = HelpApp::new();
34
35    loop {
36        terminal.draw(|f| draw_help_ui(f, &mut app))?;
37
38        if event::poll(std::time::Duration::from_millis(100))? {
39            match event::read()? {
40                Event::Key(key) => {
41                    match key.code {
42                        // 退出
43                        KeyCode::Char('q') | KeyCode::Esc => break,
44                        KeyCode::Char('c') if key.modifiers.contains(KeyModifiers::CONTROL) => {
45                            break;
46                        }
47
48                        // Tab 切换
49                        KeyCode::Right | KeyCode::Char('l') => app.next_tab(),
50                        KeyCode::Left | KeyCode::Char('h') => app.prev_tab(),
51                        KeyCode::Tab => {
52                            if key.modifiers.contains(KeyModifiers::SHIFT) {
53                                app.prev_tab();
54                            } else {
55                                app.next_tab();
56                            }
57                        }
58                        KeyCode::BackTab => app.prev_tab(),
59
60                        // 数字键跳转
61                        KeyCode::Char(c @ '1'..='9') => {
62                            let idx = (c as usize) - ('1' as usize);
63                            app.goto_tab(idx);
64                        }
65                        KeyCode::Char('0') => app.goto_tab(9),
66
67                        // 滚动
68                        KeyCode::Down | KeyCode::Char('j') => app.scroll_down(1),
69                        KeyCode::Up | KeyCode::Char('k') => app.scroll_up(1),
70                        KeyCode::PageDown => app.scroll_down(10),
71                        KeyCode::PageUp => app.scroll_up(10),
72                        KeyCode::Home => app.scroll_to_top(),
73                        KeyCode::End => app.scroll_to_bottom(),
74
75                        _ => {}
76                    }
77                }
78                Event::Resize(_, _) => {
79                    app.invalidate_cache();
80                }
81                _ => {}
82            }
83        }
84    }
85
86    terminal::disable_raw_mode()?;
87    execute!(terminal.backend_mut(), LeaveAlternateScreen)?;
88
89    Ok(())
90}