Refactor `KeybindingKeystroke` (#37065)

张小白 created

This pull request refactors the `KeybindingKeystroke` struct and related
code to improve platform abstraction. The changes centralize
platform-specific logic within `KeybindingKeystroke` and update its
usage throughout the codebase, making the API more consistent and less
error-prone.



Release Notes:

- N/A

Change summary

crates/editor/src/editor.rs                             |  24 +-
crates/gpui/src/keymap.rs                               |   2 
crates/gpui/src/keymap/binding.rs                       |   2 
crates/gpui/src/platform/keystroke.rs                   | 117 +++++++++-
crates/gpui/src/platform/mac/platform.rs                |  10 
crates/gpui/src/platform/windows/keyboard.rs            |  32 +-
crates/settings/src/keymap_file.rs                      |  10 
crates/settings_ui/src/keybindings.rs                   |  50 +---
crates/settings_ui/src/ui_components/keystroke_input.rs |  38 +-
crates/ui/src/components/keybinding.rs                  |  19 -
crates/zed/src/zed.rs                                   |   2 
11 files changed, 183 insertions(+), 123 deletions(-)

Detailed changes

crates/editor/src/editor.rs 🔗

@@ -2588,7 +2588,7 @@ impl Editor {
                 || binding
                     .keystrokes()
                     .first()
-                    .is_some_and(|keystroke| keystroke.display_modifiers.modified())
+                    .is_some_and(|keystroke| keystroke.modifiers().modified())
         }))
     }
 
