diff options
Diffstat (limited to 'makima/src/daemon/tui/event.rs')
| -rw-r--r-- | makima/src/daemon/tui/event.rs | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/makima/src/daemon/tui/event.rs b/makima/src/daemon/tui/event.rs new file mode 100644 index 0000000..12a6890 --- /dev/null +++ b/makima/src/daemon/tui/event.rs @@ -0,0 +1,118 @@ +//! TUI event handling. + +use crossterm::event::{self, Event, KeyCode, KeyEvent, KeyModifiers}; +use std::time::Duration; + +use super::app::{Action, App, InputMode}; + +/// Poll for events with timeout +pub fn poll_event(timeout: Duration) -> std::io::Result<Option<Event>> { + if event::poll(timeout)? { + Ok(Some(event::read()?)) + } else { + Ok(None) + } +} + +/// Handle a key event and return the resulting action +pub fn handle_key_event(app: &App, key: KeyEvent) -> Action { + match app.input_mode { + InputMode::Normal => handle_normal_mode(key), + InputMode::Search => handle_search_mode(key), + InputMode::Confirm => handle_confirm_mode(key), + } +} + +/// Handle key events in normal navigation mode +fn handle_normal_mode(key: KeyEvent) -> Action { + // Check for Ctrl+C first + if key.modifiers.contains(KeyModifiers::CONTROL) { + match key.code { + KeyCode::Char('c') => return Action::Quit, + _ => {} + } + } + + match key.code { + // Navigation + KeyCode::Up | KeyCode::Char('k') => Action::Up, + KeyCode::Down | KeyCode::Char('j') => Action::Down, + + // Actions + KeyCode::Enter => Action::Select, + KeyCode::Char('e') => Action::Edit, + KeyCode::Char('d') => Action::Delete, + KeyCode::Char('c') => Action::Navigate, // cd to worktree + + // Search + KeyCode::Char('/') => Action::EnterSearch, + + // Preview toggle (space to toggle preview visibility) + KeyCode::Char(' ') => Action::Select, + + // Refresh + KeyCode::Char('r') => Action::Refresh, + + // Quit + KeyCode::Char('q') | KeyCode::Esc => Action::Quit, + + _ => Action::None, + } +} + +/// Handle key events in search mode +fn handle_search_mode(key: KeyEvent) -> Action { + // Check for Ctrl+C first + if key.modifiers.contains(KeyModifiers::CONTROL) { + match key.code { + KeyCode::Char('c') => return Action::Quit, + KeyCode::Char('u') => return Action::ClearSearch, + _ => {} + } + } + + match key.code { + // Exit search mode + KeyCode::Esc => Action::ExitSearch, + KeyCode::Enter => Action::ExitSearch, + + // Text input + KeyCode::Char(c) => Action::SearchChar(c), + KeyCode::Backspace => Action::SearchBackspace, + + // Navigation while searching + KeyCode::Up => Action::Up, + KeyCode::Down => Action::Down, + + _ => Action::None, + } +} + +/// Handle key events in confirmation mode +fn handle_confirm_mode(key: KeyEvent) -> Action { + // Check for Ctrl+C first + if key.modifiers.contains(KeyModifiers::CONTROL) { + if let KeyCode::Char('c') = key.code { + return Action::Quit; + } + } + + match key.code { + // Confirm + KeyCode::Char('y') | KeyCode::Char('Y') => Action::ConfirmYes, + + // Cancel + KeyCode::Char('n') | KeyCode::Char('N') | KeyCode::Esc => Action::ConfirmNo, + + _ => Action::None, + } +} + +/// Get help text for current mode +pub fn get_help_text(mode: InputMode) -> &'static str { + match mode { + InputMode::Normal => "j/k: navigate | Enter: details | e: edit | d: delete | c: cd | /: search | q: quit", + InputMode::Search => "Type to search | Enter/Esc: exit search | Up/Down: navigate", + InputMode::Confirm => "y: confirm | n/Esc: cancel", + } +} |
