use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
use strict::OneToThree;
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub struct KeyCombination {
pub codes: OneToThree<KeyCode>,
pub modifiers: KeyModifiers,
}
fn normalize_key_code(code: &mut KeyCode, modifiers: KeyModifiers) -> bool {
if matches!(code, KeyCode::Char('\r' | '\n')) {
*code = KeyCode::Enter;
} else if modifiers.contains(KeyModifiers::SHIFT) {
if let KeyCode::Char(c) = code {
if c.is_ascii_lowercase() {
*code = KeyCode::Char(c.to_ascii_uppercase());
}
}
} else if let KeyCode::Char(c) = code {
if c.is_ascii_uppercase() {
return true;
}
}
false
}
impl KeyCombination {
#[must_use]
pub fn normalized(mut self) -> Self {
let mut shift = normalize_key_code(self.codes.first_mut(), self.modifiers);
if let Some(ref mut code) = self.codes.get_mut(1) {
shift |= normalize_key_code(code, self.modifiers);
}
if let Some(ref mut code) = self.codes.get_mut(2) {
shift |= normalize_key_code(code, self.modifiers);
}
if shift {
self.modifiers |= KeyModifiers::SHIFT;
}
self
}
}
impl From<KeyEvent> for KeyCombination {
fn from(key_event: KeyEvent) -> Self {
let raw = Self {
codes: key_event.code.into(),
modifiers: key_event.modifiers,
};
raw.normalized()
}
}
#[macro_export]
macro_rules! key {
($($tt:tt)*) => {
$crate::__private::key!(($crate) $($tt)*)
};
}