From 08e9080ec97a99d7641ceb09ef5b4e39a770e650 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 }