From 54f1fab649bd77cb7b03f8554bc47874c69de322 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Mon, 17 Feb 2025 09:17:22 -0800 Subject: [PATCH] Use lowercase for vim key bindings (#25024) Vim itself shows keybindings cased according to the character, and so it's confusing for people coming from vim that we show all key-bindings uppercase with an icon denoting shift (c.f. #14287). So, in #24322 we changed Zed to use lowercase for bindings in vim mode. Unfortunately this (in practice) looks awful because our key icons are designed to be paired with uppercase letters. Instead, we now (for vim mode) show the same syntax as would be used in the keymap file for Zed. This is different from vim (i.e. we show shift-z instead of Z, and cmd-d instead of ) but hopefully avoids the original confusion, and as a bonus makes it easy to figure out the syntax you need for a workspace::SendKeystrokes. Closes #ISSUE Release Notes: - N/A *or* Added/Fixed/Improved ... --- crates/ui/src/components/keybinding.rs | 128 ++++++++++++------------- 1 file changed, 63 insertions(+), 65 deletions(-) diff --git a/crates/ui/src/components/keybinding.rs b/crates/ui/src/components/keybinding.rs index 3682afa972..136cf9a6de 100644 --- a/crates/ui/src/components/keybinding.rs +++ b/crates/ui/src/components/keybinding.rs @@ -92,15 +92,7 @@ impl KeyBinding { match key_icon { Some(icon) => KeyIcon::new(icon, color).size(self.size).into_any_element(), None => { - let key = if self.vim_mode { - if keystroke.modifiers.shift && keystroke.key.len() == 1 { - keystroke.key.to_ascii_uppercase().to_string() - } else { - keystroke.key.to_string() - } - } else { - util::capitalize(&keystroke.key) - }; + let key = util::capitalize(&keystroke.key); Key::new(&key, color).size(self.size).into_any_element() } } @@ -129,14 +121,25 @@ impl RenderOnce for KeyBinding { .py_0p5() .rounded_sm() .text_color(cx.theme().colors().text_muted) - .children(render_modifiers( - &keystroke.modifiers, - self.platform_style, - None, - self.size, - true, - )) - .map(|el| el.child(self.render_key(&keystroke, None))) + .when(self.vim_mode, |el| { + el.child( + Key::new( + keystroke_text(&keystroke, self.platform_style, self.vim_mode), + None, + ) + .size(self.size), + ) + }) + .when(!self.vim_mode, |el| { + el.children(render_modifiers( + &keystroke.modifiers, + self.platform_style, + None, + self.size, + true, + )) + .map(|el| el.child(self.render_key(&keystroke, None))) + }) })) } } @@ -359,80 +362,75 @@ pub fn text_for_keystroke(keystroke: &Keystroke, cx: &App) -> String { } /// Returns a textual representation of the given [`Keystroke`]. -fn keystroke_text( - keystroke: &Keystroke, - platform_style: PlatformStyle, - vim_enabled: bool, -) -> String { +fn keystroke_text(keystroke: &Keystroke, platform_style: PlatformStyle, vim_mode: bool) -> String { let mut text = String::new(); - let delimiter = match platform_style { - PlatformStyle::Mac => '-', - PlatformStyle::Linux | PlatformStyle::Windows => '+', + let delimiter = match (platform_style, vim_mode) { + (PlatformStyle::Mac, false) => '-', + (PlatformStyle::Linux | PlatformStyle::Windows, false) => '+', + (_, true) => '-', }; if keystroke.modifiers.function { - match platform_style { - PlatformStyle::Mac => text.push_str("Fn"), - PlatformStyle::Linux | PlatformStyle::Windows => text.push_str("Fn"), + match vim_mode { + false => text.push_str("Fn"), + true => text.push_str("fn"), } text.push(delimiter); } if keystroke.modifiers.control { - match platform_style { - PlatformStyle::Mac => text.push_str("Control"), - PlatformStyle::Linux | PlatformStyle::Windows => text.push_str("Ctrl"), - } - - text.push(delimiter); - } - - if keystroke.modifiers.alt { - match platform_style { - PlatformStyle::Mac => text.push_str("Option"), - PlatformStyle::Linux | PlatformStyle::Windows => text.push_str("Alt"), + match (platform_style, vim_mode) { + (PlatformStyle::Mac, false) => text.push_str("Control"), + (PlatformStyle::Linux | PlatformStyle::Windows, false) => text.push_str("Ctrl"), + (_, true) => text.push_str("ctrl"), } text.push(delimiter); } if keystroke.modifiers.platform { - match platform_style { - PlatformStyle::Mac => text.push_str("Command"), - PlatformStyle::Linux => text.push_str("Super"), - PlatformStyle::Windows => text.push_str("Win"), + match (platform_style, vim_mode) { + (PlatformStyle::Mac, false) => text.push_str("Command"), + (PlatformStyle::Mac, true) => text.push_str("cmd"), + (PlatformStyle::Linux, false) => text.push_str("Super"), + (PlatformStyle::Linux, true) => text.push_str("super"), + (PlatformStyle::Windows, false) => text.push_str("Win"), + (PlatformStyle::Windows, true) => text.push_str("win"), + } + + text.push(delimiter); + } + + if keystroke.modifiers.alt { + match (platform_style, vim_mode) { + (PlatformStyle::Mac, false) => text.push_str("Option"), + (PlatformStyle::Linux | PlatformStyle::Windows, false) => text.push_str("Alt"), + (_, true) => text.push_str("alt"), } text.push(delimiter); } if keystroke.modifiers.shift { - if !(vim_enabled && keystroke.key.len() == 1) { - match platform_style { - PlatformStyle::Mac | PlatformStyle::Linux | PlatformStyle::Windows => { - text.push_str("Shift") - } - } - text.push(delimiter); + match (platform_style, vim_mode) { + (_, false) => text.push_str("Shift"), + (_, true) => text.push_str("shift"), } + text.push(delimiter); } - let key = match keystroke.key.as_str() { - "pageup" => "PageUp", - "pagedown" => "PageDown", - key if vim_enabled => { - if !keystroke.modifiers.shift && key.len() == 1 { - key - } else { - &util::capitalize(key) - } - } - key => &util::capitalize(key), - }; - - text.push_str(key); + if vim_mode { + text.push_str(&keystroke.key) + } else { + let key = match keystroke.key.as_str() { + "pageup" => "PageUp", + "pagedown" => "PageDown", + key => &util::capitalize(key), + }; + text.push_str(key); + } text }