use crossterm::event::{KeyEvent, KeyModifiers};
use escriba_keymap::Key;
use madori::event::{KeyCode as MdKey, KeyEvent as MadoriKey, Modifiers as MadoriMods};
#[must_use]
pub fn crossterm_key_event(e: &KeyEvent) -> MadoriKey {
use crossterm::event::KeyCode as CkKey;
let modifiers = MadoriMods {
shift: e.modifiers.contains(KeyModifiers::SHIFT),
ctrl: e.modifiers.contains(KeyModifiers::CONTROL),
alt: e.modifiers.contains(KeyModifiers::ALT),
meta: e.modifiers.contains(KeyModifiers::SUPER),
};
let key = match e.code {
CkKey::Enter => MdKey::Enter,
CkKey::Esc => MdKey::Escape,
CkKey::Backspace => MdKey::Backspace,
CkKey::Delete => MdKey::Delete,
CkKey::Tab => MdKey::Tab,
CkKey::Up => MdKey::Up,
CkKey::Down => MdKey::Down,
CkKey::Left => MdKey::Left,
CkKey::Right => MdKey::Right,
CkKey::Home => MdKey::Home,
CkKey::End => MdKey::End,
CkKey::PageUp => MdKey::PageUp,
CkKey::PageDown => MdKey::PageDown,
CkKey::F(n) => MdKey::F(n),
CkKey::Char(' ') => MdKey::Space,
CkKey::Char(c) => MdKey::Char(c),
_ => MdKey::Unknown,
};
MadoriKey {
key,
pressed: true,
modifiers,
text: None,
}
}
#[must_use]
pub fn translate_crossterm_key(e: &KeyEvent) -> Option<Key> {
escriba_input::translate_key(&crossterm_key_event(e))
}
#[cfg(test)]
mod tests {
use super::*;
use crossterm::event::{KeyCode, KeyEventKind, KeyEventState};
fn ke(code: KeyCode, mods: KeyModifiers) -> KeyEvent {
KeyEvent {
code,
modifiers: mods,
kind: KeyEventKind::Press,
state: KeyEventState::NONE,
}
}
#[test]
fn plain_char() {
assert_eq!(
translate_crossterm_key(&ke(KeyCode::Char('h'), KeyModifiers::NONE)),
Some(Key::Char('h'))
);
}
#[test]
fn ctrl_char() {
assert_eq!(
translate_crossterm_key(&ke(KeyCode::Char('R'), KeyModifiers::CONTROL)),
Some(Key::Ctrl('r'))
);
}
#[test]
fn alt_char() {
assert_eq!(
translate_crossterm_key(&ke(KeyCode::Char('f'), KeyModifiers::ALT)),
Some(Key::Alt('f'))
);
}
#[test]
fn named_keys() {
assert_eq!(
translate_crossterm_key(&ke(KeyCode::Esc, KeyModifiers::NONE)),
Some(Key::Esc)
);
assert_eq!(
translate_crossterm_key(&ke(KeyCode::Enter, KeyModifiers::NONE)),
Some(Key::Enter)
);
assert_eq!(
translate_crossterm_key(&ke(KeyCode::Left, KeyModifiers::NONE)),
Some(Key::Left)
);
}
#[test]
fn the_editing_keys_this_face_used_to_swallow() {
assert_eq!(
translate_crossterm_key(&ke(KeyCode::Backspace, KeyModifiers::NONE)),
Some(Key::Backspace)
);
assert_eq!(
translate_crossterm_key(&ke(KeyCode::Delete, KeyModifiers::NONE)),
Some(Key::Delete),
"<Del> is bound to DeleteForward and must reach the runtime"
);
assert_eq!(
translate_crossterm_key(&ke(KeyCode::F(5), KeyModifiers::NONE)),
Some(Key::F(5))
);
}
#[test]
fn an_unmapped_key_is_dropped_rather_than_guessed() {
assert_eq!(
translate_crossterm_key(&ke(KeyCode::CapsLock, KeyModifiers::NONE)),
None
);
}
}