@@ -13,6 +13,32 @@ pub struct KeyEvent {
1313 pub modifiers: KeyModifiers,
1414}
1515
16+pub(crate) mod keys {
17+ pub(crate) const BACKSPACE: &str = "backspace";
18+ pub(crate) const ENTER: &str = "ret";
19+ pub(crate) const LEFT: &str = "left";
20+ pub(crate) const RIGHT: &str = "right";
21+ pub(crate) const UP: &str = "up";
22+ pub(crate) const DOWN: &str = "down";
23+ pub(crate) const HOME: &str = "home";
24+ pub(crate) const END: &str = "end";
25+ pub(crate) const PAGEUP: &str = "pageup";
26+ pub(crate) const PAGEDOWN: &str = "pagedown";
27+ pub(crate) const TAB: &str = "tab";
28+ pub(crate) const BACKTAB: &str = "backtab";
29+ pub(crate) const DELETE: &str = "del";
30+ pub(crate) const INSERT: &str = "ins";
31+ pub(crate) const NULL: &str = "null";
32+ pub(crate) const ESC: &str = "esc";
33+ pub(crate) const SPACE: &str = "space";
34+ pub(crate) const LESS_THAN: &str = "lt";
35+ pub(crate) const GREATER_THAN: &str = "gt";
36+ pub(crate) const PLUS: &str = "plus";
37+ pub(crate) const MINUS: &str = "minus";
38+ pub(crate) const SEMICOLON: &str = "semicolon";
39+ pub(crate) const PERCENT: &str = "percent";
40+}
41+
1642impl fmt::Display for KeyEvent {
1743 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
1844 f.write_fmt(format_args!(
@@ -34,28 +60,29 @@ impl fmt::Display for KeyEvent {
3460 },
3561 ))?;
3662 match self.code {
37− KeyCode::Backspace => f.write_str("backspace")?,
38− KeyCode::Enter => f.write_str("ret")?,
39− KeyCode::Left => f.write_str("left")?,
40− KeyCode::Right => f.write_str("right")?,
41− KeyCode::Up => f.write_str("up")?,
42− KeyCode::Down => f.write_str("down")?,
43− KeyCode::Home => f.write_str("home")?,
44− KeyCode::End => f.write_str("end")?,
45− KeyCode::PageUp => f.write_str("pageup")?,
46− KeyCode::PageDown => f.write_str("pagedown")?,
47− KeyCode::Tab => f.write_str("tab")?,
48− KeyCode::BackTab => f.write_str("backtab")?,
49− KeyCode::Delete => f.write_str("del")?,
50− KeyCode::Insert => f.write_str("ins")?,
51− KeyCode::Null => f.write_str("null")?,
52− KeyCode::Esc => f.write_str("esc")?,
53− KeyCode::Char('<') => f.write_str("lt")?,
54− KeyCode::Char('>') => f.write_str("gt")?,
55− KeyCode::Char('+') => f.write_str("plus")?,
56− KeyCode::Char('-') => f.write_str("minus")?,
57− KeyCode::Char(';') => f.write_str("semicolon")?,
58− KeyCode::Char('%') => f.write_str("percent")?,
63+ KeyCode::Backspace => f.write_str(keys::BACKSPACE)?,
64+ KeyCode::Enter => f.write_str(keys::ENTER)?,
65+ KeyCode::Left => f.write_str(keys::LEFT)?,
66+ KeyCode::Right => f.write_str(keys::RIGHT)?,
67+ KeyCode::Up => f.write_str(keys::UP)?,
68+ KeyCode::Down => f.write_str(keys::DOWN)?,
69+ KeyCode::Home => f.write_str(keys::HOME)?,
70+ KeyCode::End => f.write_str(keys::END)?,
71+ KeyCode::PageUp => f.write_str(keys::PAGEUP)?,
72+ KeyCode::PageDown => f.write_str(keys::PAGEDOWN)?,
73+ KeyCode::Tab => f.write_str(keys::TAB)?,
74+ KeyCode::BackTab => f.write_str(keys::BACKTAB)?,
75+ KeyCode::Delete => f.write_str(keys::DELETE)?,
76+ KeyCode::Insert => f.write_str(keys::INSERT)?,
77+ KeyCode::Null => f.write_str(keys::NULL)?,
78+ KeyCode::Esc => f.write_str(keys::ESC)?,
79+ KeyCode::Char(' ') => f.write_str(keys::SPACE)?,
80+ KeyCode::Char('<') => f.write_str(keys::LESS_THAN)?,
81+ KeyCode::Char('>') => f.write_str(keys::GREATER_THAN)?,
82+ KeyCode::Char('+') => f.write_str(keys::PLUS)?,
83+ KeyCode::Char('-') => f.write_str(keys::MINUS)?,
84+ KeyCode::Char(';') => f.write_str(keys::SEMICOLON)?,
85+ KeyCode::Char('%') => f.write_str(keys::PERCENT)?,
5986 KeyCode::F(i) => f.write_fmt(format_args!("F{}", i))?,
6087 KeyCode::Char(c) => f.write_fmt(format_args!("{}", c))?,
6188 };
@@ -63,34 +90,83 @@ impl fmt::Display for KeyEvent {
6390 }
6491}
6592
93+impl unicode_width::UnicodeWidthStr for KeyEvent {
94+ fn width(&self) -> usize {
95+ use unicode_width::UnicodeWidthChar;
96+ let mut width = match self.code {
97+ KeyCode::Backspace => keys::BACKSPACE.len(),
98+ KeyCode::Enter => keys::ENTER.len(),
99+ KeyCode::Left => keys::LEFT.len(),
100+ KeyCode::Right => keys::RIGHT.len(),
101+ KeyCode::Up => keys::UP.len(),
102+ KeyCode::Down => keys::DOWN.len(),
103+ KeyCode::Home => keys::HOME.len(),
104+ KeyCode::End => keys::END.len(),
105+ KeyCode::PageUp => keys::PAGEUP.len(),
106+ KeyCode::PageDown => keys::PAGEDOWN.len(),
107+ KeyCode::Tab => keys::TAB.len(),
108+ KeyCode::BackTab => keys::BACKTAB.len(),
109+ KeyCode::Delete => keys::DELETE.len(),
110+ KeyCode::Insert => keys::INSERT.len(),
111+ KeyCode::Null => keys::NULL.len(),
112+ KeyCode::Esc => keys::ESC.len(),
113+ KeyCode::Char(' ') => keys::SPACE.len(),
114+ KeyCode::Char('<') => keys::LESS_THAN.len(),
115+ KeyCode::Char('>') => keys::GREATER_THAN.len(),
116+ KeyCode::Char('+') => keys::PLUS.len(),
117+ KeyCode::Char('-') => keys::MINUS.len(),
118+ KeyCode::Char(';') => keys::SEMICOLON.len(),
119+ KeyCode::Char('%') => keys::PERCENT.len(),
120+ KeyCode::F(1..=9) => 2,
121+ KeyCode::F(_) => 3,
122+ KeyCode::Char(c) => c.width().unwrap_or(0),
123+ };
124+ if self.modifiers.contains(KeyModifiers::SHIFT) {
125+ width += 2;
126+ }
127+ if self.modifiers.contains(KeyModifiers::ALT) {
128+ width += 2;
129+ }
130+ if self.modifiers.contains(KeyModifiers::CONTROL) {
131+ width += 2;
132+ }
133+ width
134+ }
135+
136+ fn width_cjk(&self) -> usize {
137+ self.width()
138+ }
139+}
140+
66141impl std::str::FromStr for KeyEvent {
67142 type Err = Error;
68143
69144 fn from_str(s: &str) -> Result<Self, Self::Err> {
70145 let mut tokens: Vec<_> = s.split('-').collect();
71146 let code = match tokens.pop().ok_or_else(|| anyhow!("Missing key code"))? {
72− "backspace" => KeyCode::Backspace,
73− "space" => KeyCode::Char(' '),
74− "ret" => KeyCode::Enter,
75− "lt" => KeyCode::Char('<'),
76− "gt" => KeyCode::Char('>'),
77− "plus" => KeyCode::Char('+'),
78− "minus" => KeyCode::Char('-'),
79− "semicolon" => KeyCode::Char(';'),
80− "percent" => KeyCode::Char('%'),
81− "left" => KeyCode::Left,
82− "right" => KeyCode::Right,
83− "up" => KeyCode::Down,
84− "home" => KeyCode::Home,
85− "end" => KeyCode::End,
86− "pageup" => KeyCode::PageUp,
87− "pagedown" => KeyCode::PageDown,
88− "tab" => KeyCode::Tab,
89− "backtab" => KeyCode::BackTab,
90− "del" => KeyCode::Delete,
91− "ins" => KeyCode::Insert,
92− "null" => KeyCode::Null,
93− "esc" => KeyCode::Esc,
147+ keys::BACKSPACE => KeyCode::Backspace,
148+ keys::ENTER => KeyCode::Enter,
149+ keys::LEFT => KeyCode::Left,
150+ keys::RIGHT => KeyCode::Right,
151+ keys::UP => KeyCode::Up,
152+ keys::DOWN => KeyCode::Down,
153+ keys::HOME => KeyCode::Home,
154+ keys::END => KeyCode::End,
155+ keys::PAGEUP => KeyCode::PageUp,
156+ keys::PAGEDOWN => KeyCode::PageDown,
157+ keys::TAB => KeyCode::Tab,
158+ keys::BACKTAB => KeyCode::BackTab,
159+ keys::DELETE => KeyCode::Delete,
160+ keys::INSERT => KeyCode::Insert,
161+ keys::NULL => KeyCode::Null,
162+ keys::ESC => KeyCode::Esc,
163+ keys::SPACE => KeyCode::Char(' '),
164+ keys::LESS_THAN => KeyCode::Char('<'),
165+ keys::GREATER_THAN => KeyCode::Char('>'),
166+ keys::PLUS => KeyCode::Char('+'),
167+ keys::MINUS => KeyCode::Char('-'),
168+ keys::SEMICOLON => KeyCode::Char(';'),
169+ keys::PERCENT => KeyCode::Char('%'),
94170 single if single.len() == 1 => KeyCode::Char(single.chars().next().unwrap()),
95171 function if function.len() > 1 && function.starts_with('F') => {
96172 let function: String = function.chars().skip(1).collect();