vim: Fix renaming (#7714)

Conrad Irwin created

This was broken by #7647

Release Notes:

- N/A

Change summary

crates/editor/src/editor.rs             | 11 +++++++
crates/feedback/src/feedback_modal.rs   |  1 
crates/vim/src/editor_events.rs         |  1 
crates/vim/src/test.rs                  | 37 ++++++++++++++++++++++++++
crates/vim/src/test/vim_test_context.rs | 33 +++++++++--------------
crates/vim/src/vim.rs                   |  9 ++++--
6 files changed, 68 insertions(+), 24 deletions(-)

Detailed changes

crates/editor/src/editor.rs 🔗

@@ -399,6 +399,7 @@ pub struct Editor {
     workspace: Option<(WeakView<Workspace>, i64)>,
     keymap_context_layers: BTreeMap<TypeId, KeyContext>,
     input_enabled: bool,
+    use_modal_editing: bool,
     read_only: bool,
     leader_peer_id: Option<PeerId>,
     remote_id: Option<ViewId>,
@@ -1482,6 +1483,7 @@ impl Editor {
             workspace: None,
             keymap_context_layers: Default::default(),
             input_enabled: true,
+            use_modal_editing: mode == EditorMode::Full,
             read_only: false,
             use_autoclose: true,
             leader_peer_id: None,
@@ -1782,6 +1784,14 @@ impl Editor {
         self.show_copilot_suggestions = show_copilot_suggestions;
     }
 
+    pub fn set_use_modal_editing(&mut self, to: bool) {
+        self.use_modal_editing = to;
+    }
+
+    pub fn use_modal_editing(&self) -> bool {
+        self.use_modal_editing
+    }
+
     fn selections_did_change(
         &mut self,
         local: bool,
@@ -7836,7 +7846,6 @@ impl Editor {
         Some(rename)
     }
 
-    #[cfg(any(test, feature = "test-support"))]
     pub fn pending_rename(&self) -> Option<&RenameState> {
         self.pending_rename.as_ref()
     }

crates/feedback/src/feedback_modal.rs 🔗

@@ -187,6 +187,7 @@ impl FeedbackModal {
             editor.set_show_gutter(false, cx);
             editor.set_show_copilot_suggestions(false);
             editor.set_vertical_scroll_margin(5, cx);
+            editor.set_use_modal_editing(false);
             editor
         });
 

crates/vim/src/editor_events.rs 🔗

@@ -47,6 +47,7 @@ fn blurred(editor: View<Editor>, cx: &mut WindowContext) {
                 .upgrade()
                 .is_some_and(|previous| previous == editor.clone())
             {
+                vim.sync_vim_settings(cx);
                 vim.clear_operator(cx);
             }
         }

crates/vim/src/test.rs 🔗

@@ -7,6 +7,7 @@ use std::time::Duration;
 
 use command_palette::CommandPalette;
 use editor::DisplayPoint;
+use futures::StreamExt;
 use gpui::KeyBinding;
 pub use neovim_backed_binding_test_context::*;
 pub use neovim_backed_test_context::*;
@@ -847,3 +848,39 @@ async fn test_comma_w(cx: &mut gpui::TestAppContext) {
     cx.assert_shared_state("hellˇo hello\nhello hello").await;
     cx.assert_shared_mode(Mode::Insert).await;
 }
+
+#[gpui::test]
+async fn test_rename(cx: &mut gpui::TestAppContext) {
+    let mut cx = VimTestContext::new_typescript(cx).await;
+
+    cx.set_state("const beˇfore = 2; console.log(before)", Mode::Normal);
+    let def_range = cx.lsp_range("const «beforeˇ» = 2; console.log(before)");
+    let tgt_range = cx.lsp_range("const before = 2; console.log(«beforeˇ»)");
+    let mut prepare_request =
+        cx.handle_request::<lsp::request::PrepareRenameRequest, _, _>(move |_, _, _| async move {
+            Ok(Some(lsp::PrepareRenameResponse::Range(def_range)))
+        });
+    let mut rename_request =
+        cx.handle_request::<lsp::request::Rename, _, _>(move |url, params, _| async move {
+            Ok(Some(lsp::WorkspaceEdit {
+                changes: Some(
+                    [(
+                        url.clone(),
+                        vec![
+                            lsp::TextEdit::new(def_range, params.new_name.clone()),
+                            lsp::TextEdit::new(tgt_range, params.new_name),
+                        ],
+                    )]
+                    .into(),
+                ),
+                ..Default::default()
+            }))
+        });
+
+    cx.simulate_keystrokes(["c", "d"]);
+    prepare_request.next().await.unwrap();
+    cx.simulate_input("after");
+    cx.simulate_keystrokes(["enter"]);
+    rename_request.next().await.unwrap();
+    cx.assert_state("const afterˇ = 2; console.log(after)", Mode::Normal)
+}

crates/vim/src/test/vim_test_context.rs 🔗

@@ -1,11 +1,7 @@
 use std::ops::{Deref, DerefMut};
 
-use editor::test::{
-    editor_lsp_test_context::EditorLspTestContext, editor_test_context::EditorTestContext,
-};
-use futures::Future;
+use editor::test::editor_lsp_test_context::EditorLspTestContext;
 use gpui::{Context, View, VisualContext};
-use lsp::request;
 use search::{project_search::ProjectSearchBar, BufferSearchBar};
 
 use crate::{state::Operator, *};
@@ -38,7 +34,17 @@ impl VimTestContext {
     pub async fn new_typescript(cx: &mut gpui::TestAppContext) -> VimTestContext {
         Self::init(cx);
         Self::new_with_lsp(
-            EditorLspTestContext::new_typescript(Default::default(), cx).await,
+            EditorLspTestContext::new_typescript(
+                lsp::ServerCapabilities {
+                    rename_provider: Some(lsp::OneOf::Right(lsp::RenameOptions {
+                        prepare_provider: Some(true),
+                        work_done_progress_options: Default::default(),
+                    })),
+                    ..Default::default()
+                },
+                cx,
+            )
+            .await,
             true,
         )
     }
@@ -149,23 +155,10 @@ impl VimTestContext {
         assert_eq!(self.mode(), mode_after, "{}", self.assertion_context());
         assert_eq!(self.active_operator(), None, "{}", self.assertion_context());
     }
-
-    pub fn handle_request<T, F, Fut>(
-        &self,
-        handler: F,
-    ) -> futures::channel::mpsc::UnboundedReceiver<()>
-    where
-        T: 'static + request::Request,
-        T::Params: 'static + Send,
-        F: 'static + Send + FnMut(lsp::Url, T::Params, gpui::AsyncAppContext) -> Fut,
-        Fut: 'static + Send + Future<Output = Result<T::Result>>,
-    {
-        self.cx.handle_request::<T, F, Fut>(handler)
-    }
 }
 
 impl Deref for VimTestContext {
-    type Target = EditorTestContext;
+    type Target = EditorLspTestContext;
 
     fn deref(&self) -> &Self::Target {
         &self.cx

crates/vim/src/vim.rs 🔗

@@ -198,7 +198,7 @@ impl Vim {
     }
 
     fn activate_editor(&mut self, editor: View<Editor>, cx: &mut WindowContext) {
-        if editor.read(cx).mode() != EditorMode::Full {
+        if !editor.read(cx).use_modal_editing() {
             return;
         }
 
@@ -575,8 +575,11 @@ impl Vim {
             editor.set_input_enabled(!state.vim_controlled());
             editor.set_autoindent(state.should_autoindent());
             editor.selections.line_mode = matches!(state.mode, Mode::VisualLine);
-            let context_layer = state.keymap_context_layer();
-            editor.set_keymap_context_layer::<Self>(context_layer, cx);
+            if editor.is_focused(cx) {
+                editor.set_keymap_context_layer::<Self>(state.keymap_context_layer(), cx);
+            } else {
+                editor.remove_keymap_context_layer::<Self>(cx);
+            }
         });
     }