pub mod keymap;
use crossterm::event::{KeyEvent, KeyModifiers};
use crate::app::mode::Mode;
use crate::editor::cursor::Motion;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Action {
None,
EnterMode(Mode),
Move(Motion),
Extend(Motion),
Scroll(isize),
Page { down: bool, half: bool },
Insert(char),
InsertNewline,
InsertIndent,
DeleteBackward,
DeleteForward,
Delete,
OpenLineBelow,
OpenLineAbove,
AppendAfter,
AppendAtLineEnd,
InsertAtLineStart,
Undo,
Redo,
Yank,
Cut,
Paste,
AddCursor { below: bool },
ClearCursors,
CycleBuffer { forward: bool },
Save,
Quit,
ToggleTree,
TreeMove(isize),
TreeActivate,
SearchStart { forward: bool },
SearchInput(char),
SearchBackspace,
SearchSubmit,
SearchCancel,
SearchRepeat { forward: bool },
CommandInput(char),
CommandBackspace,
CommandSubmit,
CommandCancel,
}
#[derive(Debug, Default)]
pub struct Input {
pending: Option<char>,
}
impl Input {
pub fn handle(&mut self, key: KeyEvent, mode: Mode) -> Action {
if let Some(prefix) = self.pending.take() {
return keymap::pending(prefix, key);
}
let action = match mode {
Mode::Normal => keymap::normal(key, &mut self.pending),
Mode::Insert => keymap::insert(key),
Mode::Visual | Mode::VisualLine => keymap::visual(key, &mut self.pending),
Mode::Command => keymap::command(key),
Mode::Search => keymap::search(key),
Mode::Tree => keymap::tree(key),
};
if matches!(action, Action::EnterMode(_)) {
self.pending = None;
}
action
}
}
#[must_use]
pub(crate) fn is_plain(modifiers: KeyModifiers) -> bool {
modifiers.difference(KeyModifiers::SHIFT).is_empty()
}
#[must_use]
pub(crate) fn is_ctrl(modifiers: KeyModifiers) -> bool {
modifiers.contains(KeyModifiers::CONTROL)
}