stax 0.29.4

Fast stacked Git branches and PRs
Documentation
use crossterm::event::{self, Event, KeyCode, KeyEvent, KeyModifiers};
use std::time::Duration;

/// Poll for keyboard events with a timeout
pub fn poll_event(timeout: Duration) -> std::io::Result<Option<Event>> {
    if event::poll(timeout)? {
        Ok(Some(event::read()?))
    } else {
        Ok(None)
    }
}

/// Key event types we care about
#[derive(Debug, Clone, PartialEq)]
pub enum KeyAction {
    // Navigation
    Up,
    Down,
    Left,
    Right,
    Enter,
    Escape,

    // Actions
    Restack,
    RestackAll,
    Submit,
    OpenPr,
    NewBranch,
    Delete,
    Rename,

    // Modes
    Search,
    Help,
    Quit,
    ReorderMode,

    // Reorder mode actions
    MoveUp,
    MoveDown,

    // Text input
    Char(char),
    Backspace,
    Home,
    End,

    // Pane navigation
    Tab,

    // Unknown
    None,
}

impl From<KeyEvent> for KeyAction {
    fn from(key: KeyEvent) -> Self {
        // Handle Ctrl+C for quit
        if key.modifiers.contains(KeyModifiers::CONTROL) {
            if let KeyCode::Char('c') = key.code {
                return KeyAction::Quit;
            }
        }

        // Handle Shift modifiers
        if key.modifiers.contains(KeyModifiers::SHIFT) {
            match key.code {
                KeyCode::Char('R') | KeyCode::Char('r') => return KeyAction::RestackAll,
                KeyCode::Char('K') | KeyCode::Char('k') => return KeyAction::MoveUp,
                KeyCode::Char('J') | KeyCode::Char('j') => return KeyAction::MoveDown,
                KeyCode::Up => return KeyAction::MoveUp,
                KeyCode::Down => return KeyAction::MoveDown,
                _ => {}
            }
        }

        match key.code {
            // Navigation
            KeyCode::Up => KeyAction::Up,
            KeyCode::Down => KeyAction::Down,
            KeyCode::Left => KeyAction::Left,
            KeyCode::Right => KeyAction::Right,
            KeyCode::Enter => KeyAction::Enter,
            KeyCode::Esc => KeyAction::Escape,
            KeyCode::Home => KeyAction::Home,
            KeyCode::End => KeyAction::End,
            KeyCode::Tab => KeyAction::Tab,

            // Vim navigation
            KeyCode::Char('k') => KeyAction::Up,
            KeyCode::Char('j') => KeyAction::Down,

            // Actions
            KeyCode::Char('r') => KeyAction::Restack,
            KeyCode::Char('s') => KeyAction::Submit,
            KeyCode::Char('p') => KeyAction::OpenPr,
            KeyCode::Char('n') => KeyAction::NewBranch,
            KeyCode::Char('d') => KeyAction::Delete,
            KeyCode::Char('e') => KeyAction::Rename,

            // Modes
            KeyCode::Char('/') => KeyAction::Search,
            KeyCode::Char('?') => KeyAction::Help,
            KeyCode::Char('q') => KeyAction::Quit,
            KeyCode::Char('o') => KeyAction::ReorderMode,

            // Text input (for search mode)
            KeyCode::Char(c) => KeyAction::Char(c),
            KeyCode::Backspace => KeyAction::Backspace,

            _ => KeyAction::None,
        }
    }
}