laziergit 1.1.0

an even lazier git implementation than lazygit
use crate::app::{Action, App, Focus, Mode};
use crate::field::EditOp;
use crossterm::event::{KeyCode, KeyEvent};

pub fn map(app: &App, key: KeyEvent) -> Action {
    match &app.mode {
        Mode::Normal => normal(app.focus, key.code),
        Mode::Commit(_) | Mode::Branch(_) => editing(key.code),
        Mode::Confirm => confirm(key.code),
        Mode::Help => Action::Cancel,
    }
}

fn normal(focus: Focus, code: KeyCode) -> Action {
    use KeyCode::*;
    match focus {
        Focus::Sidebar => match code {
            Char('q') => Action::Quit,
            Char('j') | Down => Action::NavNext,
            Char('k') | Up => Action::NavPrev,
            Char('h') | Left => Action::Collapse,
            Char('l') | Right => Action::Expand,
            Char('g') => Action::PressG,
            Char('G') => Action::GoBottom,
            Char(c) if c.is_ascii_digit() => digit(c),
            Enter => Action::EnterRow,
            Tab => Action::ToggleFocus,
            Char(' ') => Action::StageToggle,
            Char('c') => Action::OpenCommit,
            Char('b') => Action::OpenBranch,
            Char('p') => Action::Pull,
            Char('P') => Action::Push,
            Char('X') => Action::OpenConfirm,
            Char('?') => Action::OpenHelp,
            _ => Action::Noop,
        },
        Focus::Diff => match code {
            Char('q') => Action::Quit,
            Char('j') | Down => Action::ScrollDiff(1),
            Char('k') | Up => Action::ScrollDiff(-1),
            Char('g') => Action::PressG,
            Char('G') => Action::GoBottom,
            Char(c) if c.is_ascii_digit() => digit(c),
            Char('?') => Action::OpenHelp,
            Enter | Tab => Action::ToggleFocus,
            _ => Action::Noop,
        },
    }
}

fn digit(c: char) -> Action {
    match c.to_digit(10) {
        Some(d) => Action::PushDigit(d),
        None => Action::Noop,
    }
}

fn editing(code: KeyCode) -> Action {
    match code {
        KeyCode::Char(c) => Action::Edit(EditOp::Insert(c)),
        KeyCode::Backspace => Action::Edit(EditOp::Backspace),
        KeyCode::Left => Action::Edit(EditOp::Left),
        KeyCode::Right => Action::Edit(EditOp::Right),
        KeyCode::Enter => Action::Submit,
        KeyCode::Esc => Action::Cancel,
        _ => Action::Noop,
    }
}

fn confirm(code: KeyCode) -> Action {
    match code {
        KeyCode::Char('y') | KeyCode::Enter => Action::Submit,
        KeyCode::Char('n') | KeyCode::Esc => Action::Cancel,
        _ => Action::Noop,
    }
}