@@ -7686,16 +7686,16 @@ impl Editor {
             .keystroke()
         {
             modifiers_held = modifiers_held
-                || (&accept_keystroke.display_modifiers == modifiers
-                    && accept_keystroke.display_modifiers.modified());
+                || (accept_keystroke.modifiers() == modifiers
+                    && accept_keystroke.modifiers().modified());
         };
         if let Some(accept_partial_keystroke) = self
             .accept_edit_prediction_keybind(true, window, cx)
             .keystroke()
         {
             modifiers_held = modifiers_held
-                || (&accept_partial_keystroke.display_modifiers == modifiers
-                    && accept_partial_keystroke.display_modifiers.modified());
+                || (accept_partial_keystroke.modifiers() == modifiers
+                    && accept_partial_keystroke.modifiers().modified());
         }
 
         if modifiers_held {
@@ -9044,7 +9044,7 @@ impl Editor {
 
         let is_platform_style_mac = PlatformStyle::platform() == PlatformStyle::Mac;
 
-        let modifiers_color = if accept_keystroke.display_modifiers == window.modifiers() {
+        let modifiers_color = if *accept_keystroke.modifiers() == window.modifiers() {
             Color::Accent
         } else {
             Color::Muted
@@ -9056,19 +9056,19 @@ impl Editor {
             .font(theme::ThemeSettings::get_global(cx).buffer_font.clone())
             .text_size(TextSize::XSmall.rems(cx))
             .child(h_flex().children(ui::render_modifiers(
-                &accept_keystroke.display_modifiers,
+                accept_keystroke.modifiers(),
                 PlatformStyle::platform(),
                 Some(modifiers_color),
                 Some(IconSize::XSmall.rems().into()),
                 true,
             )))
             .when(is_platform_style_mac, |parent| {
-                parent.child(accept_keystroke.display_key.clone())
+                parent.child(accept_keystroke.key().to_string())
             })
             .when(!is_platform_style_mac, |parent| {
                 parent.child(
                     Key::new(
-                        util::capitalize(&accept_keystroke.display_key),
+                        util::capitalize(accept_keystroke.key()),
                         Some(Color::Default),
                     )
                     .size(Some(IconSize::XSmall.rems().into())),
@@ -9249,7 +9249,7 @@ impl Editor {
                                         accept_keystroke.as_ref(),
                                         |el, accept_keystroke| {
                                             el.child(h_flex().children(ui::render_modifiers(
-                                                &accept_keystroke.display_modifiers,
+                                                accept_keystroke.modifiers(),
                                                 PlatformStyle::platform(),
                                                 Some(Color::Default),
                                                 Some(IconSize::XSmall.rems().into()),
@@ -9319,7 +9319,7 @@ impl Editor {
                         .child(completion),
                 )
                 .when_some(accept_keystroke, |el, accept_keystroke| {
-                    if !accept_keystroke.display_modifiers.modified() {
+                    if !accept_keystroke.modifiers().modified() {
                         return el;
                     }
 
@@ -9338,7 +9338,7 @@ impl Editor {
                                     .font(theme::ThemeSettings::get_global(cx).buffer_font.clone())
                                     .when(is_platform_style_mac, |parent| parent.gap_1())
                                     .child(h_flex().children(ui::render_modifiers(
-                                        &accept_keystroke.display_modifiers,
+                                        accept_keystroke.modifiers(),
                                         PlatformStyle::platform(),
                                         Some(if !has_completion {
                                             Color::Muted

crates/gpui/src/keymap.rs 🔗

@@ -638,7 +638,7 @@ mod tests {
         fn assert_bindings(keymap: &Keymap, action: &dyn Action, expected: &[&str]) {
             let actual = keymap
                 .bindings_for_action(action)
-                .map(|binding| binding.keystrokes[0].inner.unparse())
+                .map(|binding| binding.keystrokes[0].inner().unparse())
                 .collect::<Vec<_>>();
             assert_eq!(actual, expected, "{:?}", action);
         }

crates/gpui/src/keymap/binding.rs 🔗

@@ -57,7 +57,7 @@ impl KeyBinding {
             .split_whitespace()
             .map(|source| {
                 let keystroke = Keystroke::parse(source)?;
-                Ok(KeybindingKeystroke::new(
+                Ok(KeybindingKeystroke::new_with_mapper(
                     keystroke,
                     use_key_equivalents,
                     keyboard_mapper,

crates/gpui/src/platform/keystroke.rs 🔗

@@ -36,11 +36,13 @@ pub struct Keystroke {
 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
 pub struct KeybindingKeystroke {
     /// The GPUI representation of the keystroke.
-    pub inner: Keystroke,
+    inner: Keystroke,
     /// The modifiers to display.
-    pub display_modifiers: Modifiers,
+    #[cfg(target_os = "windows")]
+    display_modifiers: Modifiers,
     /// The key to display.
-    pub display_key: String,
+    #[cfg(target_os = "windows")]
+    display_key: String,
 }
 
 /// Error type for `Keystroke::parse`. This is used instead of `anyhow::Error` so that Zed can use
@@ -262,8 +264,17 @@ impl Keystroke {
 }
 
 impl KeybindingKeystroke {
-    /// Create a new keybinding keystroke from the given keystroke
-    pub fn new(
+    #[cfg(target_os = "windows")]
+    pub(crate) fn new(inner: Keystroke, display_modifiers: Modifiers, display_key: String) -> Self {
+        KeybindingKeystroke {
+            inner,
+            display_modifiers,
+            display_key,
+        }
+    }
+
+    /// Create a new keybinding keystroke from the given keystroke using the given keyboard mapper.
+    pub fn new_with_mapper(
         inner: Keystroke,
         use_key_equivalents: bool,
         keyboard_mapper: &dyn PlatformKeyboardMapper,
@@ -271,19 +282,95 @@ impl KeybindingKeystroke {
         keyboard_mapper.map_key_equivalent(inner, use_key_equivalents)
     }
 
-    pub(crate) fn from_keystroke(keystroke: Keystroke) -> Self {
-        let key = keystroke.key.clone();
-        let modifiers = keystroke.modifiers;
-        KeybindingKeystroke {
-            inner: keystroke,
-            display_modifiers: modifiers,
-            display_key: key,
+    /// Create a new keybinding keystroke from the given keystroke, without any platform-specific mapping.
+    pub fn from_keystroke(keystroke: Keystroke) -> Self {
+        #[cfg(target_os = "windows")]
+        {
+            let key = keystroke.key.clone();
+            let modifiers = keystroke.modifiers;
+            KeybindingKeystroke {
+                inner: keystroke,
+                display_modifiers: modifiers,
+                display_key: key,
+            }
+        }
+        #[cfg(not(target_os = "windows"))]
+        {
+            KeybindingKeystroke { inner: keystroke }
+        }
+    }
+
+    /// Returns the GPUI representation of the keystroke.
+    pub fn inner(&self) -> &Keystroke {
+        &self.inner
+    }
+
+    /// Returns the modifiers.
+    ///
+    /// Platform-specific behavior:
+    /// - On macOS and Linux, this modifiers is the same as `inner.modifiers`, which is the GPUI representation of the keystroke.
+    /// - On Windows, this modifiers is the display modifiers, for example, a `ctrl-@` keystroke will have `inner.modifiers` as
+    /// `Modifiers::control()` and `display_modifiers` as `Modifiers::control_shift()`.
+    pub fn modifiers(&self) -> &Modifiers {
+        #[cfg(target_os = "windows")]
+        {
+            &self.display_modifiers
+        }
+        #[cfg(not(target_os = "windows"))]
+        {
+            &self.inner.modifiers
         }
     }
 
+    /// Returns the key.
+    ///
+    /// Platform-specific behavior:
+    /// - On macOS and Linux, this key is the same as `inner.key`, which is the GPUI representation of the keystroke.
+    /// - On Windows, this key is the display key, for example, a `ctrl-@` keystroke will have `inner.key` as `@` and `display_key` as `2`.
+    pub fn key(&self) -> &str {
+        #[cfg(target_os = "windows")]
+        {
+            &self.display_key
+        }
+        #[cfg(not(target_os = "windows"))]
+        {
+            &self.inner.key
+        }
+    }
+
+    /// Sets the modifiers. On Windows this modifies both `inner.modifiers` and `display_modifiers`.
+    pub fn set_modifiers(&mut self, modifiers: Modifiers) {
+        self.inner.modifiers = modifiers;
+        #[cfg(target_os = "windows")]
+        {
+            self.display_modifiers = modifiers;
+        }
+    }
+
+    /// Sets the key. On Windows this modifies both `inner.key` and `display_key`.
+    pub fn set_key(&mut self, key: String) {
+        #[cfg(target_os = "windows")]
+        {
+            self.display_key = key.clone();
+        }
+        self.inner.key = key;
+    }
+
     /// Produces a representation of this key that Parse can understand.
     pub fn unparse(&self) -> String {
-        unparse(&self.display_modifiers, &self.display_key)
+        #[cfg(target_os = "windows")]
+        {
+            unparse(&self.display_modifiers, &self.display_key)
+        }
+        #[cfg(not(target_os = "windows"))]
+        {
+            unparse(&self.inner.modifiers, &self.inner.key)
+        }
+    }
+
+    /// Removes the key_char
+    pub fn remove_key_char(&mut self) {
+        self.inner.key_char = None;
     }
 }
 
@@ -350,8 +437,8 @@ impl std::fmt::Display for Keystroke {
 
 impl std::fmt::Display for KeybindingKeystroke {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        display_modifiers(&self.display_modifiers, f)?;
-        display_key(&self.display_key, f)
+        display_modifiers(self.modifiers(), f)?;
+        display_key(self.key(), f)
     }
 }
 

crates/gpui/src/platform/mac/platform.rs 🔗

@@ -354,19 +354,19 @@ impl MacPlatform {
                             let mut mask = NSEventModifierFlags::empty();
                             for (modifier, flag) in &[
                                 (
-                                    keystroke.display_modifiers.platform,
+                                    keystroke.modifiers().platform,
                                     NSEventModifierFlags::NSCommandKeyMask,
                                 ),
                                 (
-                                    keystroke.display_modifiers.control,
+                                    keystroke.modifiers().control,
                                     NSEventModifierFlags::NSControlKeyMask,
                                 ),
                                 (
-                                    keystroke.display_modifiers.alt,
+                                    keystroke.modifiers().alt,
                                     NSEventModifierFlags::NSAlternateKeyMask,
                                 ),
                                 (
-                                    keystroke.display_modifiers.shift,
+                                    keystroke.modifiers().shift,
                                     NSEventModifierFlags::NSShiftKeyMask,
                                 ),
                             ] {
@@ -379,7 +379,7 @@ impl MacPlatform {
                                 .initWithTitle_action_keyEquivalent_(
                                     ns_string(name),
                                     selector,
-                                    ns_string(key_to_native(&keystroke.display_key).as_ref()),
+                                    ns_string(key_to_native(keystroke.key()).as_ref()),
                                 )
                                 .autorelease();
                             if Self::os_version() >= SemanticVersion::new(12, 0, 0) {

crates/gpui/src/platform/windows/keyboard.rs 🔗

@@ -83,11 +83,7 @@ impl PlatformKeyboardMapper for WindowsKeyboardMapper {
             ..keystroke.modifiers
         };
 
-        KeybindingKeystroke {
-            inner: keystroke,
-            display_modifiers: modifiers,
-            display_key: key,
-        }
+        KeybindingKeystroke::new(keystroke, modifiers, key)
     }
 
     fn get_key_equivalents(&self) -> Option<&HashMap<char, char>> {
@@ -335,9 +331,9 @@ mod tests {
             key_char: None,
         };
         let mapped = mapper.map_key_equivalent(keystroke.clone(), true);
-        assert_eq!(mapped.inner, keystroke);
-        assert_eq!(mapped.display_key, "a");
-        assert_eq!(mapped.display_modifiers, Modifiers::control());
+        assert_eq!(*mapped.inner(), keystroke);
+        assert_eq!(mapped.key(), "a");
+        assert_eq!(*mapped.modifiers(), Modifiers::control());
 
         // Shifted case, ctrl-$
         let keystroke = Keystroke {
@@ -346,9 +342,9 @@ mod tests {
             key_char: None,
         };
         let mapped = mapper.map_key_equivalent(keystroke.clone(), true);
-        assert_eq!(mapped.inner, keystroke);
-        assert_eq!(mapped.display_key, "4");
-        assert_eq!(mapped.display_modifiers, Modifiers::control_shift());
+        assert_eq!(*mapped.inner(), keystroke);
+        assert_eq!(mapped.key(), "4");
+        assert_eq!(*mapped.modifiers(), Modifiers::control_shift());
 
         // Shifted case, but shift is true
         let keystroke = Keystroke {
@@ -357,9 +353,9 @@ mod tests {
             key_char: None,
         };
         let mapped = mapper.map_key_equivalent(keystroke, true);
-        assert_eq!(mapped.inner.modifiers, Modifiers::control());
-        assert_eq!(mapped.display_key, "4");
-        assert_eq!(mapped.display_modifiers, Modifiers::control_shift());
+        assert_eq!(mapped.inner().modifiers, Modifiers::control());
+        assert_eq!(mapped.key(), "4");
+        assert_eq!(*mapped.modifiers(), Modifiers::control_shift());
 
         // Windows style
         let keystroke = Keystroke {
@@ -368,9 +364,9 @@ mod tests {
             key_char: None,
         };
         let mapped = mapper.map_key_equivalent(keystroke, true);
-        assert_eq!(mapped.inner.modifiers, Modifiers::control());
-        assert_eq!(mapped.inner.key, "$");
-        assert_eq!(mapped.display_key, "4");
-        assert_eq!(mapped.display_modifiers, Modifiers::control_shift());
+        assert_eq!(mapped.inner().modifiers, Modifiers::control());
+        assert_eq!(mapped.inner().key, "$");
+        assert_eq!(mapped.key(), "4");
+        assert_eq!(*mapped.modifiers(), Modifiers::control_shift());
     }
 }

crates/settings/src/keymap_file.rs 🔗

@@ -820,7 +820,11 @@ impl KeymapFile {
                         .split_whitespace()
                         .map(|source| {
                             let keystroke = Keystroke::parse(source)?;
-                            Ok(KeybindingKeystroke::new(keystroke, false, keyboard_mapper))
+                            Ok(KeybindingKeystroke::new_with_mapper(
+                                keystroke,
+                                false,
+                                keyboard_mapper,
+                            ))
                         })
                         .collect::<Result<Vec<_>, InvalidKeystrokeError>>()
                     else {
@@ -830,7 +834,7 @@ impl KeymapFile {
                         || !keystrokes
                             .iter()
                             .zip(target.keystrokes)
-                            .all(|(a, b)| a.inner.should_match(b))
+                            .all(|(a, b)| a.inner().should_match(b))
                     {
                         continue;
                     }
@@ -1065,7 +1069,7 @@ mod tests {
         keystrokes
             .split(' ')
             .map(|s| {
-                KeybindingKeystroke::new(
+                KeybindingKeystroke::new_with_mapper(
                     Keystroke::parse(s).expect("Keystrokes valid"),
                     false,
                     &DummyKeyboardMapper,

crates/settings_ui/src/keybindings.rs 🔗

@@ -14,9 +14,9 @@ use gpui::{
     Action, AppContext as _, AsyncApp, Axis, ClickEvent, Context, DismissEvent, Entity,
     EventEmitter, FocusHandle, Focusable, Global, IsZero,
     KeyBindingContextPredicate::{And, Descendant, Equal, Identifier, Not, NotEqual, Or},
-    KeyContext, KeybindingKeystroke, Keystroke, MouseButton, PlatformKeyboardMapper, Point,
-    ScrollStrategy, ScrollWheelEvent, Stateful, StyledText, Subscription, Task,
-    TextStyleRefinement, WeakEntity, actions, anchored, deferred, div,
+    KeyContext, KeybindingKeystroke, MouseButton, PlatformKeyboardMapper, Point, ScrollStrategy,
+    ScrollWheelEvent, Stateful, StyledText, Subscription, Task, TextStyleRefinement, WeakEntity,
+    actions, anchored, deferred, div,
 };
 use language::{Language, LanguageConfig, ToOffset as _};
 use notifications::status_toast::{StatusToast, ToastIcon};
@@ -420,7 +420,7 @@ fn keystrokes_match_exactly(
 ) -> bool {
     keystrokes1.len() == keystrokes2.len()
         && keystrokes1.iter().zip(keystrokes2).all(|(k1, k2)| {
-            k1.inner.key == k2.inner.key && k1.inner.modifiers == k2.inner.modifiers
+            k1.inner().key == k2.inner().key && k1.inner().modifiers == k2.inner().modifiers
         })
 }
 
@@ -532,7 +532,7 @@ impl KeymapEditor {
 
                 let keystroke_query = keystroke_query
                     .into_iter()
-                    .map(|keystroke| keystroke.inner.unparse())
+                    .map(|keystroke| keystroke.inner().unparse())
                     .collect::<Vec<String>>()
                     .join(" ");
 
@@ -606,13 +606,13 @@ impl KeymapEditor {
                                             let query = &keystroke_query[query_cursor];
                                             let keystroke = &keystrokes[keystroke_cursor];
                                             let matches = query
-                                                .inner
+                                                .inner()
                                                 .modifiers
-                                                .is_subset_of(&keystroke.inner.modifiers)
-                                                && ((query.inner.key.is_empty()
-                                                    || query.inner.key == keystroke.inner.key)
-                                                    && query.inner.key_char.as_ref().is_none_or(
-                                                        |q_kc| q_kc == &keystroke.inner.key,
+                                                .is_subset_of(&keystroke.inner().modifiers)
+                                                && ((query.inner().key.is_empty()
+                                                    || query.inner().key == keystroke.inner().key)
+                                                    && query.inner().key_char.as_ref().is_none_or(
+                                                        |q_kc| q_kc == &keystroke.inner().key,
                                                     ));
                                             if matches {
                                                 found_count += 1;
@@ -2256,12 +2256,10 @@ impl KeybindingEditorModal {
         let fs = self.fs.clone();
         let tab_size = cx.global::<settings::SettingsStore>().json_tab_size();
 
-        let new_keystrokes = self
-            .validate_keystrokes(cx)
-            .map_err(InputError::error)?
-            .into_iter()
-            .map(remove_key_char)
-            .collect::<Vec<_>>();
+        let mut new_keystrokes = self.validate_keystrokes(cx).map_err(InputError::error)?;
+        new_keystrokes
+            .iter_mut()
+            .for_each(|ks| ks.remove_key_char());
 
         let new_context = self.validate_context(cx).map_err(InputError::error)?;
         let new_action_args = self
@@ -2454,24 +2452,6 @@ impl KeybindingEditorModal {
     }
 }
 
-fn remove_key_char(
-    KeybindingKeystroke {
-        inner,
-        display_modifiers,
-        display_key,
-    }: KeybindingKeystroke,
-) -> KeybindingKeystroke {
-    KeybindingKeystroke {
-        inner: Keystroke {
-            modifiers: inner.modifiers,
-            key: inner.key,
-            key_char: None,
-        },
-        display_modifiers,
-        display_key,
-    }
-}
-
 impl Render for KeybindingEditorModal {
     fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
         let theme = cx.theme().colors();

crates/settings_ui/src/ui_components/keystroke_input.rs 🔗

@@ -116,7 +116,7 @@ impl KeystrokeInput {
             && self
                 .keystrokes
                 .last()
-                .is_some_and(|last| last.display_key.is_empty())
+                .is_some_and(|last| last.key().is_empty())
         {
             return &self.keystrokes[..self.keystrokes.len() - 1];
         }
@@ -124,15 +124,11 @@ impl KeystrokeInput {
     }
 
     fn dummy(modifiers: Modifiers) -> KeybindingKeystroke {
-        KeybindingKeystroke {
-            inner: Keystroke {
-                modifiers,
-                key: "".to_string(),
-                key_char: None,
-            },
-            display_modifiers: modifiers,
-            display_key: "".to_string(),
-        }
+        KeybindingKeystroke::from_keystroke(Keystroke {
+            modifiers,
+            key: "".to_string(),
+            key_char: None,
+        })
     }
 
     fn keystrokes_changed(&self, cx: &mut Context<Self>) {
@@ -258,7 +254,7 @@ impl KeystrokeInput {
         self.keystrokes_changed(cx);
 
         if let Some(last) = self.keystrokes.last_mut()
-            && last.display_key.is_empty()
+            && last.key().is_empty()
             && keystrokes_len <= Self::KEYSTROKE_COUNT_MAX
         {
             if !self.search && !event.modifiers.modified() {
@@ -267,15 +263,14 @@ impl KeystrokeInput {
             }
             if self.search {
                 if self.previous_modifiers.modified() {
-                    last.display_modifiers |= event.modifiers;
-                    last.inner.modifiers |= event.modifiers;
+                    let modifiers = *last.modifiers() | event.modifiers;
+                    last.set_modifiers(modifiers);
                 } else {
                     self.keystrokes.push(Self::dummy(event.modifiers));
                 }
                 self.previous_modifiers |= event.modifiers;
             } else {
-                last.display_modifiers = event.modifiers;
-                last.inner.modifiers = event.modifiers;
+                last.set_modifiers(event.modifiers);
                 return;
             }
         } else if keystrokes_len < Self::KEYSTROKE_COUNT_MAX {
@@ -303,10 +298,13 @@ impl KeystrokeInput {
             return;
         }
 
-        let keystroke =
-            KeybindingKeystroke::new(keystroke.clone(), false, cx.keyboard_mapper().as_ref());
+        let keystroke = KeybindingKeystroke::new_with_mapper(
+            keystroke.clone(),
+            false,
+            cx.keyboard_mapper().as_ref(),
+        );
         if let Some(last) = self.keystrokes.last()
-            && last.display_key.is_empty()
+            && last.key().is_empty()
             && (!self.search || self.previous_modifiers.modified())
         {
             self.keystrokes.pop();
@@ -825,7 +823,7 @@ mod tests {
                 input
                     .keystrokes
                     .iter()
-                    .map(|keystroke| keystroke.inner.clone())
+                    .map(|keystroke| keystroke.inner().clone())
                     .collect()
             });
             Self::expect_keystrokes_equal(&actual, expected);
@@ -1094,7 +1092,7 @@ mod tests {
             }
 
             fn keystrokes_str(ks: &[KeybindingKeystroke]) -> String {
-                ks.iter().map(|ks| ks.inner.unparse()).join(" ")
+                ks.iter().map(|ks| ks.inner().unparse()).join(" ")
             }
         }
     }

crates/ui/src/components/keybinding.rs 🔗

@@ -124,7 +124,7 @@ impl RenderOnce for KeyBinding {
                     "KEY_BINDING-{}",
                     self.keystrokes
                         .iter()
-                        .map(|k| k.display_key.to_string())
+                        .map(|k| k.key().to_string())
                         .collect::<Vec<_>>()
                         .join(" ")
                 )
@@ -165,8 +165,8 @@ pub fn render_keybinding_keystroke(
     if use_text {
         let element = Key::new(
             keystroke_text(
-                &keystroke.display_modifiers,
-                &keystroke.display_key,
+                keystroke.modifiers(),
+                keystroke.key(),
                 platform_style,
                 vim_mode,
             ),
@@ -178,18 +178,13 @@ pub fn render_keybinding_keystroke(
     } else {
         let mut elements = Vec::new();
         elements.extend(render_modifiers(
-            &keystroke.display_modifiers,
+            keystroke.modifiers(),
             platform_style,
             color,
             size,
             true,
         ));
-        elements.push(render_key(
-            &keystroke.display_key,
-            color,
-            platform_style,
-            size,
-        ));
+        elements.push(render_key(keystroke.key(), color, platform_style, size));
         elements
     }
 }
@@ -418,8 +413,8 @@ pub fn text_for_keybinding_keystrokes(keystrokes: &[KeybindingKeystroke], cx: &A
         .iter()
         .map(|keystroke| {
             keystroke_text(
-                &keystroke.display_modifiers,
-                &keystroke.display_key,
+                keystroke.modifiers(),
+                keystroke.key(),
                 platform_style,
                 vim_enabled,
             )

crates/zed/src/zed.rs 🔗

@@ -4738,7 +4738,7 @@ mod tests {
                 // and key strokes contain the given key
                 bindings
                     .into_iter()
-                    .any(|binding| binding.keystrokes().iter().any(|k| k.display_key == key)),
+                    .any(|binding| binding.keystrokes().iter().any(|k| k.key() == key)),
                 "On {} Failed to find {} with key binding {}",
                 line,
                 action.name(),