use crossterm::event; use serde::Deserialize; use std::fmt; #[cfg(test)] use serde::Serialize; /// Represents a key. #[derive(PartialEq, Eq, Clone, Copy, Hash, Debug, Deserialize)] #[cfg_attr(test, derive(Serialize))] pub enum Key { /// Both Enter (or Return) and numpad Enter Enter, /// Tabulation key Tab, /// Backspace key Backspace, /// Escape key Esc, /// Left arrow Left, /// Right arrow Right, /// Up arrow Up, /// Down arrow Down, /// Insert key Ins, /// Delete key Delete, /// Home key Home, /// End key End, /// Page Up key PageUp, /// Page Down key PageDown, /// F0 key F0, /// F1 key F1, /// F2 key F2, /// F3 key F3, /// F4 key F4, /// F5 key F5, /// F6 key F6, /// F7 key F7, /// F8 key F8, /// F9 key F9, /// F10 key F10, /// F11 key F11, /// F12 key F12, Char(char), Ctrl(char), Alt(char), Unkown, } impl Key { /// Returns the function key corresponding to the given number /// /// 1 -> F1, etc... /// /// # Panics /// /// If `n == 0 || n > 12` pub fn from_f(n: u8) -> Key { match n { 0 => Key::F0, 1 => Key::F1, 2 => Key::F2, 3 => Key::F3, 4 => Key::F4, 5 => Key::F5, 6 => Key::F6, 7 => Key::F7, 8 => Key::F8, 9 => Key::F9, 10 => Key::F10, 11 => Key::F11, 12 => Key::F12, _ => panic!("unknown function key: F{}", n), } } } impl fmt::Display for Key { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Key::Alt(' ') => write!(f, ""), Key::Ctrl(' ') => write!(f, ""), Key::Char(' ') => write!(f, ""), Key::Alt(c) => write!(f, "", c), Key::Ctrl(c) => write!(f, "", c), Key::Char(c) => write!(f, "{}", c), Key::Left => write!(f, "\u{2190}"), //← Key::Right => write!(f, "\u{2192}"), //→ Key::Up => write!(f, "\u{2191}"), //↑ Key::Down => write!(f, "\u{2193}"), //↓ Key::Enter | Key::Tab | Key::Backspace | Key::Esc | Key::Ins | Key::Delete | Key::Home | Key::End | Key::PageUp | Key::PageDown => write!(f, "<{:?}>", self), _ => write!(f, "{:?}", self), } } } impl From for Key { fn from(key_event: event::KeyEvent) -> Self { match key_event { event::KeyEvent { code: event::KeyCode::Esc, .. } => Key::Esc, event::KeyEvent { code: event::KeyCode::Backspace, .. } => Key::Backspace, event::KeyEvent { code: event::KeyCode::Left, .. } => Key::Left, event::KeyEvent { code: event::KeyCode::Right, .. } => Key::Right, event::KeyEvent { code: event::KeyCode::Up, .. } => Key::Up, event::KeyEvent { code: event::KeyCode::Down, .. } => Key::Down, event::KeyEvent { code: event::KeyCode::Home, .. } => Key::Home, event::KeyEvent { code: event::KeyCode::End, .. } => Key::End, event::KeyEvent { code: event::KeyCode::PageUp, .. } => Key::PageUp, event::KeyEvent { code: event::KeyCode::PageDown, .. } => Key::PageDown, event::KeyEvent { code: event::KeyCode::Delete, .. } => Key::Delete, event::KeyEvent { code: event::KeyCode::Insert, .. } => Key::Ins, event::KeyEvent { code: event::KeyCode::F(n), .. } => Key::from_f(n), event::KeyEvent { code: event::KeyCode::Enter, .. } => Key::Enter, event::KeyEvent { code: event::KeyCode::Tab, .. } => Key::Tab, // First check for char + modifier event::KeyEvent { code: event::KeyCode::Char(c), modifiers: event::KeyModifiers::ALT, } => Key::Alt(c), event::KeyEvent { code: event::KeyCode::Char(c), modifiers: event::KeyModifiers::CONTROL, } => Key::Ctrl(c), event::KeyEvent { code: event::KeyCode::Char(c), .. } => Key::Char(c), _ => Key::Unkown, } } }