Add simple IME handling to the terminal

Max Brunsfeld created

Change summary

crates/editor/src/element.rs                  |  7 +++
crates/terminal/src/connection/keymappings.rs | 48 --------------------
crates/terminal/src/terminal.rs               |  4 +
crates/terminal/src/terminal_element.rs       | 15 +++++-
styles/package-lock.json                      |  1 
5 files changed, 25 insertions(+), 50 deletions(-)

Detailed changes

crates/editor/src/element.rs 🔗

@@ -1713,6 +1713,13 @@ impl Cursor {
         }
     }
 
+    pub fn bounding_rect(&self, origin: Vector2F) -> RectF {
+        RectF::new(
+            self.origin + origin,
+            vec2f(self.block_width, self.line_height),
+        )
+    }
+
     pub fn paint(&self, origin: Vector2F, cx: &mut PaintContext) {
         let bounds = match self.shape {
             CursorShape::Bar => RectF::new(self.origin + origin, vec2f(2.0, self.line_height)),

crates/terminal/src/connection/keymappings.rs 🔗

@@ -240,53 +240,7 @@ pub fn to_esc_str(keystroke: &Keystroke, mode: &TermMode) -> Option<String> {
         }
     }
 
-    //Fallback to sending the keystroke input directly
-    //Skin colors in utf8 are implemented as a seperate, invisible character
-    //that modifies the associated emoji. Some languages may have similarly
-    //implemented modifiers, e.g. certain diacritics that can be typed as a single character.
-    //This means that we need to assume some user input can result in multi-byte,
-    //multi-char strings. This is somewhat difficult, as GPUI normalizes all
-    //keys into a string representation. Hence, the check here to filter out GPUI
-    //keys that weren't captured above.
-    if !matches_gpui_key_str(&keystroke.key) {
-        return Some(keystroke.key.clone());
-    } else {
-        None
-    }
-}
-
-///Checks if the given string matches a GPUI key string.
-///Table made from reading the source at gpui/src/platform/mac/event.rs
-fn matches_gpui_key_str(str: &str) -> bool {
-    match str {
-        "backspace" => true,
-        "up" => true,
-        "down" => true,
-        "left" => true,
-        "right" => true,
-        "pageup" => true,
-        "pagedown" => true,
-        "home" => true,
-        "end" => true,
-        "delete" => true,
-        "enter" => true,
-        "escape" => true,
-        "tab" => true,
-        "f1" => true,
-        "f2" => true,
-        "f3" => true,
-        "f4" => true,
-        "f5" => true,
-        "f6" => true,
-        "f7" => true,
-        "f8" => true,
-        "f9" => true,
-        "f10" => true,
-        "f11" => true,
-        "f12" => true,
-        "space" => true,
-        _ => false,
-    }
+    None
 }
 
 ///   Code     Modifiers

crates/terminal/src/terminal.rs 🔗

@@ -262,6 +262,10 @@ impl View for Terminal {
         context
     }
 
+    fn selected_text_range(&self, _: &AppContext) -> Option<std::ops::Range<usize>> {
+        Some(0..0)
+    }
+
     fn replace_text_in_range(
         &mut self,
         _: Option<std::ops::Range<usize>>,

crates/terminal/src/terminal_element.rs 🔗

@@ -398,13 +398,22 @@ impl Element for TerminalEl {
     fn rect_for_text_range(
         &self,
         _: Range<usize>,
+        bounds: RectF,
         _: RectF,
-        _: RectF,
-        _: &Self::LayoutState,
+        layout: &Self::LayoutState,
         _: &Self::PaintState,
         _: &gpui::MeasurementContext,
     ) -> Option<RectF> {
-        todo!()
+        // Use the same origin that's passed to `Cursor::paint` in the paint
+        // method bove.
+        let mut origin = bounds.origin() + vec2f(layout.em_width.0, 0.);
+
+        // TODO - Why is it necessary to move downward one line to get correct
+        // positioning? I would think that we'd want the same rect that is
+        // painted for the cursor.
+        origin += vec2f(0., layout.line_height.0);
+
+        Some(layout.cursor.as_ref()?.bounding_rect(origin))
     }
 
     fn debug(

styles/package-lock.json 🔗

@@ -5,6 +5,7 @@
     "requires": true,
     "packages": {
         "": {
+            "name": "styles",
             "version": "1.0.0",
             "license": "ISC",
             "dependencies": {