From b055f594b06bd0ad56dab64b24c5af613f538ddd Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Mon, 3 Jul 2023 12:50:17 -0600 Subject: [PATCH 1/3] vim: ctrl-c to exit visual mode Fixes: zed-industries/community#1447 Contributes: zed-industries/community#1089 --- assets/keymaps/vim.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/assets/keymaps/vim.json b/assets/keymaps/vim.json index afee6fcd2e..d019078834 100644 --- a/assets/keymaps/vim.json +++ b/assets/keymaps/vim.json @@ -305,6 +305,10 @@ "vim::PushOperator", "Replace" ], + "ctrl-c": [ + "vim::SwitchMode", + "Normal" + ], "> >": "editor::Indent", "< <": "editor::Outdent" } From fe57e04016c120eb83441b8722febed1f6b4984f Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Mon, 3 Jul 2023 12:55:41 -0600 Subject: [PATCH 2/3] vim: Allow ^ as a motion Fixes: zed-industries/community#856 --- assets/keymaps/vim.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/keymaps/vim.json b/assets/keymaps/vim.json index d019078834..86e5b51f19 100644 --- a/assets/keymaps/vim.json +++ b/assets/keymaps/vim.json @@ -35,6 +35,7 @@ "l": "vim::Right", "right": "vim::Right", "$": "vim::EndOfLine", + "^": "vim::FirstNonWhitespace", "shift-g": "vim::EndOfDocument", "w": "vim::NextWordStart", "shift-w": [ @@ -165,7 +166,6 @@ "shift-a": "vim::InsertEndOfLine", "x": "vim::DeleteRight", "shift-x": "vim::DeleteLeft", - "^": "vim::FirstNonWhitespace", "o": "vim::InsertLineBelow", "shift-o": "vim::InsertLineAbove", "~": "vim::ChangeCase", From 0733e8d50f0ffa3339cb03c14b661ca2f4334d9f Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Mon, 3 Jul 2023 15:20:10 -0600 Subject: [PATCH 3/3] Remove editor::Cancel binding from vim When you hit in the command palette, it first editor::Cancel because the command palette is also a focused editor; this binding was catching before the `menu::Cancel` that you probably want. From looking at the uses of editor::Cancel it seems like the only way to trigger this is with in an editor. Rather than trying to hook into the existing editor cancel and add vim-specific behaviour, we'll instead take responsibility for binding directly to when necessary. Fixes: zed-industries/community#1347 --- assets/keymaps/vim.json | 10 ++++++++-- crates/vim/src/test.rs | 14 ++++++++++++++ crates/vim/src/test/vim_test_context.rs | 2 ++ crates/vim/src/vim.rs | 23 ++--------------------- 4 files changed, 26 insertions(+), 23 deletions(-) diff --git a/assets/keymaps/vim.json b/assets/keymaps/vim.json index 86e5b51f19..e08ce47caf 100644 --- a/assets/keymaps/vim.json +++ b/assets/keymaps/vim.json @@ -93,7 +93,10 @@ ], "ctrl-o": "pane::GoBack", "ctrl-]": "editor::GoToDefinition", - "escape": "editor::Cancel", + "escape": [ + "vim::SwitchMode", + "Normal" + ], "0": "vim::StartOfLine", // When no number operator present, use start of line motion "1": [ "vim::Number", @@ -325,7 +328,10 @@ "bindings": { "tab": "vim::Tab", "enter": "vim::Enter", - "escape": "editor::Cancel" + "escape": [ + "vim::SwitchMode", + "Normal" + ] } } ] diff --git a/crates/vim/src/test.rs b/crates/vim/src/test.rs index b6c5b7ca51..a6efbd4da1 100644 --- a/crates/vim/src/test.rs +++ b/crates/vim/src/test.rs @@ -4,6 +4,7 @@ mod neovim_connection; mod vim_binding_test_context; mod vim_test_context; +use command_palette::CommandPalette; pub use neovim_backed_binding_test_context::*; pub use neovim_backed_test_context::*; pub use vim_binding_test_context::*; @@ -139,3 +140,16 @@ async fn test_indent_outdent(cx: &mut gpui::TestAppContext) { cx.simulate_keystrokes(["shift-v", "down", ">", ">"]); cx.assert_editor_state("aa\n b«b\n cˇ»c"); } + +#[gpui::test] +async fn test_escape_command_palette(cx: &mut gpui::TestAppContext) { + let mut cx = VimTestContext::new(cx, true).await; + + cx.set_state("aˇbc\n", Mode::Normal); + cx.simulate_keystrokes(["i", "cmd-shift-p"]); + + assert!(cx.workspace(|workspace, _| workspace.modal::().is_some())); + cx.simulate_keystroke("escape"); + assert!(!cx.workspace(|workspace, _| workspace.modal::().is_some())); + cx.assert_state("aˇbc\n", Mode::Insert); +} diff --git a/crates/vim/src/test/vim_test_context.rs b/crates/vim/src/test/vim_test_context.rs index 3e66d6bb1c..f9ba577231 100644 --- a/crates/vim/src/test/vim_test_context.rs +++ b/crates/vim/src/test/vim_test_context.rs @@ -21,12 +21,14 @@ impl<'a> VimTestContext<'a> { cx.update(|cx| { search::init(cx); crate::init(cx); + command_palette::init(cx); }); cx.update(|cx| { cx.update_global(|store: &mut SettingsStore, cx| { store.update_user_settings::(cx, |s| *s = Some(enabled)); }); + settings::KeymapFile::load_asset("keymaps/default.json", cx).unwrap(); settings::KeymapFile::load_asset("keymaps/vim.json", cx).unwrap(); }); diff --git a/crates/vim/src/vim.rs b/crates/vim/src/vim.rs index eae8643cf3..2bcc2254ee 100644 --- a/crates/vim/src/vim.rs +++ b/crates/vim/src/vim.rs @@ -12,7 +12,7 @@ mod visual; use anyhow::Result; use collections::CommandPaletteFilter; -use editor::{Bias, Cancel, Editor, EditorMode, Event}; +use editor::{Bias, Editor, EditorMode, Event}; use gpui::{ actions, impl_actions, AppContext, Subscription, ViewContext, ViewHandle, WeakViewHandle, WindowContext, @@ -64,22 +64,6 @@ pub fn init(cx: &mut AppContext) { Vim::update(cx, |vim, cx| vim.push_number(n, cx)); }); - // Editor Actions - cx.add_action(|_: &mut Editor, _: &Cancel, cx| { - // If we are in aren't in normal mode or have an active operator, swap to normal mode - // Otherwise forward cancel on to the editor - let vim = Vim::read(cx); - if vim.state.mode != Mode::Normal || vim.active_operator().is_some() { - WindowContext::defer(cx, |cx| { - Vim::update(cx, |state, cx| { - state.switch_mode(Mode::Normal, false, cx); - }); - }); - } else { - cx.propagate_action(); - } - }); - cx.add_action(|_: &mut Workspace, _: &Tab, cx| { Vim::active_editor_input_ignored(" ".into(), cx) }); @@ -109,10 +93,7 @@ pub fn observe_keystrokes(cx: &mut WindowContext) { cx.observe_keystrokes(|_keystroke, _result, handled_by, cx| { if let Some(handled_by) = handled_by { // Keystroke is handled by the vim system, so continue forward - // Also short circuit if it is the special cancel action - if handled_by.namespace() == "vim" - || (handled_by.namespace() == "editor" && handled_by.name() == "Cancel") - { + if handled_by.namespace() == "vim" { return true; } }