Skip to content

Commit

Permalink
Display case-sensitive keybindings for vim commands (#24322)
Browse files Browse the repository at this point in the history
This Pull Request tackles the issue outline in #14287 by changing the
way `KeyBinding`s for vim mode are displayed in the command palette.
It's worth pointing out that this whole thing was pretty much
implemented by Conrad Irwin during a pairing session, I just tried to
clean up some other changes introduced for a different issue, while
improving some comments.

Here's a quick list of the changes introduced:

- Update `KeyBinding` with a new `vim_mode` field to determine whether
the keybinding should be displayed in vim mode.
- Update the way `KeyBinding` is rendered, so as to detect if the
keybinding is for vim mode, if it is, only display keys in uppercase if
they require the shift key.
- Introduce a new global state – `VimStyle(bool)` - use to determine
whether `vim_mode` should be enabled or disabled when creating a new
`KeyBinding` struct. This global state is automatically set by the `vim`
crate whenever vim mode is enabled or disabled.
- Since the app's context is now required when building a `KeyBinding` ,
update a lot of callers to correctly pass this context.

And before and after screenshots, for comparison:

| before | after |
|--------|-------|
| <img width="1050" alt="SCR-20250205-tyeq"
src="https://github.com/user-attachments/assets/e577206d-2a3d-4e06-a96f-a98899cc15c0"
/> | <img width="1050" alt="SCR-20250205-tylh"
src="https://github.com/user-attachments/assets/ebbf70a9-e838-4d32-aee5-0ffde94d65fb"
/> |

Closes #14287 

Release Notes:

- Fix rendering of vim commands to preserve case sensitivity

---------

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
  • Loading branch information
dinocosta and ConradIrwin authored Feb 15, 2025
1 parent 14289b5 commit e0fc767
Show file tree
Hide file tree
Showing 30 changed files with 236 additions and 165 deletions.
4 changes: 2 additions & 2 deletions assets/keymaps/vim.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@
"[ [": "vim::PreviousSectionStart",
"[ ]": "vim::PreviousSectionEnd",
"] m": "vim::NextMethodStart",
"] M": "vim::NextMethodEnd",
"] shift-m": "vim::NextMethodEnd",
"[ m": "vim::PreviousMethodStart",
"[ M": "vim::PreviousMethodEnd",
"[ shift-m": "vim::PreviousMethodEnd",
"[ *": "vim::PreviousComment",
"[ /": "vim::PreviousComment",
"] *": "vim::NextComment",
Expand Down
17 changes: 11 additions & 6 deletions crates/assistant/src/inline_assistant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1704,7 +1704,7 @@ impl PromptEditor {
// always show the cursor (even when it isn't focused) because
// typing in one will make what you typed appear in all of them.
editor.set_show_cursor_when_unfocused(true, cx);
editor.set_placeholder_text(Self::placeholder_text(codegen.read(cx), window), cx);
editor.set_placeholder_text(Self::placeholder_text(codegen.read(cx), window, cx), cx);
editor
});

