diff --git a/crates/gpui/src/platform/keystroke.rs b/crates/gpui/src/platform/keystroke.rs index 9cdffd5e61..d6c4ea28a5 100644 --- a/crates/gpui/src/platform/keystroke.rs +++ b/crates/gpui/src/platform/keystroke.rs @@ -108,6 +108,35 @@ impl Keystroke { ime_key, }) } + + /// Returns a new keystroke with the ime_key filled. + /// This is used for dispatch_keystroke where we want users to + /// be able to simulate typing "space", etc. + pub fn with_simulated_ime(mut self) -> Self { + if self.ime_key.is_none() + && !self.modifiers.command + && !self.modifiers.control + && !self.modifiers.function + && !self.modifiers.alt + { + self.ime_key = match self.key.as_str() { + "space" => Some(" ".into()), + "tab" => Some("\t".into()), + "enter" => Some("\n".into()), + "up" | "down" | "left" | "right" | "pageup" | "pagedown" | "home" | "end" + | "delete" | "escape" | "backspace" | "f1" | "f2" | "f3" | "f4" | "f5" | "f6" + | "f7" | "f8" | "f9" | "f10" | "f11" | "f12" => None, + key => { + if self.modifiers.shift { + Some(key.to_uppercase()) + } else { + Some(key.into()) + } + } + } + } + self + } } impl std::fmt::Display for Keystroke { diff --git a/crates/gpui/src/window.rs b/crates/gpui/src/window.rs index 0a45934ad2..2d2f6b8e10 100644 --- a/crates/gpui/src/window.rs +++ b/crates/gpui/src/window.rs @@ -1104,18 +1104,8 @@ impl<'a> WindowContext<'a> { /// Dispatch a given keystroke as though the user had typed it. /// You can create a keystroke with Keystroke::parse(""). - pub fn dispatch_keystroke(&mut self, mut keystroke: Keystroke) -> bool { - if keystroke.ime_key.is_none() - && !keystroke.modifiers.command - && !keystroke.modifiers.control - && !keystroke.modifiers.function - { - keystroke.ime_key = Some(if keystroke.modifiers.shift { - keystroke.key.to_uppercase().clone() - } else { - keystroke.key.clone() - }) - } + pub fn dispatch_keystroke(&mut self, keystroke: Keystroke) -> bool { + let keystroke = keystroke.with_simulated_ime(); if self.dispatch_event(PlatformInput::KeyDown(KeyDownEvent { keystroke: keystroke.clone(), is_held: false, diff --git a/crates/vim/src/test.rs b/crates/vim/src/test.rs index 75961f8750..71399dfa3b 100644 --- a/crates/vim/src/test.rs +++ b/crates/vim/src/test.rs @@ -950,4 +950,16 @@ async fn test_remap(cx: &mut gpui::TestAppContext) { cx.set_state("ˇ1234\n56789", Mode::Normal); cx.simulate_keystrokes(["g", "u"]); cx.assert_state("1234 567ˇ89", Mode::Normal); + + // test leaving command + cx.update(|cx| { + cx.bind_keys([KeyBinding::new( + "g t", + workspace::SendKeystrokes("i space escape".to_string()), + None, + )]) + }); + cx.set_state("12ˇ34", Mode::Normal); + cx.simulate_keystrokes(["g", "t"]); + cx.assert_state("12ˇ 34", Mode::Normal); }