|
|
|
@ -1,10 +1,45 @@
|
|
|
|
|
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
|
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
use termion::event::Key as TermionKey;
|
|
|
|
|
use serde_yaml;
|
|
|
|
|
use std::cmp::Ordering;
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
|
|
|
#[serde(rename_all = "kebab-case")]
|
|
|
|
|
pub enum Key {
|
|
|
|
|
Number(u8),
|
|
|
|
|
F1,
|
|
|
|
|
F2,
|
|
|
|
|
F3,
|
|
|
|
|
F4,
|
|
|
|
|
F5,
|
|
|
|
|
F6,
|
|
|
|
|
F7,
|
|
|
|
|
F8,
|
|
|
|
|
F9,
|
|
|
|
|
F10,
|
|
|
|
|
F11,
|
|
|
|
|
F12,
|
|
|
|
|
|
|
|
|
|
Num0,
|
|
|
|
|
Num1,
|
|
|
|
|
Num2,
|
|
|
|
|
Num3,
|
|
|
|
|
Num4,
|
|
|
|
|
Num5,
|
|
|
|
|
Num6,
|
|
|
|
|
Num7,
|
|
|
|
|
Num8,
|
|
|
|
|
Num9,
|
|
|
|
|
|
|
|
|
|
AltNum0,
|
|
|
|
|
AltNum1,
|
|
|
|
|
AltNum2,
|
|
|
|
|
AltNum3,
|
|
|
|
|
AltNum4,
|
|
|
|
|
AltNum5,
|
|
|
|
|
AltNum6,
|
|
|
|
|
AltNum7,
|
|
|
|
|
AltNum8,
|
|
|
|
|
AltNum9,
|
|
|
|
|
|
|
|
|
|
Backspace,
|
|
|
|
|
Left,
|
|
|
|
@ -18,7 +53,7 @@ pub enum Key {
|
|
|
|
|
BackTab,
|
|
|
|
|
Delete,
|
|
|
|
|
Insert,
|
|
|
|
|
Return,
|
|
|
|
|
Enter,
|
|
|
|
|
Space,
|
|
|
|
|
Tab,
|
|
|
|
|
Esc,
|
|
|
|
@ -131,297 +166,401 @@ pub enum Key {
|
|
|
|
|
ShiftY,
|
|
|
|
|
ShiftZ,
|
|
|
|
|
|
|
|
|
|
CtrlShiftA,
|
|
|
|
|
CtrlShiftB,
|
|
|
|
|
CtrlShiftC,
|
|
|
|
|
CtrlShiftD,
|
|
|
|
|
CtrlShiftE,
|
|
|
|
|
CtrlShiftF,
|
|
|
|
|
CtrlShiftG,
|
|
|
|
|
CtrlShiftH,
|
|
|
|
|
CtrlShiftI,
|
|
|
|
|
CtrlShiftJ,
|
|
|
|
|
CtrlShiftK,
|
|
|
|
|
CtrlShiftL,
|
|
|
|
|
CtrlShiftM,
|
|
|
|
|
CtrlShiftN,
|
|
|
|
|
CtrlShiftO,
|
|
|
|
|
CtrlShiftP,
|
|
|
|
|
CtrlShiftQ,
|
|
|
|
|
CtrlShiftR,
|
|
|
|
|
CtrlShiftS,
|
|
|
|
|
CtrlShiftT,
|
|
|
|
|
CtrlShiftU,
|
|
|
|
|
CtrlShiftV,
|
|
|
|
|
CtrlShiftW,
|
|
|
|
|
CtrlShiftX,
|
|
|
|
|
CtrlShiftY,
|
|
|
|
|
CtrlShiftZ,
|
|
|
|
|
|
|
|
|
|
AltShiftA,
|
|
|
|
|
AltShiftB,
|
|
|
|
|
AltShiftC,
|
|
|
|
|
AltShiftD,
|
|
|
|
|
AltShiftE,
|
|
|
|
|
AltShiftF,
|
|
|
|
|
AltShiftG,
|
|
|
|
|
AltShiftH,
|
|
|
|
|
AltShiftI,
|
|
|
|
|
AltShiftJ,
|
|
|
|
|
AltShiftK,
|
|
|
|
|
AltShiftL,
|
|
|
|
|
AltShiftM,
|
|
|
|
|
AltShiftN,
|
|
|
|
|
AltShiftO,
|
|
|
|
|
AltShiftP,
|
|
|
|
|
AltShiftQ,
|
|
|
|
|
AltShiftR,
|
|
|
|
|
AltShiftS,
|
|
|
|
|
AltShiftT,
|
|
|
|
|
AltShiftU,
|
|
|
|
|
AltShiftV,
|
|
|
|
|
AltShiftW,
|
|
|
|
|
AltShiftX,
|
|
|
|
|
AltShiftY,
|
|
|
|
|
AltShiftZ,
|
|
|
|
|
|
|
|
|
|
Plus,
|
|
|
|
|
Minus,
|
|
|
|
|
Backtick,
|
|
|
|
|
Tilde,
|
|
|
|
|
Underscore,
|
|
|
|
|
Equals,
|
|
|
|
|
Semicolon,
|
|
|
|
|
Colon,
|
|
|
|
|
SingleQuote,
|
|
|
|
|
DoubleQuote,
|
|
|
|
|
ForwardSlash,
|
|
|
|
|
BackSlash,
|
|
|
|
|
Dot,
|
|
|
|
|
Comma,
|
|
|
|
|
QuestionMark,
|
|
|
|
|
Pound,
|
|
|
|
|
Special(char),
|
|
|
|
|
|
|
|
|
|
NotSupported,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl std::fmt::Display for Key {
|
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
|
write!(f, "{:?}", self)
|
|
|
|
|
let key_str = self.to_char().map(|c| c.to_string()).unwrap_or_else(|| {
|
|
|
|
|
serde_yaml::to_value(self)
|
|
|
|
|
.ok()
|
|
|
|
|
.and_then(|v| v.as_str().map(|v| v.to_string()))
|
|
|
|
|
.unwrap_or_default()
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
write!(f, "{}", key_str)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Key {
|
|
|
|
|
pub fn from_termion_event(key: TermionKey) -> Self {
|
|
|
|
|
match key {
|
|
|
|
|
TermionKey::Char('0') => Key::Number(0),
|
|
|
|
|
TermionKey::Char('1') => Key::Number(1),
|
|
|
|
|
TermionKey::Char('2') => Key::Number(2),
|
|
|
|
|
TermionKey::Char('3') => Key::Number(3),
|
|
|
|
|
TermionKey::Char('4') => Key::Number(4),
|
|
|
|
|
TermionKey::Char('5') => Key::Number(5),
|
|
|
|
|
TermionKey::Char('6') => Key::Number(6),
|
|
|
|
|
TermionKey::Char('7') => Key::Number(7),
|
|
|
|
|
TermionKey::Char('8') => Key::Number(8),
|
|
|
|
|
TermionKey::Char('9') => Key::Number(9),
|
|
|
|
|
|
|
|
|
|
TermionKey::Backspace => Key::Backspace,
|
|
|
|
|
TermionKey::Left => Key::Left,
|
|
|
|
|
TermionKey::Right => Key::Right,
|
|
|
|
|
TermionKey::Up => Key::Up,
|
|
|
|
|
TermionKey::Down => Key::Down,
|
|
|
|
|
TermionKey::Home => Key::Home,
|
|
|
|
|
TermionKey::End => Key::End,
|
|
|
|
|
TermionKey::PageUp => Key::PageUp,
|
|
|
|
|
TermionKey::PageDown => Key::PageDown,
|
|
|
|
|
TermionKey::BackTab => Key::BackTab,
|
|
|
|
|
TermionKey::Delete => Key::Delete,
|
|
|
|
|
TermionKey::Insert => Key::Insert,
|
|
|
|
|
TermionKey::Char('\n') => Key::Return,
|
|
|
|
|
TermionKey::Char(' ') => Key::Space,
|
|
|
|
|
TermionKey::Char('\t') => Key::Tab,
|
|
|
|
|
TermionKey::Esc => Key::Esc,
|
|
|
|
|
|
|
|
|
|
TermionKey::Char('a') => Key::A,
|
|
|
|
|
TermionKey::Char('b') => Key::B,
|
|
|
|
|
TermionKey::Char('c') => Key::C,
|
|
|
|
|
TermionKey::Char('d') => Key::D,
|
|
|
|
|
TermionKey::Char('e') => Key::E,
|
|
|
|
|
TermionKey::Char('f') => Key::F,
|
|
|
|
|
TermionKey::Char('g') => Key::G,
|
|
|
|
|
TermionKey::Char('h') => Key::H,
|
|
|
|
|
TermionKey::Char('i') => Key::I,
|
|
|
|
|
TermionKey::Char('j') => Key::J,
|
|
|
|
|
TermionKey::Char('k') => Key::K,
|
|
|
|
|
TermionKey::Char('l') => Key::L,
|
|
|
|
|
TermionKey::Char('m') => Key::M,
|
|
|
|
|
TermionKey::Char('n') => Key::N,
|
|
|
|
|
TermionKey::Char('o') => Key::O,
|
|
|
|
|
TermionKey::Char('p') => Key::P,
|
|
|
|
|
TermionKey::Char('q') => Key::Q,
|
|
|
|
|
TermionKey::Char('r') => Key::R,
|
|
|
|
|
TermionKey::Char('s') => Key::S,
|
|
|
|
|
TermionKey::Char('t') => Key::T,
|
|
|
|
|
TermionKey::Char('u') => Key::U,
|
|
|
|
|
TermionKey::Char('v') => Key::V,
|
|
|
|
|
TermionKey::Char('w') => Key::W,
|
|
|
|
|
TermionKey::Char('x') => Key::X,
|
|
|
|
|
TermionKey::Char('y') => Key::Y,
|
|
|
|
|
TermionKey::Char('z') => Key::Z,
|
|
|
|
|
|
|
|
|
|
TermionKey::Ctrl('a') => Key::CtrlA,
|
|
|
|
|
TermionKey::Ctrl('b') => Key::CtrlB,
|
|
|
|
|
TermionKey::Ctrl('c') => Key::CtrlC,
|
|
|
|
|
TermionKey::Ctrl('d') => Key::CtrlD,
|
|
|
|
|
TermionKey::Ctrl('e') => Key::CtrlE,
|
|
|
|
|
TermionKey::Ctrl('f') => Key::CtrlF,
|
|
|
|
|
TermionKey::Ctrl('g') => Key::CtrlG,
|
|
|
|
|
TermionKey::Ctrl('h') => Key::CtrlH,
|
|
|
|
|
TermionKey::Ctrl('i') => Key::CtrlI,
|
|
|
|
|
TermionKey::Ctrl('j') => Key::CtrlJ,
|
|
|
|
|
TermionKey::Ctrl('k') => Key::CtrlK,
|
|
|
|
|
TermionKey::Ctrl('l') => Key::CtrlL,
|
|
|
|
|
TermionKey::Ctrl('m') => Key::CtrlM,
|
|
|
|
|
TermionKey::Ctrl('n') => Key::CtrlN,
|
|
|
|
|
TermionKey::Ctrl('o') => Key::CtrlO,
|
|
|
|
|
TermionKey::Ctrl('p') => Key::CtrlP,
|
|
|
|
|
TermionKey::Ctrl('q') => Key::CtrlQ,
|
|
|
|
|
TermionKey::Ctrl('r') => Key::CtrlR,
|
|
|
|
|
TermionKey::Ctrl('s') => Key::CtrlS,
|
|
|
|
|
TermionKey::Ctrl('t') => Key::CtrlT,
|
|
|
|
|
TermionKey::Ctrl('u') => Key::CtrlU,
|
|
|
|
|
TermionKey::Ctrl('v') => Key::CtrlV,
|
|
|
|
|
TermionKey::Ctrl('w') => Key::CtrlW,
|
|
|
|
|
TermionKey::Ctrl('x') => Key::CtrlX,
|
|
|
|
|
TermionKey::Ctrl('y') => Key::CtrlY,
|
|
|
|
|
TermionKey::Ctrl('z') => Key::CtrlZ,
|
|
|
|
|
|
|
|
|
|
TermionKey::Alt('a') => Key::AltA,
|
|
|
|
|
TermionKey::Alt('b') => Key::AltB,
|
|
|
|
|
TermionKey::Alt('c') => Key::AltC,
|
|
|
|
|
TermionKey::Alt('d') => Key::AltD,
|
|
|
|
|
TermionKey::Alt('e') => Key::AltE,
|
|
|
|
|
TermionKey::Alt('f') => Key::AltF,
|
|
|
|
|
TermionKey::Alt('g') => Key::AltG,
|
|
|
|
|
TermionKey::Alt('h') => Key::AltH,
|
|
|
|
|
TermionKey::Alt('i') => Key::AltI,
|
|
|
|
|
TermionKey::Alt('j') => Key::AltJ,
|
|
|
|
|
TermionKey::Alt('k') => Key::AltK,
|
|
|
|
|
TermionKey::Alt('l') => Key::AltL,
|
|
|
|
|
TermionKey::Alt('m') => Key::AltM,
|
|
|
|
|
TermionKey::Alt('n') => Key::AltN,
|
|
|
|
|
TermionKey::Alt('o') => Key::AltO,
|
|
|
|
|
TermionKey::Alt('p') => Key::AltP,
|
|
|
|
|
TermionKey::Alt('q') => Key::AltQ,
|
|
|
|
|
TermionKey::Alt('r') => Key::AltR,
|
|
|
|
|
TermionKey::Alt('s') => Key::AltS,
|
|
|
|
|
TermionKey::Alt('t') => Key::AltT,
|
|
|
|
|
TermionKey::Alt('u') => Key::AltU,
|
|
|
|
|
TermionKey::Alt('v') => Key::AltV,
|
|
|
|
|
TermionKey::Alt('w') => Key::AltW,
|
|
|
|
|
TermionKey::Alt('x') => Key::AltX,
|
|
|
|
|
TermionKey::Alt('y') => Key::AltY,
|
|
|
|
|
TermionKey::Alt('z') => Key::AltZ,
|
|
|
|
|
|
|
|
|
|
TermionKey::Char('A') => Key::ShiftA,
|
|
|
|
|
TermionKey::Char('B') => Key::ShiftB,
|
|
|
|
|
TermionKey::Char('C') => Key::ShiftC,
|
|
|
|
|
TermionKey::Char('D') => Key::ShiftD,
|
|
|
|
|
TermionKey::Char('E') => Key::ShiftE,
|
|
|
|
|
TermionKey::Char('F') => Key::ShiftF,
|
|
|
|
|
TermionKey::Char('G') => Key::ShiftG,
|
|
|
|
|
TermionKey::Char('H') => Key::ShiftH,
|
|
|
|
|
TermionKey::Char('I') => Key::ShiftI,
|
|
|
|
|
TermionKey::Char('J') => Key::ShiftJ,
|
|
|
|
|
TermionKey::Char('K') => Key::ShiftK,
|
|
|
|
|
TermionKey::Char('L') => Key::ShiftL,
|
|
|
|
|
TermionKey::Char('M') => Key::ShiftM,
|
|
|
|
|
TermionKey::Char('N') => Key::ShiftN,
|
|
|
|
|
TermionKey::Char('O') => Key::ShiftO,
|
|
|
|
|
TermionKey::Char('P') => Key::ShiftP,
|
|
|
|
|
TermionKey::Char('Q') => Key::ShiftQ,
|
|
|
|
|
TermionKey::Char('R') => Key::ShiftR,
|
|
|
|
|
TermionKey::Char('S') => Key::ShiftS,
|
|
|
|
|
TermionKey::Char('T') => Key::ShiftT,
|
|
|
|
|
TermionKey::Char('U') => Key::ShiftU,
|
|
|
|
|
TermionKey::Char('V') => Key::ShiftV,
|
|
|
|
|
TermionKey::Char('W') => Key::ShiftW,
|
|
|
|
|
TermionKey::Char('X') => Key::ShiftX,
|
|
|
|
|
TermionKey::Char('Y') => Key::ShiftY,
|
|
|
|
|
TermionKey::Char('Z') => Key::ShiftZ,
|
|
|
|
|
|
|
|
|
|
TermionKey::Ctrl('A') => Key::CtrlShiftA,
|
|
|
|
|
TermionKey::Ctrl('B') => Key::CtrlShiftB,
|
|
|
|
|
TermionKey::Ctrl('C') => Key::CtrlShiftC,
|
|
|
|
|
TermionKey::Ctrl('D') => Key::CtrlShiftD,
|
|
|
|
|
TermionKey::Ctrl('E') => Key::CtrlShiftE,
|
|
|
|
|
TermionKey::Ctrl('F') => Key::CtrlShiftF,
|
|
|
|
|
TermionKey::Ctrl('G') => Key::CtrlShiftG,
|
|
|
|
|
TermionKey::Ctrl('H') => Key::CtrlShiftH,
|
|
|
|
|
TermionKey::Ctrl('I') => Key::CtrlShiftI,
|
|
|
|
|
TermionKey::Ctrl('J') => Key::CtrlShiftJ,
|
|
|
|
|
TermionKey::Ctrl('K') => Key::CtrlShiftK,
|
|
|
|
|
TermionKey::Ctrl('L') => Key::CtrlShiftL,
|
|
|
|
|
TermionKey::Ctrl('M') => Key::CtrlShiftM,
|
|
|
|
|
TermionKey::Ctrl('N') => Key::CtrlShiftN,
|
|
|
|
|
TermionKey::Ctrl('O') => Key::CtrlShiftO,
|
|
|
|
|
TermionKey::Ctrl('P') => Key::CtrlShiftP,
|
|
|
|
|
TermionKey::Ctrl('Q') => Key::CtrlShiftQ,
|
|
|
|
|
TermionKey::Ctrl('R') => Key::CtrlShiftR,
|
|
|
|
|
TermionKey::Ctrl('S') => Key::CtrlShiftS,
|
|
|
|
|
TermionKey::Ctrl('T') => Key::CtrlShiftT,
|
|
|
|
|
TermionKey::Ctrl('U') => Key::CtrlShiftU,
|
|
|
|
|
TermionKey::Ctrl('V') => Key::CtrlShiftV,
|
|
|
|
|
TermionKey::Ctrl('W') => Key::CtrlShiftW,
|
|
|
|
|
TermionKey::Ctrl('X') => Key::CtrlShiftX,
|
|
|
|
|
TermionKey::Ctrl('Y') => Key::CtrlShiftY,
|
|
|
|
|
TermionKey::Ctrl('Z') => Key::CtrlShiftZ,
|
|
|
|
|
|
|
|
|
|
TermionKey::Alt('A') => Key::AltShiftA,
|
|
|
|
|
TermionKey::Alt('B') => Key::AltShiftB,
|
|
|
|
|
TermionKey::Alt('C') => Key::AltShiftC,
|
|
|
|
|
TermionKey::Alt('D') => Key::AltShiftD,
|
|
|
|
|
TermionKey::Alt('E') => Key::AltShiftE,
|
|
|
|
|
TermionKey::Alt('F') => Key::AltShiftF,
|
|
|
|
|
TermionKey::Alt('G') => Key::AltShiftG,
|
|
|
|
|
TermionKey::Alt('H') => Key::AltShiftH,
|
|
|
|
|
TermionKey::Alt('I') => Key::AltShiftI,
|
|
|
|
|
TermionKey::Alt('J') => Key::AltShiftJ,
|
|
|
|
|
TermionKey::Alt('K') => Key::AltShiftK,
|
|
|
|
|
TermionKey::Alt('L') => Key::AltShiftL,
|
|
|
|
|
TermionKey::Alt('M') => Key::AltShiftM,
|
|
|
|
|
TermionKey::Alt('N') => Key::AltShiftN,
|
|
|
|
|
TermionKey::Alt('O') => Key::AltShiftO,
|
|
|
|
|
TermionKey::Alt('P') => Key::AltShiftP,
|
|
|
|
|
TermionKey::Alt('Q') => Key::AltShiftQ,
|
|
|
|
|
TermionKey::Alt('R') => Key::AltShiftR,
|
|
|
|
|
TermionKey::Alt('S') => Key::AltShiftS,
|
|
|
|
|
TermionKey::Alt('T') => Key::AltShiftT,
|
|
|
|
|
TermionKey::Alt('U') => Key::AltShiftU,
|
|
|
|
|
TermionKey::Alt('V') => Key::AltShiftV,
|
|
|
|
|
TermionKey::Alt('W') => Key::AltShiftW,
|
|
|
|
|
TermionKey::Alt('X') => Key::AltShiftX,
|
|
|
|
|
TermionKey::Alt('Y') => Key::AltShiftY,
|
|
|
|
|
TermionKey::Alt('Z') => Key::AltShiftZ,
|
|
|
|
|
|
|
|
|
|
TermionKey::Char('+') => Key::Plus,
|
|
|
|
|
TermionKey::Char('-') => Key::Minus,
|
|
|
|
|
TermionKey::Char('`') => Key::Backtick,
|
|
|
|
|
TermionKey::Char('~') => Key::Tilde,
|
|
|
|
|
TermionKey::Char('_') => Key::Underscore,
|
|
|
|
|
TermionKey::Char('=') => Key::Equals,
|
|
|
|
|
TermionKey::Char(';') => Key::Semicolon,
|
|
|
|
|
TermionKey::Char(':') => Key::Colon,
|
|
|
|
|
TermionKey::Char('\'') => Key::SingleQuote,
|
|
|
|
|
TermionKey::Char('"') => Key::DoubleQuote,
|
|
|
|
|
TermionKey::Char('/') => Key::ForwardSlash,
|
|
|
|
|
TermionKey::Char('\\') => Key::BackSlash,
|
|
|
|
|
TermionKey::Char('.') => Key::Dot,
|
|
|
|
|
TermionKey::Char(',') => Key::Comma,
|
|
|
|
|
TermionKey::Char('?') => Key::QuestionMark,
|
|
|
|
|
TermionKey::Char('#') => Key::Pound,
|
|
|
|
|
|
|
|
|
|
_ => Key::NotSupported,
|
|
|
|
|
pub fn from_event(key: KeyEvent) -> Self {
|
|
|
|
|
match key.modifiers {
|
|
|
|
|
KeyModifiers::CONTROL => match key.code {
|
|
|
|
|
KeyCode::Char('a') => Key::CtrlA,
|
|
|
|
|
KeyCode::Char('b') => Key::CtrlB,
|
|
|
|
|
KeyCode::Char('c') => Key::CtrlC,
|
|
|
|
|
KeyCode::Char('d') => Key::CtrlD,
|
|
|
|
|
KeyCode::Char('e') => Key::CtrlE,
|
|
|
|
|
KeyCode::Char('f') => Key::CtrlF,
|
|
|
|
|
KeyCode::Char('g') => Key::CtrlG,
|
|
|
|
|
KeyCode::Char('h') => Key::CtrlH,
|
|
|
|
|
KeyCode::Char('i') => Key::CtrlI,
|
|
|
|
|
KeyCode::Char('j') => Key::CtrlJ,
|
|
|
|
|
KeyCode::Char('k') => Key::CtrlK,
|
|
|
|
|
KeyCode::Char('l') => Key::CtrlL,
|
|
|
|
|
KeyCode::Char('m') => Key::CtrlM,
|
|
|
|
|
KeyCode::Char('n') => Key::CtrlN,
|
|
|
|
|
KeyCode::Char('o') => Key::CtrlO,
|
|
|
|
|
KeyCode::Char('p') => Key::CtrlP,
|
|
|
|
|
KeyCode::Char('q') => Key::CtrlQ,
|
|
|
|
|
KeyCode::Char('r') => Key::CtrlR,
|
|
|
|
|
KeyCode::Char('s') => Key::CtrlS,
|
|
|
|
|
KeyCode::Char('t') => Key::CtrlT,
|
|
|
|
|
KeyCode::Char('u') => Key::CtrlU,
|
|
|
|
|
KeyCode::Char('v') => Key::CtrlV,
|
|
|
|
|
KeyCode::Char('w') => Key::CtrlW,
|
|
|
|
|
KeyCode::Char('x') => Key::CtrlX,
|
|
|
|
|
KeyCode::Char('y') => Key::CtrlY,
|
|
|
|
|
KeyCode::Char('z') => Key::CtrlZ,
|
|
|
|
|
|
|
|
|
|
KeyCode::Char(c) => c.into(),
|
|
|
|
|
|
|
|
|
|
_ => Key::NotSupported,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
KeyModifiers::ALT => match key.code {
|
|
|
|
|
KeyCode::Char('0') => Key::AltNum0,
|
|
|
|
|
KeyCode::Char('1') => Key::AltNum1,
|
|
|
|
|
KeyCode::Char('2') => Key::AltNum2,
|
|
|
|
|
KeyCode::Char('3') => Key::AltNum3,
|
|
|
|
|
KeyCode::Char('4') => Key::AltNum4,
|
|
|
|
|
KeyCode::Char('5') => Key::AltNum5,
|
|
|
|
|
KeyCode::Char('6') => Key::AltNum6,
|
|
|
|
|
KeyCode::Char('7') => Key::AltNum7,
|
|
|
|
|
KeyCode::Char('8') => Key::AltNum8,
|
|
|
|
|
KeyCode::Char('9') => Key::AltNum9,
|
|
|
|
|
|
|
|
|
|
KeyCode::Char('a') => Key::AltA,
|
|
|
|
|
KeyCode::Char('b') => Key::AltB,
|
|
|
|
|
KeyCode::Char('c') => Key::AltC,
|
|
|
|
|
KeyCode::Char('d') => Key::AltD,
|
|
|
|
|
KeyCode::Char('e') => Key::AltE,
|
|
|
|
|
KeyCode::Char('f') => Key::AltF,
|
|
|
|
|
KeyCode::Char('g') => Key::AltG,
|
|
|
|
|
KeyCode::Char('h') => Key::AltH,
|
|
|
|
|
KeyCode::Char('i') => Key::AltI,
|
|
|
|
|
KeyCode::Char('j') => Key::AltJ,
|
|
|
|
|
KeyCode::Char('k') => Key::AltK,
|
|
|
|
|
KeyCode::Char('l') => Key::AltL,
|
|
|
|
|
KeyCode::Char('m') => Key::AltM,
|
|
|
|
|
KeyCode::Char('n') => Key::AltN,
|
|
|
|
|
KeyCode::Char('o') => Key::AltO,
|
|
|
|
|
KeyCode::Char('p') => Key::AltP,
|
|
|
|
|
KeyCode::Char('q') => Key::AltQ,
|
|
|
|
|
KeyCode::Char('r') => Key::AltR,
|
|
|
|
|
KeyCode::Char('s') => Key::AltS,
|
|
|
|
|
KeyCode::Char('t') => Key::AltT,
|
|
|
|
|
KeyCode::Char('u') => Key::AltU,
|
|
|
|
|
KeyCode::Char('v') => Key::AltV,
|
|
|
|
|
KeyCode::Char('w') => Key::AltW,
|
|
|
|
|
KeyCode::Char('x') => Key::AltX,
|
|
|
|
|
KeyCode::Char('y') => Key::AltY,
|
|
|
|
|
KeyCode::Char('z') => Key::AltZ,
|
|
|
|
|
|
|
|
|
|
KeyCode::Char(c) => c.into(),
|
|
|
|
|
|
|
|
|
|
_ => Key::NotSupported,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
_ => match key.code {
|
|
|
|
|
KeyCode::F(1) => Key::F1,
|
|
|
|
|
KeyCode::F(2) => Key::F2,
|
|
|
|
|
KeyCode::F(3) => Key::F3,
|
|
|
|
|
KeyCode::F(4) => Key::F4,
|
|
|
|
|
KeyCode::F(5) => Key::F5,
|
|
|
|
|
KeyCode::F(6) => Key::F6,
|
|
|
|
|
KeyCode::F(7) => Key::F7,
|
|
|
|
|
KeyCode::F(8) => Key::F8,
|
|
|
|
|
KeyCode::F(9) => Key::F9,
|
|
|
|
|
KeyCode::F(10) => Key::F10,
|
|
|
|
|
KeyCode::F(11) => Key::F11,
|
|
|
|
|
KeyCode::F(12) => Key::F12,
|
|
|
|
|
|
|
|
|
|
KeyCode::Backspace => Key::Backspace,
|
|
|
|
|
KeyCode::Left => Key::Left,
|
|
|
|
|
KeyCode::Right => Key::Right,
|
|
|
|
|
KeyCode::Up => Key::Up,
|
|
|
|
|
KeyCode::Down => Key::Down,
|
|
|
|
|
KeyCode::Home => Key::Home,
|
|
|
|
|
KeyCode::End => Key::End,
|
|
|
|
|
KeyCode::PageUp => Key::PageUp,
|
|
|
|
|
KeyCode::PageDown => Key::PageDown,
|
|
|
|
|
KeyCode::BackTab => Key::BackTab,
|
|
|
|
|
KeyCode::Delete => Key::Delete,
|
|
|
|
|
KeyCode::Insert => Key::Insert,
|
|
|
|
|
KeyCode::Enter => Key::Enter,
|
|
|
|
|
KeyCode::Tab => Key::Tab,
|
|
|
|
|
KeyCode::Esc => Key::Esc,
|
|
|
|
|
|
|
|
|
|
KeyCode::Char(c) => c.into(),
|
|
|
|
|
|
|
|
|
|
_ => Key::NotSupported,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn is_alphabet(&self) -> bool {
|
|
|
|
|
match self {
|
|
|
|
|
Self::A => true,
|
|
|
|
|
Self::B => true,
|
|
|
|
|
Self::C => true,
|
|
|
|
|
Self::D => true,
|
|
|
|
|
Self::E => true,
|
|
|
|
|
Self::F => true,
|
|
|
|
|
Self::G => true,
|
|
|
|
|
Self::H => true,
|
|
|
|
|
Self::I => true,
|
|
|
|
|
Self::J => true,
|
|
|
|
|
Self::K => true,
|
|
|
|
|
Self::L => true,
|
|
|
|
|
Self::M => true,
|
|
|
|
|
Self::N => true,
|
|
|
|
|
Self::O => true,
|
|
|
|
|
Self::P => true,
|
|
|
|
|
Self::Q => true,
|
|
|
|
|
Self::R => true,
|
|
|
|
|
Self::S => true,
|
|
|
|
|
Self::T => true,
|
|
|
|
|
Self::U => true,
|
|
|
|
|
Self::V => true,
|
|
|
|
|
Self::W => true,
|
|
|
|
|
Self::X => true,
|
|
|
|
|
Self::Y => true,
|
|
|
|
|
Self::Z => true,
|
|
|
|
|
|
|
|
|
|
Self::ShiftA => true,
|
|
|
|
|
Self::ShiftB => true,
|
|
|
|
|
Self::ShiftC => true,
|
|
|
|
|
Self::ShiftD => true,
|
|
|
|
|
Self::ShiftE => true,
|
|
|
|
|
Self::ShiftF => true,
|
|
|
|
|
Self::ShiftG => true,
|
|
|
|
|
Self::ShiftH => true,
|
|
|
|
|
Self::ShiftI => true,
|
|
|
|
|
Self::ShiftJ => true,
|
|
|
|
|
Self::ShiftK => true,
|
|
|
|
|
Self::ShiftL => true,
|
|
|
|
|
Self::ShiftM => true,
|
|
|
|
|
Self::ShiftN => true,
|
|
|
|
|
Self::ShiftO => true,
|
|
|
|
|
Self::ShiftP => true,
|
|
|
|
|
Self::ShiftQ => true,
|
|
|
|
|
Self::ShiftR => true,
|
|
|
|
|
Self::ShiftS => true,
|
|
|
|
|
Self::ShiftT => true,
|
|
|
|
|
Self::ShiftU => true,
|
|
|
|
|
Self::ShiftV => true,
|
|
|
|
|
Self::ShiftW => true,
|
|
|
|
|
Self::ShiftX => true,
|
|
|
|
|
Self::ShiftY => true,
|
|
|
|
|
Self::ShiftZ => true,
|
|
|
|
|
|
|
|
|
|
_ => false,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn is_number(&self) -> bool {
|
|
|
|
|
match self {
|
|
|
|
|
Self::Num0 => true,
|
|
|
|
|
Self::Num1 => true,
|
|
|
|
|
Self::Num2 => true,
|
|
|
|
|
Self::Num3 => true,
|
|
|
|
|
Self::Num4 => true,
|
|
|
|
|
Self::Num5 => true,
|
|
|
|
|
Self::Num6 => true,
|
|
|
|
|
Self::Num7 => true,
|
|
|
|
|
Self::Num8 => true,
|
|
|
|
|
Self::Num9 => true,
|
|
|
|
|
_ => false,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn is_special_character(&self) -> bool {
|
|
|
|
|
match self {
|
|
|
|
|
Self::Special(_) => true,
|
|
|
|
|
_ => false,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn to_char(&self) -> Option<char> {
|
|
|
|
|
match self {
|
|
|
|
|
Self::Num0 => Some('0'),
|
|
|
|
|
Self::Num1 => Some('1'),
|
|
|
|
|
Self::Num2 => Some('2'),
|
|
|
|
|
Self::Num3 => Some('3'),
|
|
|
|
|
Self::Num4 => Some('4'),
|
|
|
|
|
Self::Num5 => Some('5'),
|
|
|
|
|
Self::Num6 => Some('6'),
|
|
|
|
|
Self::Num7 => Some('7'),
|
|
|
|
|
Self::Num8 => Some('8'),
|
|
|
|
|
Self::Num9 => Some('9'),
|
|
|
|
|
|
|
|
|
|
Self::A => Some('a'),
|
|
|
|
|
Self::B => Some('b'),
|
|
|
|
|
Self::C => Some('c'),
|
|
|
|
|
Self::D => Some('d'),
|
|
|
|
|
Self::E => Some('e'),
|
|
|
|
|
Self::F => Some('f'),
|
|
|
|
|
Self::G => Some('g'),
|
|
|
|
|
Self::H => Some('h'),
|
|
|
|
|
Self::I => Some('i'),
|
|
|
|
|
Self::J => Some('j'),
|
|
|
|
|
Self::K => Some('k'),
|
|
|
|
|
Self::L => Some('l'),
|
|
|
|
|
Self::M => Some('m'),
|
|
|
|
|
Self::N => Some('n'),
|
|
|
|
|
Self::O => Some('o'),
|
|
|
|
|
Self::P => Some('p'),
|
|
|
|
|
Self::Q => Some('q'),
|
|
|
|
|
Self::R => Some('r'),
|
|
|
|
|
Self::S => Some('s'),
|
|
|
|
|
Self::T => Some('t'),
|
|
|
|
|
Self::U => Some('u'),
|
|
|
|
|
Self::V => Some('v'),
|
|
|
|
|
Self::W => Some('w'),
|
|
|
|
|
Self::X => Some('x'),
|
|
|
|
|
Self::Y => Some('y'),
|
|
|
|
|
Self::Z => Some('z'),
|
|
|
|
|
|
|
|
|
|
Self::ShiftA => Some('A'),
|
|
|
|
|
Self::ShiftB => Some('B'),
|
|
|
|
|
Self::ShiftC => Some('C'),
|
|
|
|
|
Self::ShiftD => Some('D'),
|
|
|
|
|
Self::ShiftE => Some('E'),
|
|
|
|
|
Self::ShiftF => Some('F'),
|
|
|
|
|
Self::ShiftG => Some('G'),
|
|
|
|
|
Self::ShiftH => Some('H'),
|
|
|
|
|
Self::ShiftI => Some('I'),
|
|
|
|
|
Self::ShiftJ => Some('J'),
|
|
|
|
|
Self::ShiftK => Some('K'),
|
|
|
|
|
Self::ShiftL => Some('L'),
|
|
|
|
|
Self::ShiftM => Some('M'),
|
|
|
|
|
Self::ShiftN => Some('N'),
|
|
|
|
|
Self::ShiftO => Some('O'),
|
|
|
|
|
Self::ShiftP => Some('P'),
|
|
|
|
|
Self::ShiftQ => Some('Q'),
|
|
|
|
|
Self::ShiftR => Some('R'),
|
|
|
|
|
Self::ShiftS => Some('S'),
|
|
|
|
|
Self::ShiftT => Some('T'),
|
|
|
|
|
Self::ShiftU => Some('U'),
|
|
|
|
|
Self::ShiftV => Some('V'),
|
|
|
|
|
Self::ShiftW => Some('W'),
|
|
|
|
|
Self::ShiftX => Some('X'),
|
|
|
|
|
Self::ShiftY => Some('Y'),
|
|
|
|
|
Self::ShiftZ => Some('Z'),
|
|
|
|
|
|
|
|
|
|
Self::Special(c) => Some(c.to_owned()),
|
|
|
|
|
|
|
|
|
|
_ => None,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<char> for Key {
|
|
|
|
|
fn from(c: char) -> Self {
|
|
|
|
|
match c {
|
|
|
|
|
'0' => Key::Num0,
|
|
|
|
|
'1' => Key::Num1,
|
|
|
|
|
'2' => Key::Num2,
|
|
|
|
|
'3' => Key::Num3,
|
|
|
|
|
'4' => Key::Num4,
|
|
|
|
|
'5' => Key::Num5,
|
|
|
|
|
'6' => Key::Num6,
|
|
|
|
|
'7' => Key::Num7,
|
|
|
|
|
'8' => Key::Num8,
|
|
|
|
|
'9' => Key::Num9,
|
|
|
|
|
|
|
|
|
|
'a' => Key::A,
|
|
|
|
|
'b' => Key::B,
|
|
|
|
|
'c' => Key::C,
|
|
|
|
|
'd' => Key::D,
|
|
|
|
|
'e' => Key::E,
|
|
|
|
|
'f' => Key::F,
|
|
|
|
|
'g' => Key::G,
|
|
|
|
|
'h' => Key::H,
|
|
|
|
|
'i' => Key::I,
|
|
|
|
|
'j' => Key::J,
|
|
|
|
|
'k' => Key::K,
|
|
|
|
|
'l' => Key::L,
|
|
|
|
|
'm' => Key::M,
|
|
|
|
|
'n' => Key::N,
|
|
|
|
|
'o' => Key::O,
|
|
|
|
|
'p' => Key::P,
|
|
|
|
|
'q' => Key::Q,
|
|
|
|
|
'r' => Key::R,
|
|
|
|
|
's' => Key::S,
|
|
|
|
|
't' => Key::T,
|
|
|
|
|
'u' => Key::U,
|
|
|
|
|
'v' => Key::V,
|
|
|
|
|
'w' => Key::W,
|
|
|
|
|
'x' => Key::X,
|
|
|
|
|
'y' => Key::Y,
|
|
|
|
|
'z' => Key::Z,
|
|
|
|
|
|
|
|
|
|
'A' => Key::ShiftA,
|
|
|
|
|
'B' => Key::ShiftB,
|
|
|
|
|
'C' => Key::ShiftC,
|
|
|
|
|
'D' => Key::ShiftD,
|
|
|
|
|
'E' => Key::ShiftE,
|
|
|
|
|
'F' => Key::ShiftF,
|
|
|
|
|
'G' => Key::ShiftG,
|
|
|
|
|
'H' => Key::ShiftH,
|
|
|
|
|
'I' => Key::ShiftI,
|
|
|
|
|
'J' => Key::ShiftJ,
|
|
|
|
|
'K' => Key::ShiftK,
|
|
|
|
|
'L' => Key::ShiftL,
|
|
|
|
|
'M' => Key::ShiftM,
|
|
|
|
|
'N' => Key::ShiftN,
|
|
|
|
|
'O' => Key::ShiftO,
|
|
|
|
|
'P' => Key::ShiftP,
|
|
|
|
|
'Q' => Key::ShiftQ,
|
|
|
|
|
'R' => Key::ShiftR,
|
|
|
|
|
'S' => Key::ShiftS,
|
|
|
|
|
'T' => Key::ShiftT,
|
|
|
|
|
'U' => Key::ShiftU,
|
|
|
|
|
'V' => Key::ShiftV,
|
|
|
|
|
'W' => Key::ShiftW,
|
|
|
|
|
'X' => Key::ShiftX,
|
|
|
|
|
'Y' => Key::ShiftY,
|
|
|
|
|
'Z' => Key::ShiftZ,
|
|
|
|
|
|
|
|
|
|
' ' => Key::Space,
|
|
|
|
|
'\t' => Key::Tab,
|
|
|
|
|
'\n' => Key::Enter,
|
|
|
|
|
|
|
|
|
|
c => Key::Special(c),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<String> for Key {
|
|
|
|
|
fn from(string: String) -> Self {
|
|
|
|
|
string
|
|
|
|
|
.chars()
|
|
|
|
|
.next()
|
|
|
|
|
.map(|c| c.into())
|
|
|
|
|
.unwrap_or(Key::NotSupported)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<&str> for Key {
|
|
|
|
|
fn from(string: &str) -> Self {
|
|
|
|
|
string.to_string().into()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Ord for Key {
|
|
|
|
|
fn cmp(&self, other: &Self) -> Ordering {
|
|
|
|
|
// Notice that the we flip the ordering on costs.
|
|
|
|
|
// In case of a tie we compare positions - this step is necessary
|
|
|
|
|
// to make implementations of `PartialEq` and `Ord` consistent.
|
|
|
|
|
other.to_string().cmp(&self.to_string())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
impl PartialOrd for Key {
|
|
|
|
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
|
|
|
|
Some(self.cmp(other))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|