use ratatui::crossterm::event::{
Event, KeyCode, KeyEvent, KeyModifiers, MouseEvent, MouseEventKind,
};
use tui_input::Input;
#[derive(Debug, PartialEq, Eq)]
pub enum ScrollType {
Tab,
Table,
List,
Block,
}
#[derive(Debug, PartialEq, Eq)]
pub enum Command {
OpenRepo,
ShowDetails,
Next(ScrollType, usize),
Previous(ScrollType, usize),
Top,
Bottom,
Increment,
Decrement,
Input(InputCommand),
Hexdump(HexdumpCommand),
TraceCalls,
Exit,
Nothing,
HumanReadable,
}
impl From<KeyEvent> for Command {
fn from(key_event: KeyEvent) -> Self {
match key_event.code {
KeyCode::Right | KeyCode::Char('l') => Self::Next(ScrollType::Table, 1),
KeyCode::Left | KeyCode::Char('h') => Self::Previous(ScrollType::Table, 1),
KeyCode::Char('n') => Self::Next(ScrollType::Block, 1),
KeyCode::Char('p') => Self::Previous(ScrollType::Block, 1),
KeyCode::Down | KeyCode::Char('j') => Self::Next(ScrollType::List, 1),
KeyCode::Up | KeyCode::Char('k') => Self::Previous(ScrollType::List, 1),
KeyCode::PageDown => Self::Next(ScrollType::List, 5),
KeyCode::PageUp => Self::Previous(ScrollType::List, 5),
KeyCode::Char('d') => {
if key_event.modifiers == KeyModifiers::CONTROL {
Self::Next(ScrollType::List, 5)
} else {
Self::Nothing
}
}
KeyCode::Char('u') => {
if key_event.modifiers == KeyModifiers::CONTROL {
Self::Previous(ScrollType::List, 5)
} else {
Self::Nothing
}
}
KeyCode::Esc | KeyCode::Char('q') => Self::Exit,
KeyCode::Tab => Self::Next(ScrollType::Tab, 1),
KeyCode::BackTab => Self::Previous(ScrollType::Tab, 1),
KeyCode::Char('t') | KeyCode::Home => Self::Top,
KeyCode::Char('b') | KeyCode::End => Self::Bottom,
KeyCode::Char('+') => Self::Increment,
KeyCode::Char('-') => Self::Decrement,
KeyCode::Char('c') | KeyCode::Char('C') => {
if key_event.modifiers == KeyModifiers::CONTROL {
Self::Exit
} else {
Self::Nothing
}
}
KeyCode::Char('/') => Self::Input(InputCommand::Enter),
KeyCode::Char('f') => {
if key_event.modifiers == KeyModifiers::CONTROL {
Self::Input(InputCommand::Enter)
} else {
Self::Nothing
}
}
KeyCode::Backspace => Self::Input(InputCommand::Resume(Event::Key(key_event))),
KeyCode::Enter => Self::ShowDetails,
KeyCode::Char('o') => Self::OpenRepo,
KeyCode::Char('r') => Self::TraceCalls,
KeyCode::Char('s') => Self::HumanReadable,
_ => Self::Nothing,
}
}
}
impl From<MouseEvent> for Command {
fn from(mouse_event: MouseEvent) -> Self {
match mouse_event.kind {
MouseEventKind::ScrollDown => Self::Next(ScrollType::List, 1),
MouseEventKind::ScrollUp => Self::Previous(ScrollType::List, 1),
_ => Self::Nothing,
}
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum InputCommand {
Handle(Event),
Enter,
Confirm,
Resume(Event),
Exit,
}
impl InputCommand {
pub fn parse(key_event: KeyEvent, input: &Input) -> Self {
if key_event.code == KeyCode::Esc
|| (key_event.code == KeyCode::Backspace && input.value().is_empty())
{
Self::Exit
} else if key_event.code == KeyCode::Enter {
Self::Confirm
} else {
Self::Handle(Event::Key(key_event))
}
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum HexdumpCommand {
Handle(Event),
HandleCustom(Event, Event),
Warn(String, Event),
CancelNext,
CancelPrevious,
Exit(Event),
}
impl HexdumpCommand {
pub fn parse(key_event: KeyEvent, is_read_only: bool) -> Self {
match key_event.code {
KeyCode::Char('q') => Self::Exit(Event::Key(key_event)),
KeyCode::Tab => Self::CancelNext,
KeyCode::BackTab => Self::CancelPrevious,
KeyCode::Char('s') => {
if is_read_only {
Self::Warn(String::from("file is read-only"), Event::Key(key_event))
} else {
Self::HandleCustom(
Event::Key(KeyEvent::new(KeyCode::Char('s'), KeyModifiers::CONTROL)),
Event::Key(key_event),
)
}
}
KeyCode::Char('g') => Self::HandleCustom(
Event::Key(KeyEvent::new(KeyCode::Char('j'), KeyModifiers::CONTROL)),
Event::Key(key_event),
),
KeyCode::Char('n') => Self::HandleCustom(
Event::Key(KeyEvent::new(KeyCode::Char('e'), KeyModifiers::CONTROL)),
Event::Key(key_event),
),
_ => Self::Handle(Event::Key(key_event)),
}
}
}