zte/src/action.rs

143 lines
4.1 KiB
Rust

use crate::{state::State, terminal::TerminalEvent};
use crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyModifiers};
#[derive(Clone, Debug)]
pub enum Dir {
Left,
Right,
Up,
Down,
}
#[derive(Clone, Debug)]
pub enum Action {
Char(char), // Insert a character
Backspace, // Backspace a character
Move(Dir), // Move the cursor
PaneMove(Dir), // Move panes
Cancel, // Cancels the current context
Go, // Search, accept, or select the current option
Quit, // Quit the application
OpenPrompt, // Open the command prompt
Show(String), // Display some arbitrary text to the user
}
pub enum Event {
// The incoming event is an action generated by some other internal component.
Action(Action),
// The incoming event is a raw user input.
Raw(RawEvent),
}
impl Event {
pub fn from_raw(e: TerminalEvent) -> Self {
Self::Raw(RawEvent(e))
}
/// Turn the event into an action (if possible).
///
/// The translation function allows elements to translate raw events into their own context-specific actions.
pub fn to_action(&self, translate: impl FnOnce(&RawEvent) -> Option<Action>) -> Option<Action> {
match self {
Self::Action(a) => Some(a.clone()),
Self::Raw(te) => translate(te),
}
}
}
pub struct RawEvent(TerminalEvent);
impl RawEvent {
pub fn to_char(&self) -> Option<char> {
match self.0 {
TerminalEvent::Key(KeyEvent {
code,
modifiers,
kind: KeyEventKind::Press | KeyEventKind::Repeat,
..
}) => match code {
KeyCode::Char(c)
if matches!(modifiers, KeyModifiers::NONE | KeyModifiers::SHIFT) =>
{
Some(c)
}
KeyCode::Backspace if modifiers == KeyModifiers::NONE => Some('\x08'),
KeyCode::Enter if modifiers == KeyModifiers::NONE => Some('\n'),
_ => None,
},
_ => None,
}
}
pub fn to_pane_move(&self) -> Option<Dir> {
match &self.0 {
TerminalEvent::Key(KeyEvent {
code,
modifiers: KeyModifiers::ALT,
kind: KeyEventKind::Press | KeyEventKind::Repeat,
..
}) => match code {
KeyCode::Char('a') => Some(Dir::Left),
KeyCode::Char('d') => Some(Dir::Right),
KeyCode::Char('w') => Some(Dir::Up),
KeyCode::Char('s') => Some(Dir::Down),
_ => None,
},
_ => None,
}
}
pub fn to_move(&self) -> Option<Dir> {
match &self.0 {
TerminalEvent::Key(KeyEvent {
code,
modifiers: KeyModifiers::NONE,
kind: KeyEventKind::Press | KeyEventKind::Repeat,
..
}) => match code {
KeyCode::Left => Some(Dir::Left),
KeyCode::Right => Some(Dir::Right),
KeyCode::Up => Some(Dir::Up),
KeyCode::Down => Some(Dir::Down),
_ => None,
},
_ => None,
}
}
pub fn is_go(&self) -> bool {
matches!(
&self.0,
TerminalEvent::Key(KeyEvent {
code: KeyCode::Enter,
modifiers: KeyModifiers::NONE,
kind: KeyEventKind::Press,
..
})
)
}
pub fn is_prompt(&self) -> bool {
matches!(
&self.0,
TerminalEvent::Key(KeyEvent {
code: KeyCode::Enter,
modifiers: KeyModifiers::ALT,
kind: KeyEventKind::Press,
..
})
)
}
pub fn is_cancel(&self) -> bool {
matches!(
&self.0,
TerminalEvent::Key(KeyEvent {
code: KeyCode::Esc,
modifiers: KeyModifiers::NONE,
kind: KeyEventKind::Press,
..
})
)
}
}