1use std::io;
6
7use anyhow::Result;
8use crossterm::{
9 event::{
10 self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode, KeyEventKind, KeyModifiers,
11 },
12 execute,
13 terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
14};
15use ratatui::{backend::CrosstermBackend, Terminal};
16
17use super::app::{App, AppMode};
18use super::ui;
19
20pub fn run_tui() -> Result<()> {
22 enable_raw_mode()?;
24 let mut stdout = io::stdout();
25 execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?;
26 let backend = CrosstermBackend::new(stdout);
27 let mut terminal = Terminal::new(backend)?;
28
29 let mut app = App::new()?;
31
32 let res = run_app(&mut terminal, &mut app);
34
35 disable_raw_mode()?;
37 execute!(
38 terminal.backend_mut(),
39 LeaveAlternateScreen,
40 DisableMouseCapture
41 )?;
42 terminal.show_cursor()?;
43
44 if let Err(err) = res {
45 eprintln!("Error: {}", err);
46 }
47
48 Ok(())
49}
50
51fn run_app<B: ratatui::backend::Backend>(terminal: &mut Terminal<B>, app: &mut App) -> Result<()> {
53 terminal.draw(|f| ui::render(f, app))?;
55
56 loop {
57 if let Event::Key(key) = event::read()? {
59 if key.kind != KeyEventKind::Press {
61 continue;
62 }
63
64 app.status_message = None;
66
67 if app.filter_active {
69 match key.code {
70 KeyCode::Enter => app.confirm_filter(),
71 KeyCode::Esc => app.cancel_filter(),
72 KeyCode::Backspace => app.filter_backspace(),
73 KeyCode::Char(c) => app.filter_input(c),
74 _ => {}
75 }
76 terminal.draw(|f| ui::render(f, app))?;
77 continue;
78 }
79
80 if app.mode == AppMode::Help {
82 app.back();
83 terminal.draw(|f| ui::render(f, app))?;
84 continue;
85 }
86
87 match key.code {
89 KeyCode::Char('q') => {
90 return Ok(());
91 }
92 KeyCode::Char('c') if key.modifiers.contains(KeyModifiers::CONTROL) => {
93 return Ok(());
94 }
95 KeyCode::Char('?') => {
96 app.toggle_help();
97 }
98 KeyCode::Char('j') | KeyCode::Down => {
99 app.navigate_down();
100 }
101 KeyCode::Char('k') | KeyCode::Up => {
102 app.navigate_up();
103 }
104 KeyCode::Char('g') => {
105 app.go_to_top();
106 }
107 KeyCode::Char('G') => {
108 app.go_to_bottom();
109 }
110 KeyCode::PageUp => {
111 app.page_up();
112 }
113 KeyCode::PageDown => {
114 app.page_down();
115 }
116 KeyCode::Enter => {
117 app.enter();
118 }
119 KeyCode::Esc | KeyCode::Backspace => {
120 app.back();
121 }
122 KeyCode::Char('/') if app.mode == AppMode::Workspaces => {
123 app.start_filter();
124 }
125 KeyCode::Char('r') => {
126 app.refresh();
127 }
128 _ => continue, }
130
131 terminal.draw(|f| ui::render(f, app))?;
133 }
134 }
135}