use crate::prelude::*;
use input::{Key, Modifiers};
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub struct KeyEvent {
pub modifiers: Modifiers,
pub key: Key,
}
impl TryFrom<crossterm::event::KeyEvent> for KeyEvent {
type Error = ();
fn try_from(event: crossterm::event::KeyEvent) -> Result<Self, Self::Error> {
Ok(KeyEvent {
modifiers: event.modifiers.into(),
key: Key::try_from(event.code)?,
})
}
}
impl std::fmt::Display for KeyEvent {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.modifiers.is_empty() {
write!(f, "{}", self.key)
} else {
write!(f, "{}+{}", self.modifiers, self.key)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crossterm::event::{KeyCode, KeyModifiers};
fn ct_key(
code: KeyCode,
mods: KeyModifiers,
) -> crossterm::event::KeyEvent {
crossterm::event::KeyEvent::new(code, mods)
}
#[test]
fn try_from_char_no_mods() {
let ev = KeyEvent::try_from(ct_key(KeyCode::Char('a'), KeyModifiers::empty()))
.unwrap();
assert_eq!(ev.key, Key::Char('a'));
assert!(ev.modifiers.is_empty());
}
#[test]
fn try_from_char_with_ctrl() {
let ev =
KeyEvent::try_from(ct_key(KeyCode::Char('s'), KeyModifiers::CONTROL)).unwrap();
assert_eq!(ev.key, Key::Char('s'));
assert!(ev.modifiers.contains(Modifiers::CTRL));
}
#[test]
fn try_from_enter_with_shift() {
let ev = KeyEvent::try_from(ct_key(KeyCode::Enter, KeyModifiers::SHIFT)).unwrap();
assert_eq!(ev.key, Key::Enter);
assert!(ev.modifiers.contains(Modifiers::SHIFT));
}
#[test]
fn try_from_unknown_key_is_err() {
assert!(
KeyEvent::try_from(ct_key(KeyCode::Null, KeyModifiers::empty())).is_err()
);
}
#[test]
fn display_no_modifiers() {
let ev = KeyEvent {
modifiers: Modifiers::empty(),
key: Key::Enter,
};
assert_eq!(ev.to_string(), "Enter");
}
#[test]
fn display_ctrl_modifier() {
let ev = KeyEvent {
modifiers: Modifiers::CTRL,
key: Key::Char('s'),
};
assert_eq!(ev.to_string(), "Ctrl+s");
}
#[test]
fn display_ctrl_shift_modifier() {
let ev = KeyEvent {
modifiers: Modifiers::CTRL | Modifiers::SHIFT,
key: Key::ArrowUp,
};
assert_eq!(ev.to_string(), "Ctrl+Shift+ArrowUp");
}
#[test]
fn display_alt_modifier() {
let ev = KeyEvent {
modifiers: Modifiers::ALT,
key: Key::F(4),
};
assert_eq!(ev.to_string(), "Alt+F4");
}
#[test]
fn key_event_clone_eq() {
let ev = KeyEvent {
modifiers: Modifiers::CTRL,
key: Key::Char('c'),
};
assert_eq!(ev.clone(), ev);
}
#[test]
fn key_event_hash() {
use std::collections::HashSet;
let ev = KeyEvent {
modifiers: Modifiers::CTRL,
key: Key::Char('c'),
};
let mut s = HashSet::new();
s.insert(ev);
assert!(s.contains(&ev));
}
}