#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum KeyCode {
Esc,
Enter,
Backspace,
Delete,
Left,
Right,
Up,
Down,
Home,
End,
Tab,
BackTab,
Char(char),
}
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
pub struct KeyModifiers {
pub ctrl: bool,
pub alt: bool,
pub shift: bool,
}
impl KeyModifiers {
pub const NONE: Self = Self {
ctrl: false,
alt: false,
shift: false,
};
pub const CONTROL: Self = Self {
ctrl: true,
alt: false,
shift: false,
};
pub const ALT: Self = Self {
ctrl: false,
alt: true,
shift: false,
};
pub const SHIFT: Self = Self {
ctrl: false,
alt: false,
shift: true,
};
pub fn contains(self, other: Self) -> bool {
(!other.ctrl || self.ctrl) && (!other.alt || self.alt) && (!other.shift || self.shift)
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct KeyEvent {
pub code: KeyCode,
pub modifiers: KeyModifiers,
}
impl KeyEvent {
pub fn new(code: KeyCode, modifiers: KeyModifiers) -> Self {
Self { code, modifiers }
}
pub fn bare(code: KeyCode) -> Self {
Self {
code,
modifiers: KeyModifiers::NONE,
}
}
pub fn ctrl(code: KeyCode) -> Self {
Self {
code,
modifiers: KeyModifiers::CONTROL,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn none_contains_nothing_and_is_contained_by_everything() {
assert!(KeyModifiers::NONE.contains(KeyModifiers::NONE));
assert!(!KeyModifiers::NONE.contains(KeyModifiers::CONTROL));
assert!(KeyModifiers::CONTROL.contains(KeyModifiers::NONE));
}
#[test]
fn contains_asks_for_a_subset_not_equality() {
let ctrl_shift = KeyModifiers {
ctrl: true,
alt: false,
shift: true,
};
assert!(ctrl_shift.contains(KeyModifiers::CONTROL));
assert!(ctrl_shift.contains(KeyModifiers::SHIFT));
assert!(!ctrl_shift.contains(KeyModifiers::ALT));
}
#[test]
fn constructors_agree_with_literals() {
assert_eq!(
KeyEvent::bare(KeyCode::Enter),
KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE)
);
assert_eq!(
KeyEvent::ctrl(KeyCode::Char('w')),
KeyEvent::new(KeyCode::Char('w'), KeyModifiers::CONTROL)
);
}
}