Expand Down Expand Up @@ -1783,7 +1783,10 @@ impl PromptEditor {
self.editor = cx.new(|cx| {
let mut editor = Editor::auto_height(Self::MAX_LINES as usize, window, cx);
editor.set_soft_wrap_mode(language::language_settings::SoftWrap::EditorWidth, cx);
editor.set_placeholder_text(Self::placeholder_text(self.codegen.read(cx), window), cx);
editor.set_placeholder_text(
Self::placeholder_text(self.codegen.read(cx), window, cx),
cx,
);
editor.set_placeholder_text("Add a prompt…", cx);
editor.set_text(prompt, window, cx);
if focus {
Expand All @@ -1794,8 +1797,8 @@ impl PromptEditor {
self.subscribe_to_editor(window, cx);
}

fn placeholder_text(codegen: &Codegen, window: &Window) -> String {
let context_keybinding = text_for_action(&zed_actions::assistant::ToggleFocus, window)
fn placeholder_text(codegen: &Codegen, window: &Window, cx: &App) -> String {
let context_keybinding = text_for_action(&zed_actions::assistant::ToggleFocus, window, cx)
.map(|keybinding| format!(" • {keybinding} for context"))
.unwrap_or_default();

Expand Down Expand Up @@ -2084,12 +2087,13 @@ impl PromptEditor {
.tooltip({
let focus_handle = self.editor.focus_handle(cx);
move |window, cx| {
cx.new(|_| {
cx.new(|cx| {
let mut tooltip = Tooltip::new("Previous Alternative").key_binding(
KeyBinding::for_action_in(
&CyclePreviousInlineAssist,
&focus_handle,
window,
cx,
),
);
if !disabled && current_index != 0 {
Expand Down Expand Up @@ -2126,12 +2130,13 @@ impl PromptEditor {
.tooltip({
let focus_handle = self.editor.focus_handle(cx);
move |window, cx| {
cx.new(|_| {
cx.new(|cx| {
let mut tooltip = Tooltip::new("Next Alternative").key_binding(
KeyBinding::for_action_in(
&CycleNextInlineAssist,
&focus_handle,
window,
cx,
),
);
if !disabled && current_index != total_models - 1 {
Expand Down
6 changes: 3 additions & 3 deletions crates/assistant/src/terminal_inline_assistant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -725,7 +725,7 @@ impl PromptEditor {
cx,
);
editor.set_soft_wrap_mode(language::language_settings::SoftWrap::EditorWidth, cx);
editor.set_placeholder_text(Self::placeholder_text(window), cx);
editor.set_placeholder_text(Self::placeholder_text(window, cx), cx);
editor
});

Expand Down Expand Up @@ -774,8 +774,8 @@ impl PromptEditor {
this
}

fn placeholder_text(window: &Window) -> String {
let context_keybinding = text_for_action(&zed_actions::assistant::ToggleFocus, window)
fn placeholder_text(window: &Window, cx: &App) -> String {
let context_keybinding = text_for_action(&zed_actions::assistant::ToggleFocus, window, cx)
.map(|keybinding| format!(" • {keybinding} for context"))
.unwrap_or_default();

Expand Down
1 change: 1 addition & 0 deletions crates/assistant2/src/assistant_panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,7 @@ impl AssistantPanel {
&OpenHistory,
&self.focus_handle(cx),
window,
cx
))
.on_click(move |_event, window, cx| {
window.dispatch_action(OpenHistory.boxed_clone(), cx);
Expand Down
1 change: 1 addition & 0 deletions crates/assistant2/src/context_strip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,7 @@ impl Render for ContextStrip {
&ToggleContextPicker,
&focus_handle,
window,
cx,
)
.map(|binding| binding.into_any_element()),
),
Expand Down
8 changes: 5 additions & 3 deletions crates/assistant2/src/inline_prompt_editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ impl<T: 'static> PromptEditor<T> {
};

let assistant_panel_keybinding =
ui::text_for_action(&zed_actions::assistant::ToggleFocus, window)
ui::text_for_action(&zed_actions::assistant::ToggleFocus, window, cx)
.map(|keybinding| format!("{keybinding} to chat ― "))
.unwrap_or_default();

Expand Down Expand Up @@ -618,12 +618,13 @@ impl<T: 'static> PromptEditor<T> {
.tooltip({
let focus_handle = self.editor.focus_handle(cx);
move |window, cx| {
cx.new(|_| {
cx.new(|cx| {
let mut tooltip = Tooltip::new("Previous Alternative").key_binding(
KeyBinding::for_action_in(
&CyclePreviousInlineAssist,
&focus_handle,
window,
cx,
),
);
if !disabled && current_index != 0 {
Expand Down Expand Up @@ -659,12 +660,13 @@ impl<T: 'static> PromptEditor<T> {
.tooltip({
let focus_handle = self.editor.focus_handle(cx);
move |window, cx| {
cx.new(|_| {
cx.new(|cx| {
let mut tooltip = Tooltip::new("Next Alternative").key_binding(
KeyBinding::for_action_in(
&CycleNextInlineAssist,
&focus_handle,
window,
cx,
),
);
if !disabled && current_index != total_models - 1 {
Expand Down
3 changes: 3 additions & 0 deletions crates/assistant2/src/message_editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,7 @@ impl Render for MessageEditor {
&ChatMode,
&focus_handle,
window,
cx,
)),
)
.child(h_flex().gap_1().child(self.model_selector.clone()).child(
Expand Down Expand Up @@ -419,6 +420,7 @@ impl Render for MessageEditor {
&editor::actions::Cancel,
&focus_handle,
window,
cx,
)
.map(|binding| binding.into_any_element()),
),
Expand Down Expand Up @@ -449,6 +451,7 @@ impl Render for MessageEditor {
&Chat,
&focus_handle,
window,
cx,
)
.map(|binding| binding.into_any_element()),
),
Expand Down
4 changes: 2 additions & 2 deletions crates/assistant_context_editor/src/context_editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2290,7 +2290,7 @@ impl ContextEditor {
},
))
.children(
KeyBinding::for_action_in(&Assist, &focus_handle, window)
KeyBinding::for_action_in(&Assist, &focus_handle, window, cx)
.map(|binding| binding.into_any_element()),
)
.on_click(move |_event, window, cx| {
Expand Down Expand Up @@ -2343,7 +2343,7 @@ impl ContextEditor {
.layer(ElevationIndex::ModalSurface)
.child(Label::new("Suggest Edits"))
.children(
KeyBinding::for_action_in(&Edit, &focus_handle, window)
KeyBinding::for_action_in(&Edit, &focus_handle, window, cx)
.map(|binding| binding.into_any_element()),
)
.on_click(move |_event, window, cx| {
Expand Down
1 change: 1 addition & 0 deletions crates/collab_ui/src/chat_panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -992,6 +992,7 @@ impl Render for ChatPanel {
.key_binding(KeyBinding::for_action(
&collab_panel::ToggleFocus,
window,
cx,
))
.on_click(|_, window, cx| {
window.dispatch_action(
Expand Down
3 changes: 2 additions & 1 deletion crates/command_palette/src/command_palette.rs
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ impl PickerDelegate for CommandPaletteDelegate {
ix: usize,
selected: bool,
window: &mut Window,
_: &mut Context<Picker<Self>>,
cx: &mut Context<Picker<Self>>,
) -> Option<Self::ListItem> {
let r#match = self.matches.get(ix)?;
let command = self.commands.get(r#match.candidate_id)?;
Expand All @@ -424,6 +424,7 @@ impl PickerDelegate for CommandPaletteDelegate {
&*command.action,
&self.previous_focus_handle,
window,
cx,
)),
),
)
Expand Down
1 change: 1 addition & 0 deletions crates/editor/src/element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2731,6 +2731,7 @@ impl EditorElement {
&OpenExcerpts,
&focus_handle,
window,
cx,
)
.map(|binding| binding.into_any_element()),
),
Expand Down
2 changes: 1 addition & 1 deletion crates/editor/src/proposed_changes_editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ impl Render for ProposedChangesEditorToolbar {
Some(editor) => {
let focus_handle = editor.focus_handle(cx);
let keybinding =
KeyBinding::for_action_in(&ApplyAllDiffHunks, &focus_handle, window)
KeyBinding::for_action_in(&ApplyAllDiffHunks, &focus_handle, window, cx)
.map(|binding| binding.into_any_element());

button_like.children(keybinding).on_click({
Expand Down
3 changes: 2 additions & 1 deletion crates/file_finder/src/file_finder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1317,7 +1317,7 @@ impl PickerDelegate for FileFinderDelegate {
.border_color(cx.theme().colors().border_variant)
.child(
Button::new("open-selection", "Open")
.key_binding(KeyBinding::for_action(&menu::Confirm, window))
.key_binding(KeyBinding::for_action(&menu::Confirm, window, cx))
.on_click(|_, window, cx| {
window.dispatch_action(menu::Confirm.boxed_clone(), cx)
}),
Expand All @@ -1334,6 +1334,7 @@ impl PickerDelegate for FileFinderDelegate {
&ToggleMenu,
&context,
window,
cx,
)),
)
.menu({
Expand Down
3 changes: 2 additions & 1 deletion crates/language_tools/src/key_context_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ impl Render for KeyContextView {
.key_binding(ui::KeyBinding::for_action(
&zed_actions::OpenDefaultKeymap,
window,
cx
))
.on_click(|_, window, cx| {
window.dispatch_action(workspace::SplitRight.boxed_clone(), cx);
Expand All @@ -225,7 +226,7 @@ impl Render for KeyContextView {
.child(
Button::new("default", "Edit your keymap")
.style(ButtonStyle::Filled)
.key_binding(ui::KeyBinding::for_action(&zed_actions::OpenKeymap, window))
.key_binding(ui::KeyBinding::for_action(&zed_actions::OpenKeymap, window, cx))
.on_click(|_, window, cx| {
window.dispatch_action(workspace::SplitRight.boxed_clone(), cx);
window.dispatch_action(zed_actions::OpenKeymap.boxed_clone(), cx);
Expand Down
2 changes: 1 addition & 1 deletion crates/project_panel/src/project_panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4643,7 +4643,7 @@ impl Render for ProjectPanel {
.child(
Button::new("open_project", "Open a project")
.full_width()
.key_binding(KeyBinding::for_action(&workspace::Open, window))
.key_binding(KeyBinding::for_action(&workspace::Open, window, cx))
.on_click(cx.listener(|this, _, window, cx| {
this.workspace
.update(cx, |_, cx| {
Expand Down
2 changes: 1 addition & 1 deletion crates/prompt_library/src/prompt_library.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1268,7 +1268,7 @@ impl Render for PromptLibrary {
Button::new("create-prompt", "New Prompt")
.full_width()
.key_binding(KeyBinding::for_action(
&NewPrompt, window,
&NewPrompt, window, cx,
))
.on_click(|_, window, cx| {
window.dispatch_action(
Expand Down
4 changes: 2 additions & 2 deletions crates/recent_projects/src/recent_projects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -465,14 +465,14 @@ impl PickerDelegate for RecentProjectsDelegate {
.border_color(cx.theme().colors().border_variant)
.child(
Button::new("remote", "Open Remote Folder")
.key_binding(KeyBinding::for_action(&OpenRemote, window))
.key_binding(KeyBinding::for_action(&OpenRemote, window, cx))
.on_click(|_, window, cx| {
window.dispatch_action(OpenRemote.boxed_clone(), cx)
}),
)
.child(
Button::new("local", "Open Local Folder")
.key_binding(KeyBinding::for_action(&workspace::Open, window))
.key_binding(KeyBinding::for_action(&workspace::Open, window, cx))
.on_click(|_, window, cx| {
window.dispatch_action(workspace::Open.boxed_clone(), cx)
}),
Expand Down
2 changes: 1 addition & 1 deletion crates/repl/src/repl_sessions_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ impl Render for ReplSessionsPage {
return ReplSessionsContainer::new("No Jupyter Kernel Sessions").child(
v_flex()
.child(Label::new(instructions))
.children(KeyBinding::for_action(&Run, window)),
.children(KeyBinding::for_action(&Run, window, cx)),
);
}

Expand Down
9 changes: 7 additions & 2 deletions crates/search/src/project_search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ impl Render for ProjectSearchView {
None
}
} else {
Some(self.landing_text_minor(window).into_any_element())
Some(self.landing_text_minor(window, cx).into_any_element())
};

let page_content = page_content.map(|text| div().child(text));
Expand Down Expand Up @@ -1231,7 +1231,7 @@ impl ProjectSearchView {
self.active_match_index.is_some()
}

fn landing_text_minor(&self, window: &mut Window) -> impl IntoElement {
fn landing_text_minor(&self, window: &mut Window, cx: &App) -> impl IntoElement {
let focus_handle = self.focus_handle.clone();
v_flex()
.gap_1()
Expand All @@ -1249,6 +1249,7 @@ impl ProjectSearchView {
&ToggleFilters,
&focus_handle,
window,
cx,
))
.on_click(|_event, window, cx| {
window.dispatch_action(ToggleFilters.boxed_clone(), cx)
Expand All @@ -1263,6 +1264,7 @@ impl ProjectSearchView {
&ToggleReplace,
&focus_handle,
window,
cx,
))
.on_click(|_event, window, cx| {
window.dispatch_action(ToggleReplace.boxed_clone(), cx)
Expand All @@ -1277,6 +1279,7 @@ impl ProjectSearchView {
&ToggleRegex,
&focus_handle,
window,
cx,
))
.on_click(|_event, window, cx| {
window.dispatch_action(ToggleRegex.boxed_clone(), cx)
Expand All @@ -1291,6 +1294,7 @@ impl ProjectSearchView {
&ToggleCaseSensitive,
&focus_handle,
window,
cx,
))
.on_click(|_event, window, cx| {
window.dispatch_action(ToggleCaseSensitive.boxed_clone(), cx)
Expand All @@ -1305,6 +1309,7 @@ impl ProjectSearchView {
&ToggleWholeWord,
&focus_handle,
window,
cx,
))
.on_click(|_event, window, cx| {
window.dispatch_action(ToggleWholeWord.boxed_clone(), cx)
Expand Down
Loading

0 comments on commit e0fc767

Please sign in to comment.