diff --git a/src/edit_mode/vi/mod.rs b/src/edit_mode/vi/mod.rs index de6bf722..a3b54726 100644 --- a/src/edit_mode/vi/mod.rs +++ b/src/edit_mode/vi/mod.rs @@ -75,9 +75,11 @@ impl Vi { impl EditMode for Vi { fn parse_event(&mut self, event: ReedlineRawEvent) -> ReedlineEvent { match event.into() { - Event::Key(KeyEvent { - code, modifiers, .. - }) => match (self.mode, modifiers, code) { + Event::Key( + key_event @ KeyEvent { + code, modifiers, .. + }, + ) => match (self.mode, modifiers, code) { (ViMode::Normal, KeyModifiers::NONE, KeyCode::Char('v')) => { self.cache.clear(); self.mode = ViMode::Visual; @@ -91,6 +93,8 @@ impl EditMode for Vi { .find_binding(modifiers, KeyCode::Char(c)) { event + } else if let Some(event) = self.handle_alt_as_esc(key_event) { + event } else if modifier == KeyModifiers::NONE || modifier == KeyModifiers::SHIFT { self.cache.push(if modifier == KeyModifiers::SHIFT { c.to_ascii_uppercase() @@ -134,23 +138,28 @@ impl EditMode for Vi { self.insert_keybindings .find_binding(modifier, KeyCode::Char(c)) .unwrap_or_else(|| { - if modifier == KeyModifiers::NONE - || modifier == KeyModifiers::SHIFT - || modifier == KeyModifiers::CONTROL | KeyModifiers::ALT - || modifier - == KeyModifiers::CONTROL - | KeyModifiers::ALT - | KeyModifiers::SHIFT - { - ReedlineEvent::Edit(vec![EditCommand::InsertChar( - if modifier == KeyModifiers::SHIFT { - c.to_ascii_uppercase() - } else { - c - }, - )]) + if let Some(event) = self.handle_alt_as_esc(key_event) { + event } else { - ReedlineEvent::None + // including alt here is a bit redundant now + if modifier == KeyModifiers::NONE + || modifier == KeyModifiers::SHIFT + || modifier == KeyModifiers::CONTROL | KeyModifiers::ALT + || modifier + == KeyModifiers::CONTROL + | KeyModifiers::ALT + | KeyModifiers::SHIFT + { + ReedlineEvent::Edit(vec![EditCommand::InsertChar( + if modifier == KeyModifiers::SHIFT { + c.to_ascii_uppercase() + } else { + c + }, + )]) + } else { + ReedlineEvent::None + } } }) } @@ -204,6 +213,21 @@ impl EditMode for Vi { } } +impl Vi { + fn handle_alt_as_esc(&mut self, mut event: KeyEvent) -> Option { + if event.modifiers.contains(KeyModifiers::ALT) { + self.mode = ViMode::Normal; + event.modifiers &= !KeyModifiers::ALT; + + ReedlineRawEvent::try_from(Event::Key(event)) + .ok() + .map(|event| self.parse_event(event)) + } else { + None + } + } +} + #[cfg(test)] mod test { use super::*;