xbp 10.40.0

XBP is a zero-config build pack that can also interact with proxies, kafka, sockets, synthetic monitors.
Documentation
use super::app::{App, Mode, View};
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};

#[derive(Debug, Clone)]
pub enum Action {
    None,
    Quit,
    Redraw,
    MoveUp,
    MoveDown,
    PageUp,
    PageDown,
    Top,
    Bottom,
    OpenDetail,
    Back,
    StartSearch,
    StartCommand,
    StartHelp,
    InputChar(char),
    InputBackspace,
    CommandHistoryPrev,
    CommandHistoryNext,
    RepeatLastCommand,
    CancelInput,
    SubmitInput,
    Reload,
    CycleSort,
    ToggleSortDir,
    ToggleMe,
    NextMatch,
    PrevMatch,
    StartEditTitle,
    StartComment,
    CycleStatus,
    CyclePriority,
    AssignMe,
    ViewComments,
    Undo,
}

pub fn map_key(app: &App, key: KeyEvent) -> Action {
    if app.comments_popup.is_some() {
        return match key.code {
            KeyCode::Esc | KeyCode::Char('q') | KeyCode::Char('v') => Action::CancelInput,
            _ => Action::None,
        };
    }
    match app.mode {
        Mode::Command => map_command_mode(key),
        Mode::Search | Mode::EditTitle | Mode::EditComment => map_input_mode(key),
        Mode::Help => match key.code {
            KeyCode::Esc | KeyCode::Char('q') | KeyCode::Char('?') => Action::CancelInput,
            _ => Action::None,
        },
        Mode::Normal => match app.view {
            View::List => map_list_normal(key),
            View::Detail => map_detail_normal(key),
        },
    }
}

fn map_input_mode(key: KeyEvent) -> Action {
    match key.code {
        KeyCode::Esc => Action::CancelInput,
        KeyCode::Enter => Action::SubmitInput,
        KeyCode::Backspace => Action::InputBackspace,
        KeyCode::Char(c) if !key.modifiers.contains(KeyModifiers::CONTROL) => Action::InputChar(c),
        _ => Action::None,
    }
}

fn map_command_mode(key: KeyEvent) -> Action {
    match key.code {
        KeyCode::Up => Action::CommandHistoryPrev,
        KeyCode::Down => Action::CommandHistoryNext,
        _ => map_input_mode(key),
    }
}

fn map_list_normal(key: KeyEvent) -> Action {
    if key.modifiers.contains(KeyModifiers::CONTROL) {
        return match key.code {
            KeyCode::Char('d') => Action::PageDown,
            KeyCode::Char('u') => Action::PageUp,
            KeyCode::Char('z') => Action::Undo,
            KeyCode::Char('c') => Action::Quit,
            _ => Action::None,
        };
    }
    match key.code {
        KeyCode::Char('q') => Action::Quit,
        KeyCode::Char('.') => Action::RepeatLastCommand,
        KeyCode::Char('j') | KeyCode::Down => Action::MoveDown,
        KeyCode::Char('k') | KeyCode::Up => Action::MoveUp,
        KeyCode::PageDown => Action::PageDown,
        KeyCode::PageUp => Action::PageUp,
        KeyCode::Char('g') => Action::Top,
        KeyCode::Char('G') => Action::Bottom,
        KeyCode::Enter | KeyCode::Char('o') | KeyCode::Char('l') => Action::OpenDetail,
        KeyCode::Char('/') => Action::StartSearch,
        KeyCode::Char(':') => Action::StartCommand,
        KeyCode::Char('?') => Action::StartHelp,
        KeyCode::Char('r') => Action::Reload,
        KeyCode::Char('s') => Action::CycleSort,
        KeyCode::Char('S') => Action::ToggleSortDir,
        KeyCode::Char('m') => Action::ToggleMe,
        KeyCode::Char('n') => Action::NextMatch,
        KeyCode::Char('N') => Action::PrevMatch,
        KeyCode::Char('e') => Action::StartEditTitle,
        KeyCode::Char('c') => Action::StartComment,
        KeyCode::Char('t') => Action::CycleStatus,
        KeyCode::Char('p') => Action::CyclePriority,
        KeyCode::Char('a') => Action::AssignMe,
        KeyCode::Char('v') => Action::ViewComments,
        _ => Action::None,
    }
}

fn map_detail_normal(key: KeyEvent) -> Action {
    if key.modifiers.contains(KeyModifiers::CONTROL) {
        return match key.code {
            KeyCode::Char('c') => Action::Quit,
            KeyCode::Char('z') => Action::Undo,
            KeyCode::Char('d') => Action::PageDown,
            KeyCode::Char('u') => Action::PageUp,
            _ => Action::None,
        };
    }
    match key.code {
        KeyCode::Esc | KeyCode::Char('b') | KeyCode::Char('q') | KeyCode::Char('h') => Action::Back,
        KeyCode::Char('.') => Action::RepeatLastCommand,
        KeyCode::Char('e') => Action::StartEditTitle,
        KeyCode::Char('c') => Action::StartComment,
        KeyCode::Char('t') => Action::CycleStatus,
        KeyCode::Char('p') => Action::CyclePriority,
        KeyCode::Char('a') => Action::AssignMe,
        KeyCode::Char('v') => Action::ViewComments,
        KeyCode::Char('r') => Action::Reload,
        KeyCode::Char('?') => Action::StartHelp,
        KeyCode::Char(':') => Action::StartCommand,
        KeyCode::Char('/') => Action::StartSearch,
        _ => Action::None,
    }
}