vim: Fix search in the Assistant (#20258)

Conrad Irwin created

Closes #17704

Release Notes:

- vim: Fix search in the assistant panel

Change summary

crates/assistant/src/assistant_panel.rs | 16 ++++++++++++++++
crates/vim/src/normal/search.rs         |  4 +++-
crates/vim/src/vim.rs                   | 23 +++++++++++++----------
crates/vim/src/visual.rs                |  7 +------
crates/workspace/src/workspace.rs       | 15 +++++++++++++++
5 files changed, 48 insertions(+), 17 deletions(-)

Detailed changes

crates/assistant/src/assistant_panel.rs 🔗

@@ -64,6 +64,7 @@ use serde::{Deserialize, Serialize};
 use settings::{update_settings_file, Settings};
 use smol::stream::StreamExt;
 use std::{
+    any::TypeId,
     borrow::Cow,
     cmp,
     ops::{ControlFlow, Range},
@@ -4186,6 +4187,21 @@ impl Item for ContextEditor {
     fn deactivated(&mut self, cx: &mut ViewContext<Self>) {
         self.editor.update(cx, Item::deactivated)
     }
+
+    fn act_as_type<'a>(
+        &'a self,
+        type_id: TypeId,
+        self_handle: &'a View<Self>,
+        _: &'a AppContext,
+    ) -> Option<AnyView> {
+        if type_id == TypeId::of::<Self>() {
+            Some(self_handle.to_any())
+        } else if type_id == TypeId::of::<Editor>() {
+            Some(self.editor.to_any())
+        } else {
+            None
+        }
+    }
 }
 
 impl SearchableItem for ContextEditor {

crates/vim/src/normal/search.rs 🔗

@@ -112,7 +112,9 @@ impl Vim {
     }
 
     fn search(&mut self, action: &Search, cx: &mut ViewContext<Self>) {
-        let Some(pane) = self.pane(cx) else { return };
+        let Some(pane) = self.pane(cx) else {
+            return;
+        };
         let direction = if action.backwards {
             Direction::Prev
         } else {

crates/vim/src/vim.rs 🔗

@@ -114,12 +114,13 @@ pub fn init(cx: &mut AppContext) {
         });
 
         workspace.register_action(|workspace, _: &SearchSubmit, cx| {
-            let Some(vim) = workspace
-                .active_item_as::<Editor>(cx)
-                .and_then(|editor| editor.read(cx).addon::<VimAddon>().cloned())
-            else {
-                return;
-            };
+            let vim = workspace
+                .focused_pane(cx)
+                .read(cx)
+                .active_item()
+                .and_then(|item| item.act_as::<Editor>(cx))
+                .and_then(|editor| editor.read(cx).addon::<VimAddon>().cloned());
+            let Some(vim) = vim else { return };
             vim.view
                 .update(cx, |_, cx| cx.defer(|vim, cx| vim.search_submit(cx)))
         });
@@ -334,13 +335,15 @@ impl Vim {
         self.editor.upgrade()
     }
 
-    pub fn workspace(&self, cx: &ViewContext<Self>) -> Option<View<Workspace>> {
-        self.editor().and_then(|editor| editor.read(cx).workspace())
+    pub fn workspace(&self, cx: &mut ViewContext<Self>) -> Option<View<Workspace>> {
+        cx.window_handle()
+            .downcast::<Workspace>()
+            .and_then(|handle| handle.root(cx).ok())
     }
 
-    pub fn pane(&self, cx: &ViewContext<Self>) -> Option<View<Pane>> {
+    pub fn pane(&self, cx: &mut ViewContext<Self>) -> Option<View<Pane>> {
         self.workspace(cx)
-            .and_then(|workspace| workspace.read(cx).pane_for(&self.editor()?))
+            .map(|workspace| workspace.read(cx).focused_pane(cx))
     }
 
     pub fn enabled(cx: &mut AppContext) -> bool {

crates/vim/src/visual.rs 🔗

@@ -576,14 +576,9 @@ impl Vim {
 
     pub fn select_match(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
         let count = self.take_count(cx).unwrap_or(1);
-        let Some(workspace) = self
-            .editor
-            .upgrade()
-            .and_then(|editor| editor.read(cx).workspace())
-        else {
+        let Some(pane) = self.pane(cx) else {
             return;
         };
-        let pane = workspace.read(cx).active_pane().clone();
         let vim_is_normal = self.mode == Mode::Normal;
         let mut start_selection = 0usize;
         let mut end_selection = 0usize;

crates/workspace/src/workspace.rs 🔗

@@ -3219,6 +3219,21 @@ impl Workspace {
         &self.active_pane
     }
 
+    pub fn focused_pane(&self, cx: &WindowContext) -> View<Pane> {
+        for dock in [&self.left_dock, &self.right_dock, &self.bottom_dock] {
+            if dock.focus_handle(cx).contains_focused(cx) {
+                if let Some(pane) = dock
+                    .read(cx)
+                    .active_panel()
+                    .and_then(|panel| panel.pane(cx))
+                {
+                    return pane;
+                }
+            }
+        }
+        self.active_pane().clone()
+    }
+
     pub fn adjacent_pane(&mut self, cx: &mut ViewContext<Self>) -> View<Pane> {
         self.find_pane_in_direction(SplitDirection::Right, cx)
             .or_else(|| self.find_pane_in_direction(SplitDirection::Left, cx))