use std::collections::HashMap;
use super::key::{Key, KeyEvent};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum KeymapAction {
Submit,
Newline,
Quit,
HistorySearch,
ToggleTheme,
ScrollUp,
ScrollDown,
ExternalEditor,
}
impl KeymapAction {
pub const ALL: &'static [KeymapAction] = &[
KeymapAction::Submit,
KeymapAction::Newline,
KeymapAction::Quit,
KeymapAction::HistorySearch,
KeymapAction::ToggleTheme,
KeymapAction::ScrollUp,
KeymapAction::ScrollDown,
KeymapAction::ExternalEditor,
];
pub fn name(self) -> &'static str {
match self {
KeymapAction::Submit => "submit",
KeymapAction::Newline => "newline",
KeymapAction::Quit => "quit",
KeymapAction::HistorySearch => "history_search",
KeymapAction::ToggleTheme => "toggle_theme",
KeymapAction::ScrollUp => "scroll_up",
KeymapAction::ScrollDown => "scroll_down",
KeymapAction::ExternalEditor => "external_editor",
}
}
pub fn default_key(self) -> KeyEvent {
match self {
KeymapAction::Submit => KeyEvent::plain(Key::Enter),
KeymapAction::Newline => KeyEvent {
key: Key::Enter,
ctrl: false,
alt: true,
shift: false,
},
KeymapAction::Quit => KeyEvent::ctrl(Key::Char('c')),
KeymapAction::HistorySearch => KeyEvent::ctrl(Key::Char('r')),
KeymapAction::ToggleTheme => KeyEvent::ctrl(Key::Char('t')),
KeymapAction::ScrollUp => KeyEvent::plain(Key::PageUp),
KeymapAction::ScrollDown => KeyEvent::plain(Key::PageDown),
KeymapAction::ExternalEditor => KeyEvent::ctrl(Key::Char('e')),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Keymap {
bindings: HashMap<KeymapAction, KeyEvent>,
}
impl Default for Keymap {
fn default() -> Self {
let bindings = KeymapAction::ALL
.iter()
.map(|&a| (a, a.default_key()))
.collect();
Keymap { bindings }
}
}
impl Keymap {
pub fn with_overrides(overrides: &HashMap<String, String>) -> Self {
let mut km = Keymap::default();
for action in KeymapAction::ALL {
if let Some(spec) = overrides.get(action.name()) {
if let Some(key) = KeyEvent::parse(spec) {
km.bindings.insert(*action, key);
}
}
}
km
}
pub fn key_for(&self, action: KeymapAction) -> KeyEvent {
self.bindings
.get(&action)
.copied()
.unwrap_or_else(|| action.default_key())
}
pub fn action_for(&self, key: KeyEvent) -> Option<KeymapAction> {
self.bindings
.iter()
.find(|(_, &bound)| bound == key)
.map(|(&a, _)| a)
}
}