Allow typing space in workspace::SendKeystrokes (#8288)

Conrad Irwin created

Fixes #8222

Release Notes:

- N/A

Change summary

crates/gpui/src/platform/keystroke.rs | 29 +++++++++++++++++++++++++++++
crates/gpui/src/window.rs             | 14 ++------------
crates/vim/src/test.rs                | 12 ++++++++++++
3 files changed, 43 insertions(+), 12 deletions(-)

Detailed changes

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 {

crates/gpui/src/window.rs 🔗

@@ -1101,18 +1101,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,

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);
 }