// from https://github.com/Rigellute/spotify-tui use std::fmt; use crossterm::event; /// Represents an key. #[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)] pub enum Key { /// Both Enter (or Return) and numpad Enter Enter, Tab, Backspace, 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), Unknown, } 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 | Key::Right | Key::Up | Key::Down => write!(f, "<{:?} Arrow Key>", 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::Unknown, } } } #[cfg(test)] mod tests { use super::*; #[test] fn test_key_fmt() { assert_eq!(format!("{}", Key::Left), ""); assert_eq!(format!("{}", Key::Alt(' ')), ""); assert_eq!(format!("{}", Key::Alt('c')), ""); assert_eq!(format!("{}", Key::Char('c')), ""); assert_eq!(format!("{}", Key::Enter), ""); assert_eq!(format!("{}", Key::F10), ""); } #[test] fn test_key_from_event() { assert_eq!( Key::from(event::KeyEvent::from(event::KeyCode::Esc)), Key::Esc ); assert_eq!( Key::from(event::KeyEvent::from(event::KeyCode::F(2))), Key::F2 ); assert_eq!( Key::from(event::KeyEvent::from(event::KeyCode::Char('J'))), Key::Char('J') ); assert_eq!( Key::from(event::KeyEvent { code: event::KeyCode::Char('c'), modifiers: event::KeyModifiers::ALT }), Key::Alt('c') ); assert_eq!( Key::from(event::KeyEvent { code: event::KeyCode::Char('c'), modifiers: event::KeyModifiers::CONTROL }), Key::Ctrl('c') ); } }