Implement FileFinder

Conrad Irwin created

Change summary

crates/file_finder2/src/file_finder.rs | 3121 +++++++++++++--------------
crates/picker2/src/picker2.rs          |    5 
crates/workspace2/src/workspace2.rs    |  144 
3 files changed, 1,615 insertions(+), 1,655 deletions(-)

Detailed changes

crates/file_finder2/src/file_finder.rs 🔗

@@ -2,7 +2,8 @@ use collections::HashMap;
 use editor::{scroll::autoscroll::Autoscroll, Bias, Editor};
 use fuzzy::{CharBag, PathMatch, PathMatchCandidate};
 use gpui::{
-    actions, AppContext, Div, EventEmitter, Render, Task, View, ViewContext, WindowContext,
+    actions, div, AppContext, Component, Div, EventEmitter, Model, ParentElement, Render,
+    StatelessInteractive, Styled, Task, View, ViewContext, VisualContext, WeakView, WindowContext,
 };
 use picker::{Picker, PickerDelegate};
 use project::{PathMatchCandidateSet, Project, ProjectPath, WorktreeId};
@@ -14,7 +15,9 @@ use std::{
     },
 };
 use text::Point;
-use util::{paths::PathLikeWithPosition, post_inc};
+use theme::ActiveTheme;
+use ui::{v_stack, HighlightedLabel, StyledExt};
+use util::{paths::PathLikeWithPosition, post_inc, ResultExt};
 use workspace::{Modal, ModalEvent, Workspace};
 
 actions!(Toggle);
@@ -24,14 +27,16 @@ pub struct FileFinder {
 }
 
 pub fn init(cx: &mut AppContext) {
-    cx.observe_new_views(FileFinder::register);
+    cx.observe_new_views(FileFinder::register).detach();
 }
 
 impl FileFinder {
     fn register(workspace: &mut Workspace, _: &mut ViewContext<Workspace>) {
+        dbg!("yay");
         workspace.register_action(|workspace, _: &Toggle, cx| {
+            dbg!("yayer");
             let Some(file_finder) = workspace.current_modal::<Self>(cx) else {
-                workspace.toggle_modal(cx, |cx| FileFinder::new(workspace, cx));
+                Self::open(workspace, cx);
                 return;
             };
             file_finder.update(cx, |file_finder, cx| {
@@ -42,7 +47,7 @@ impl FileFinder {
         });
     }
 
-    fn new(workspace: &mut Workspace, cx: &mut ViewContext<Self>) -> Self {
+    fn open(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) {
         let project = workspace.project().read(cx);
 
         let currently_opened_path = workspace
@@ -84,20 +89,25 @@ impl FileFinder {
             .collect();
 
         let project = workspace.project().clone();
-        let workspace = cx.handle().downgrade();
-        let finder = cx.add_view(|cx| {
-            Picker::new(
-                FileFinderDelegate::new(
-                    workspace,
-                    project,
-                    currently_opened_path,
-                    history_items,
-                    cx,
-                ),
+        let weak_workspace = cx.view().downgrade();
+        workspace.toggle_modal(cx, |cx| {
+            let delegate = FileFinderDelegate::new(
+                cx.view().downgrade(),
+                weak_workspace,
+                project,
+                currently_opened_path,
+                history_items,
                 cx,
-            )
+            );
+
+            FileFinder::new(delegate, cx)
         });
-        finder
+    }
+
+    fn new(delegate: FileFinderDelegate, cx: &mut ViewContext<Self>) -> Self {
+        Self {
+            picker: cx.build_view(|cx| Picker::new(delegate, cx)),
+        }
     }
 }
 
@@ -116,8 +126,9 @@ impl Render for FileFinder {
 }
 
 pub struct FileFinderDelegate {
-    workspace: WeakViewHandle<Workspace>,
-    project: ModelHandle<Project>,
+    file_finder: WeakView<FileFinder>,
+    workspace: WeakView<Workspace>,
+    project: Model<Project>,
     search_count: usize,
     latest_search_id: usize,
     latest_search_did_cancel: bool,
@@ -263,82 +274,6 @@ impl FoundPath {
 
 const MAX_RECENT_SELECTIONS: usize = 20;
 
-fn toggle_or_cycle_file_finder(
-    workspace: &mut Workspace,
-    _: &Toggle,
-    cx: &mut ViewContext<Workspace>,
-) {
-    match workspace.modal::<FileFinder>() {
-        Some(file_finder) => file_finder.update(cx, |file_finder, cx| {
-            let current_index = file_finder.delegate().selected_index();
-            file_finder.select_next(&menu::SelectNext, cx);
-            let new_index = file_finder.delegate().selected_index();
-            if current_index == new_index {
-                file_finder.select_first(&menu::SelectFirst, cx);
-            }
-        }),
-        None => {
-            workspace.toggle_modal(cx, |workspace, cx| {
-                let project = workspace.project().read(cx);
-
-                let currently_opened_path = workspace
-                    .active_item(cx)
-                    .and_then(|item| item.project_path(cx))
-                    .map(|project_path| {
-                        let abs_path = project
-                            .worktree_for_id(project_path.worktree_id, cx)
-                            .map(|worktree| worktree.read(cx).abs_path().join(&project_path.path));
-                        FoundPath::new(project_path, abs_path)
-                    });
-
-                // if exists, bubble the currently opened path to the top
-                let history_items = currently_opened_path
-                    .clone()
-                    .into_iter()
-                    .chain(
-                        workspace
-                            .recent_navigation_history(Some(MAX_RECENT_SELECTIONS), cx)
-                            .into_iter()
-                            .filter(|(history_path, _)| {
-                                Some(history_path)
-                                    != currently_opened_path
-                                        .as_ref()
-                                        .map(|found_path| &found_path.project)
-                            })
-                            .filter(|(_, history_abs_path)| {
-                                history_abs_path.as_ref()
-                                    != currently_opened_path
-                                        .as_ref()
-                                        .and_then(|found_path| found_path.absolute.as_ref())
-                            })
-                            .filter(|(_, history_abs_path)| match history_abs_path {
-                                Some(abs_path) => history_file_exists(abs_path),
-                                None => true,
-                            })
-                            .map(|(history_path, abs_path)| FoundPath::new(history_path, abs_path)),
-                    )
-                    .collect();
-
-                let project = workspace.project().clone();
-                let workspace = cx.handle().downgrade();
-                let finder = cx.add_view(|cx| {
-                    Picker::new(
-                        FileFinderDelegate::new(
-                            workspace,
-                            project,
-                            currently_opened_path,
-                            history_items,
-                            cx,
-                        ),
-                        cx,
-                    )
-                });
-                finder
-            });
-        }
-    }
-}
-
 #[cfg(not(test))]
 fn history_file_exists(abs_path: &PathBuf) -> bool {
     abs_path.exists()
@@ -371,17 +306,23 @@ impl FileSearchQuery {
 
 impl FileFinderDelegate {
     fn new(
-        workspace: WeakViewHandle<Workspace>,
-        project: ModelHandle<Project>,
+        file_finder: WeakView<FileFinder>,
+        workspace: WeakView<Workspace>,
+        project: Model<Project>,
         currently_opened_path: Option<FoundPath>,
         history_items: Vec<FoundPath>,
         cx: &mut ViewContext<FileFinder>,
     ) -> Self {
-        cx.observe(&project, |picker, _, cx| {
-            picker.update_matches(picker.query(cx), cx);
+        cx.observe(&project, |file_finder, _, cx| {
+            //todo!() We should probably not re-render on every project anything
+            file_finder
+                .picker
+                .update(cx, |picker, cx| picker.refresh(cx))
         })
         .detach();
+
         Self {
+            file_finder,
             workspace,
             project,
             search_count: 0,
@@ -399,7 +340,7 @@ impl FileFinderDelegate {
     fn spawn_search(
         &mut self,
         query: PathLikeWithPosition<FileSearchQuery>,
-        cx: &mut ViewContext<FileFinder>,
+        cx: &mut ViewContext<Picker<Self>>,
     ) -> Task<()> {
         let relative_to = self
             .currently_opened_path
@@ -437,14 +378,14 @@ impl FileFinderDelegate {
                 false,
                 100,
                 &cancel_flag,
-                cx.background(),
+                cx.background_executor().clone(),
             )
             .await;
             let did_cancel = cancel_flag.load(atomic::Ordering::Relaxed);
             picker
                 .update(&mut cx, |picker, cx| {
                     picker
-                        .delegate_mut()
+                        .delegate
                         .set_search_matches(search_id, did_cancel, query, matches, cx)
                 })
                 .log_err();
@@ -457,7 +398,7 @@ impl FileFinderDelegate {
         did_cancel: bool,
         query: PathLikeWithPosition<FileSearchQuery>,
         matches: Vec<PathMatch>,
-        cx: &mut ViewContext<FileFinder>,
+        cx: &mut ViewContext<Picker<Self>>,
     ) {
         if search_id >= self.latest_search_id {
             self.latest_search_id = search_id;
@@ -589,6 +530,8 @@ impl FileFinderDelegate {
 }
 
 impl PickerDelegate for FileFinderDelegate {
+    type ListItem = Div<Picker<Self>>;
+
     fn placeholder_text(&self) -> Arc<str> {
         "Search project files...".into()
     }
@@ -601,12 +544,16 @@ impl PickerDelegate for FileFinderDelegate {
         self.selected_index.unwrap_or(0)
     }
 
-    fn set_selected_index(&mut self, ix: usize, cx: &mut ViewContext<FileFinder>) {
+    fn set_selected_index(&mut self, ix: usize, cx: &mut ViewContext<Picker<Self>>) {
         self.selected_index = Some(ix);
         cx.notify();
     }
 
-    fn update_matches(&mut self, raw_query: String, cx: &mut ViewContext<FileFinder>) -> Task<()> {
+    fn update_matches(
+        &mut self,
+        raw_query: String,
+        cx: &mut ViewContext<Picker<Self>>,
+    ) -> Task<()> {
         if raw_query.is_empty() {
             let project = self.project.read(cx);
             self.latest_search_id = post_inc(&mut self.search_count);
@@ -644,9 +591,9 @@ impl PickerDelegate for FileFinderDelegate {
         }
     }
 
-    fn confirm(&mut self, secondary: bool, cx: &mut ViewContext<FileFinder>) {
+    fn confirm(&mut self, secondary: bool, cx: &mut ViewContext<Picker<FileFinderDelegate>>) {
         if let Some(m) = self.matches.get(self.selected_index()) {
-            if let Some(workspace) = self.workspace.upgrade(cx) {
+            if let Some(workspace) = self.workspace.upgrade() {
                 let open_task = workspace.update(cx, move |workspace, cx| {
                     let split_or_open = |workspace: &mut Workspace, project_path, cx| {
                         if secondary {
@@ -722,6 +669,8 @@ impl PickerDelegate for FileFinderDelegate {
                     .and_then(|query| query.column)
                     .unwrap_or(0)
                     .saturating_sub(1);
+                let finder = self.file_finder.clone();
+
                 cx.spawn(|_, mut cx| async move {
                     let item = open_task.await.log_err()?;
                     if let Some(row) = row {
@@ -740,10 +689,9 @@ impl PickerDelegate for FileFinderDelegate {
                                 .log_err();
                         }
                     }
-                    workspace
-                        .downgrade()
-                        .update(&mut cx, |workspace, cx| workspace.dismiss_modal(cx))
-                        .log_err();
+                    finder
+                        .update(&mut cx, |_, cx| cx.emit(ModalEvent::Dismissed))
+                        .ok()?;
 
                     Some(())
                 })
@@ -752,1490 +700,1497 @@ impl PickerDelegate for FileFinderDelegate {
         }
     }
 
-    fn dismissed(&mut self, _: &mut ViewContext<FileFinder>) {}
+    fn dismissed(&mut self, cx: &mut ViewContext<Picker<FileFinderDelegate>>) {
+        self.file_finder
+            .update(cx, |_, cx| cx.emit(ModalEvent::Dismissed))
+            .log_err();
+    }
 
     fn render_match(
         &self,
         ix: usize,
-        mouse_state: &mut MouseState,
         selected: bool,
-        cx: &AppContext,
-    ) -> AnyElement<Picker<Self>> {
+        cx: &mut ViewContext<Picker<Self>>,
+    ) -> Self::ListItem {
         let path_match = self
             .matches
             .get(ix)
             .expect("Invalid matches state: no element for index {ix}");
-        let theme = theme::current(cx);
-        let style = theme.picker.item.in_state(selected).style_for(mouse_state);
+        let theme = cx.theme();
+        let colors = theme.colors();
+
         let (file_name, file_name_positions, full_path, full_path_positions) =
             self.labels_for_match(path_match, cx, ix);
-        Flex::column()
-            .with_child(
-                Label::new(file_name, style.label.clone()).with_highlights(file_name_positions),
-            )
-            .with_child(
-                Label::new(full_path, style.label.clone()).with_highlights(full_path_positions),
-            )
-            .flex(1., false)
-            .contained()
-            .with_style(style.container)
-            .into_any_named("match")
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use std::{assert_eq, collections::HashMap, path::Path, time::Duration};
-
-    use super::*;
-    use editor::Editor;
-    use gpui::{TestAppContext, ViewHandle};
-    use menu::{Confirm, SelectNext};
-    use serde_json::json;
-    use workspace::{AppState, Workspace};
-
-    #[ctor::ctor]
-    fn init_logger() {
-        if std::env::var("RUST_LOG").is_ok() {
-            env_logger::init();
-        }
-    }
-
-    #[gpui::test]
-    async fn test_matching_paths(cx: &mut TestAppContext) {
-        let app_state = init_test(cx);
-        app_state
-            .fs
-            .as_fake()
-            .insert_tree(
-                "/root",
-                json!({
-                    "a": {
-                        "banana": "",
-                        "bandana": "",
-                    }
-                }),
-            )
-            .await;
-
-        let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
-        let window = cx.add_window(|cx| Workspace::test_new(project, cx));
-        let workspace = window.root(cx);
-        cx.dispatch_action(window.into(), Toggle);
-
-        let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
-        finder
-            .update(cx, |finder, cx| {
-                finder.delegate_mut().update_matches("bna".to_string(), cx)
-            })
-            .await;
-        finder.read_with(cx, |finder, _| {
-            assert_eq!(finder.delegate().matches.len(), 2);
-        });
 
-        let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone());
-        cx.dispatch_action(window.into(), SelectNext);
-        cx.dispatch_action(window.into(), Confirm);
-        active_pane
-            .condition(cx, |pane, _| pane.active_item().is_some())
-            .await;
-        cx.read(|cx| {
-            let active_item = active_pane.read(cx).active_item().unwrap();
-            assert_eq!(
-                active_item
-                    .as_any()
-                    .downcast_ref::<Editor>()
-                    .unwrap()
-                    .read(cx)
-                    .title(cx),
-                "bandana"
-            );
-        });
-    }
-
-    #[gpui::test]
-    async fn test_row_column_numbers_query_inside_file(cx: &mut TestAppContext) {
-        let app_state = init_test(cx);
-
-        let first_file_name = "first.rs";
-        let first_file_contents = "// First Rust file";
-        app_state
-            .fs
-            .as_fake()
-            .insert_tree(
-                "/src",
-                json!({
-                    "test": {
-                        first_file_name: first_file_contents,
-                        "second.rs": "// Second Rust file",
-                    }
-                }),
+        div()
+            .px_1()
+            .text_color(colors.text)
+            .text_ui()
+            .bg(colors.ghost_element_background)
+            .rounded_md()
+            .when(selected, |this| this.bg(colors.ghost_element_selected))
+            .hover(|this| this.bg(colors.ghost_element_hover))
+            .child(
+                v_stack()
+                    .child(HighlightedLabel::new(file_name, file_name_positions))
+                    .child(HighlightedLabel::new(full_path, full_path_positions)),
             )
-            .await;
-
-        let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
-        let window = cx.add_window(|cx| Workspace::test_new(project, cx));
-        let workspace = window.root(cx);
-        cx.dispatch_action(window.into(), Toggle);
-        let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
-
-        let file_query = &first_file_name[..3];
-        let file_row = 1;
-        let file_column = 3;
-        assert!(file_column <= first_file_contents.len());
-        let query_inside_file = format!("{file_query}:{file_row}:{file_column}");
-        finder
-            .update(cx, |finder, cx| {
-                finder
-                    .delegate_mut()
-                    .update_matches(query_inside_file.to_string(), cx)
-            })
-            .await;
-        finder.read_with(cx, |finder, _| {
-            let finder = finder.delegate();
-            assert_eq!(finder.matches.len(), 1);
-            let latest_search_query = finder
-                .latest_search_query
-                .as_ref()
-                .expect("Finder should have a query after the update_matches call");
-            assert_eq!(latest_search_query.path_like.raw_query, query_inside_file);
-            assert_eq!(
-                latest_search_query.path_like.file_query_end,
-                Some(file_query.len())
-            );
-            assert_eq!(latest_search_query.row, Some(file_row));
-            assert_eq!(latest_search_query.column, Some(file_column as u32));
-        });
-
-        let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone());
-        cx.dispatch_action(window.into(), SelectNext);
-        cx.dispatch_action(window.into(), Confirm);
-        active_pane
-            .condition(cx, |pane, _| pane.active_item().is_some())
-            .await;
-        let editor = cx.update(|cx| {
-            let active_item = active_pane.read(cx).active_item().unwrap();
-            active_item.downcast::<Editor>().unwrap()
-        });
-        cx.foreground().advance_clock(Duration::from_secs(2));
-        cx.foreground().start_waiting();
-        cx.foreground().finish_waiting();
-        editor.update(cx, |editor, cx| {
-            let all_selections = editor.selections.all_adjusted(cx);
-            assert_eq!(
-                all_selections.len(),
-                1,
-                "Expected to have 1 selection (caret) after file finder confirm, but got: {all_selections:?}"
-            );
-            let caret_selection = all_selections.into_iter().next().unwrap();
-            assert_eq!(caret_selection.start, caret_selection.end,
-                "Caret selection should have its start and end at the same position");
-            assert_eq!(file_row, caret_selection.start.row + 1,
-                "Query inside file should get caret with the same focus row");
-            assert_eq!(file_column, caret_selection.start.column as usize + 1,
-                "Query inside file should get caret with the same focus column");
-        });
-    }
-
-    #[gpui::test]
-    async fn test_row_column_numbers_query_outside_file(cx: &mut TestAppContext) {
-        let app_state = init_test(cx);
-
-        let first_file_name = "first.rs";
-        let first_file_contents = "// First Rust file";
-        app_state
-            .fs
-            .as_fake()
-            .insert_tree(
-                "/src",
-                json!({
-                    "test": {
-                        first_file_name: first_file_contents,
-                        "second.rs": "// Second Rust file",
-                    }
-                }),
-            )
-            .await;
-
-        let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
-        let window = cx.add_window(|cx| Workspace::test_new(project, cx));
-        let workspace = window.root(cx);
-        cx.dispatch_action(window.into(), Toggle);
-        let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
-
-        let file_query = &first_file_name[..3];
-        let file_row = 200;
-        let file_column = 300;
-        assert!(file_column > first_file_contents.len());
-        let query_outside_file = format!("{file_query}:{file_row}:{file_column}");
-        finder
-            .update(cx, |finder, cx| {
-                finder
-                    .delegate_mut()
-                    .update_matches(query_outside_file.to_string(), cx)
-            })
-            .await;
-        finder.read_with(cx, |finder, _| {
-            let finder = finder.delegate();
-            assert_eq!(finder.matches.len(), 1);
-            let latest_search_query = finder
-                .latest_search_query
-                .as_ref()
-                .expect("Finder should have a query after the update_matches call");
-            assert_eq!(latest_search_query.path_like.raw_query, query_outside_file);
-            assert_eq!(
-                latest_search_query.path_like.file_query_end,
-                Some(file_query.len())
-            );
-            assert_eq!(latest_search_query.row, Some(file_row));
-            assert_eq!(latest_search_query.column, Some(file_column as u32));
-        });
-
-        let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone());
-        cx.dispatch_action(window.into(), SelectNext);
-        cx.dispatch_action(window.into(), Confirm);
-        active_pane
-            .condition(cx, |pane, _| pane.active_item().is_some())
-            .await;
-        let editor = cx.update(|cx| {
-            let active_item = active_pane.read(cx).active_item().unwrap();
-            active_item.downcast::<Editor>().unwrap()
-        });
-        cx.foreground().advance_clock(Duration::from_secs(2));
-        cx.foreground().start_waiting();
-        cx.foreground().finish_waiting();
-        editor.update(cx, |editor, cx| {
-            let all_selections = editor.selections.all_adjusted(cx);
-            assert_eq!(
-                all_selections.len(),
-                1,
-                "Expected to have 1 selection (caret) after file finder confirm, but got: {all_selections:?}"
-            );
-            let caret_selection = all_selections.into_iter().next().unwrap();
-            assert_eq!(caret_selection.start, caret_selection.end,
-                "Caret selection should have its start and end at the same position");
-            assert_eq!(0, caret_selection.start.row,
-                "Excessive rows (as in query outside file borders) should get trimmed to last file row");
-            assert_eq!(first_file_contents.len(), caret_selection.start.column as usize,
-                "Excessive columns (as in query outside file borders) should get trimmed to selected row's last column");
-        });
-    }
-
-    #[gpui::test]
-    async fn test_matching_cancellation(cx: &mut TestAppContext) {
-        let app_state = init_test(cx);
-        app_state
-            .fs
-            .as_fake()
-            .insert_tree(
-                "/dir",
-                json!({
-                    "hello": "",
-                    "goodbye": "",
-                    "halogen-light": "",
-                    "happiness": "",
-                    "height": "",
-                    "hi": "",
-                    "hiccup": "",
-                }),
-            )
-            .await;
-
-        let project = Project::test(app_state.fs.clone(), ["/dir".as_ref()], cx).await;
-        let workspace = cx
-            .add_window(|cx| Workspace::test_new(project, cx))
-            .root(cx);
-        let finder = cx
-            .add_window(|cx| {
-                Picker::new(
-                    FileFinderDelegate::new(
-                        workspace.downgrade(),
-                        workspace.read(cx).project().clone(),
-                        None,
-                        Vec::new(),
-                        cx,
-                    ),
-                    cx,
-                )
-            })
-            .root(cx);
-
-        let query = test_path_like("hi");
-        finder
-            .update(cx, |f, cx| f.delegate_mut().spawn_search(query.clone(), cx))
-            .await;
-        finder.read_with(cx, |f, _| assert_eq!(f.delegate().matches.len(), 5));
-
-        finder.update(cx, |finder, cx| {
-            let delegate = finder.delegate_mut();
-            assert!(
-                delegate.matches.history.is_empty(),
-                "Search matches expected"
-            );
-            let matches = delegate.matches.search.clone();
-
-            // Simulate a search being cancelled after the time limit,
-            // returning only a subset of the matches that would have been found.
-            drop(delegate.spawn_search(query.clone(), cx));
-            delegate.set_search_matches(
-                delegate.latest_search_id,
-                true, // did-cancel
-                query.clone(),
-                vec![matches[1].clone(), matches[3].clone()],
-                cx,
-            );
-
-            // Simulate another cancellation.
-            drop(delegate.spawn_search(query.clone(), cx));
-            delegate.set_search_matches(
-                delegate.latest_search_id,
-                true, // did-cancel
-                query.clone(),
-                vec![matches[0].clone(), matches[2].clone(), matches[3].clone()],
-                cx,
-            );
-
-            assert!(
-                delegate.matches.history.is_empty(),
-                "Search matches expected"
-            );
-            assert_eq!(delegate.matches.search.as_slice(), &matches[0..4]);
-        });
-    }
-
-    #[gpui::test]
-    async fn test_ignored_files(cx: &mut TestAppContext) {
-        let app_state = init_test(cx);
-        app_state
-            .fs
-            .as_fake()
-            .insert_tree(
-                "/ancestor",
-                json!({
-                    ".gitignore": "ignored-root",
-                    "ignored-root": {
-                        "happiness": "",
-                        "height": "",
-                        "hi": "",
-                        "hiccup": "",
-                    },
-                    "tracked-root": {
-                        ".gitignore": "height",
-                        "happiness": "",
-                        "height": "",
-                        "hi": "",
-                        "hiccup": "",
-                    },
-                }),
-            )
-            .await;
-
-        let project = Project::test(
-            app_state.fs.clone(),
-            [
-                "/ancestor/tracked-root".as_ref(),
-                "/ancestor/ignored-root".as_ref(),
-            ],
-            cx,
-        )
-        .await;
-        let workspace = cx
-            .add_window(|cx| Workspace::test_new(project, cx))
-            .root(cx);
-        let finder = cx
-            .add_window(|cx| {
-                Picker::new(
-                    FileFinderDelegate::new(
-                        workspace.downgrade(),
-                        workspace.read(cx).project().clone(),
-                        None,
-                        Vec::new(),
-                        cx,
-                    ),
-                    cx,
-                )
-            })
-            .root(cx);
-        finder
-            .update(cx, |f, cx| {
-                f.delegate_mut().spawn_search(test_path_like("hi"), cx)
-            })
-            .await;
-        finder.read_with(cx, |f, _| assert_eq!(f.delegate().matches.len(), 7));
-    }
-
-    #[gpui::test]
-    async fn test_single_file_worktrees(cx: &mut TestAppContext) {
-        let app_state = init_test(cx);
-        app_state
-            .fs
-            .as_fake()
-            .insert_tree("/root", json!({ "the-parent-dir": { "the-file": "" } }))
-            .await;
-
-        let project = Project::test(
-            app_state.fs.clone(),
-            ["/root/the-parent-dir/the-file".as_ref()],
-            cx,
-        )
-        .await;
-        let workspace = cx
-            .add_window(|cx| Workspace::test_new(project, cx))
-            .root(cx);
-        let finder = cx
-            .add_window(|cx| {
-                Picker::new(
-                    FileFinderDelegate::new(
-                        workspace.downgrade(),
-                        workspace.read(cx).project().clone(),
-                        None,
-                        Vec::new(),
-                        cx,
-                    ),
-                    cx,
-                )
-            })
-            .root(cx);
-
-        // Even though there is only one worktree, that worktree's filename
-        // is included in the matching, because the worktree is a single file.
-        finder
-            .update(cx, |f, cx| {
-                f.delegate_mut().spawn_search(test_path_like("thf"), cx)
-            })
-            .await;
-        cx.read(|cx| {
-            let finder = finder.read(cx);
-            let delegate = finder.delegate();
-            assert!(
-                delegate.matches.history.is_empty(),
-                "Search matches expected"
-            );
-            let matches = delegate.matches.search.clone();
-            assert_eq!(matches.len(), 1);
-
-            let (file_name, file_name_positions, full_path, full_path_positions) =
-                delegate.labels_for_path_match(&matches[0]);
-            assert_eq!(file_name, "the-file");
-            assert_eq!(file_name_positions, &[0, 1, 4]);
-            assert_eq!(full_path, "the-file");
-            assert_eq!(full_path_positions, &[0, 1, 4]);
-        });
-
-        // Since the worktree root is a file, searching for its name followed by a slash does
-        // not match anything.
-        finder
-            .update(cx, |f, cx| {
-                f.delegate_mut().spawn_search(test_path_like("thf/"), cx)
-            })
-            .await;
-        finder.read_with(cx, |f, _| assert_eq!(f.delegate().matches.len(), 0));
-    }
-
-    #[gpui::test]
-    async fn test_path_distance_ordering(cx: &mut TestAppContext) {
-        let app_state = init_test(cx);
-        app_state
-            .fs
-            .as_fake()
-            .insert_tree(
-                "/root",
-                json!({
-                    "dir1": { "a.txt": "" },
-                    "dir2": {
-                        "a.txt": "",
-                        "b.txt": ""
-                    }
-                }),
-            )
-            .await;
-
-        let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
-        let workspace = cx
-            .add_window(|cx| Workspace::test_new(project, cx))
-            .root(cx);
-        let worktree_id = cx.read(|cx| {
-            let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
-            assert_eq!(worktrees.len(), 1);
-            WorktreeId::from_usize(worktrees[0].id())
-        });
-
-        // When workspace has an active item, sort items which are closer to that item
-        // first when they have the same name. In this case, b.txt is closer to dir2's a.txt
-        // so that one should be sorted earlier
-        let b_path = Some(dummy_found_path(ProjectPath {
-            worktree_id,
-            path: Arc::from(Path::new("/root/dir2/b.txt")),
-        }));
-        let finder = cx
-            .add_window(|cx| {
-                Picker::new(
-                    FileFinderDelegate::new(
-                        workspace.downgrade(),
-                        workspace.read(cx).project().clone(),
-                        b_path,
-                        Vec::new(),
-                        cx,
-                    ),
-                    cx,
-                )
-            })
-            .root(cx);
-
-        finder
-            .update(cx, |f, cx| {
-                f.delegate_mut().spawn_search(test_path_like("a.txt"), cx)
-            })
-            .await;
-
-        finder.read_with(cx, |f, _| {
-            let delegate = f.delegate();
-            assert!(
-                delegate.matches.history.is_empty(),
-                "Search matches expected"
-            );
-            let matches = delegate.matches.search.clone();
-            assert_eq!(matches[0].path.as_ref(), Path::new("dir2/a.txt"));
-            assert_eq!(matches[1].path.as_ref(), Path::new("dir1/a.txt"));
-        });
-    }
-
-    #[gpui::test]
-    async fn test_search_worktree_without_files(cx: &mut TestAppContext) {
-        let app_state = init_test(cx);
-        app_state
-            .fs
-            .as_fake()
-            .insert_tree(
-                "/root",
-                json!({
-                    "dir1": {},
-                    "dir2": {
-                        "dir3": {}
-                    }
-                }),
-            )
-            .await;
-
-        let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
-        let workspace = cx
-            .add_window(|cx| Workspace::test_new(project, cx))
-            .root(cx);
-        let finder = cx
-            .add_window(|cx| {
-                Picker::new(
-                    FileFinderDelegate::new(
-                        workspace.downgrade(),
-                        workspace.read(cx).project().clone(),
-                        None,
-                        Vec::new(),
-                        cx,
-                    ),
-                    cx,
-                )
-            })
-            .root(cx);
-        finder
-            .update(cx, |f, cx| {
-                f.delegate_mut().spawn_search(test_path_like("dir"), cx)
-            })
-            .await;
-        cx.read(|cx| {
-            let finder = finder.read(cx);
-            assert_eq!(finder.delegate().matches.len(), 0);
-        });
-    }
-
-    #[gpui::test]
-    async fn test_query_history(
-        deterministic: Arc<gpui::executor::Deterministic>,
-        cx: &mut gpui::TestAppContext,
-    ) {
-        let app_state = init_test(cx);
-
-        app_state
-            .fs
-            .as_fake()
-            .insert_tree(
-                "/src",
-                json!({
-                    "test": {
-                        "first.rs": "// First Rust file",
-                        "second.rs": "// Second Rust file",
-                        "third.rs": "// Third Rust file",
-                    }
-                }),
-            )
-            .await;
-
-        let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
-        let window = cx.add_window(|cx| Workspace::test_new(project, cx));
-        let workspace = window.root(cx);
-        let worktree_id = cx.read(|cx| {
-            let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
-            assert_eq!(worktrees.len(), 1);
-            WorktreeId::from_usize(worktrees[0].id())
-        });
-
-        // Open and close panels, getting their history items afterwards.
-        // Ensure history items get populated with opened items, and items are kept in a certain order.
-        // The history lags one opened buffer behind, since it's updated in the search panel only on its reopen.
-        //
-        // TODO: without closing, the opened items do not propagate their history changes for some reason
-        // it does work in real app though, only tests do not propagate.
-
-        let initial_history = open_close_queried_buffer(
-            "fir",
-            1,
-            "first.rs",
-            window.into(),
-            &workspace,
-            &deterministic,
-            cx,
-        )
-        .await;
-        assert!(
-            initial_history.is_empty(),
-            "Should have no history before opening any files"
-        );
-
-        let history_after_first = open_close_queried_buffer(
-            "sec",
-            1,
-            "second.rs",
-            window.into(),
-            &workspace,
-            &deterministic,
-            cx,
-        )
-        .await;
-        assert_eq!(
-            history_after_first,
-            vec![FoundPath::new(
-                ProjectPath {
-                    worktree_id,
-                    path: Arc::from(Path::new("test/first.rs")),
-                },
-                Some(PathBuf::from("/src/test/first.rs"))
-            )],
-            "Should show 1st opened item in the history when opening the 2nd item"
-        );
-
-        let history_after_second = open_close_queried_buffer(
-            "thi",
-            1,
-            "third.rs",
-            window.into(),
-            &workspace,
-            &deterministic,
-            cx,
-        )
-        .await;
-        assert_eq!(
-            history_after_second,
-            vec![
-                FoundPath::new(
-                    ProjectPath {
-                        worktree_id,
-                        path: Arc::from(Path::new("test/second.rs")),
-                    },
-                    Some(PathBuf::from("/src/test/second.rs"))
-                ),
-                FoundPath::new(
-                    ProjectPath {
-                        worktree_id,
-                        path: Arc::from(Path::new("test/first.rs")),
-                    },
-                    Some(PathBuf::from("/src/test/first.rs"))
-                ),
-            ],
-            "Should show 1st and 2nd opened items in the history when opening the 3rd item. \
-2nd item should be the first in the history, as the last opened."
-        );
-
-        let history_after_third = open_close_queried_buffer(
-            "sec",
-            1,
-            "second.rs",
-            window.into(),
-            &workspace,
-            &deterministic,
-            cx,
-        )
-        .await;
-        assert_eq!(
-            history_after_third,
-            vec![
-                FoundPath::new(
-                    ProjectPath {
-                        worktree_id,
-                        path: Arc::from(Path::new("test/third.rs")),
-                    },
-                    Some(PathBuf::from("/src/test/third.rs"))
-                ),
-                FoundPath::new(
-                    ProjectPath {
-                        worktree_id,
-                        path: Arc::from(Path::new("test/second.rs")),
-                    },
-                    Some(PathBuf::from("/src/test/second.rs"))
-                ),
-                FoundPath::new(
-                    ProjectPath {
-                        worktree_id,
-                        path: Arc::from(Path::new("test/first.rs")),
-                    },
-                    Some(PathBuf::from("/src/test/first.rs"))
-                ),
-            ],
-            "Should show 1st, 2nd and 3rd opened items in the history when opening the 2nd item again. \
-3rd item should be the first in the history, as the last opened."
-        );
-
-        let history_after_second_again = open_close_queried_buffer(
-            "thi",
-            1,
-            "third.rs",
-            window.into(),
-            &workspace,
-            &deterministic,
-            cx,
-        )
-        .await;
-        assert_eq!(
-            history_after_second_again,
-            vec![
-                FoundPath::new(
-                    ProjectPath {
-                        worktree_id,
-                        path: Arc::from(Path::new("test/second.rs")),
-                    },
-                    Some(PathBuf::from("/src/test/second.rs"))
-                ),
-                FoundPath::new(
-                    ProjectPath {
-                        worktree_id,
-                        path: Arc::from(Path::new("test/third.rs")),
-                    },
-                    Some(PathBuf::from("/src/test/third.rs"))
-                ),
-                FoundPath::new(
-                    ProjectPath {
-                        worktree_id,
-                        path: Arc::from(Path::new("test/first.rs")),
-                    },
-                    Some(PathBuf::from("/src/test/first.rs"))
-                ),
-            ],
-            "Should show 1st, 2nd and 3rd opened items in the history when opening the 3rd item again. \
-2nd item, as the last opened, 3rd item should go next as it was opened right before."
-        );
-    }
-
-    #[gpui::test]
-    async fn test_external_files_history(
-        deterministic: Arc<gpui::executor::Deterministic>,
-        cx: &mut gpui::TestAppContext,
-    ) {
-        let app_state = init_test(cx);
-
-        app_state
-            .fs
-            .as_fake()
-            .insert_tree(
-                "/src",
-                json!({
-                    "test": {
-                        "first.rs": "// First Rust file",
-                        "second.rs": "// Second Rust file",
-                    }
-                }),
-            )
-            .await;
-
-        app_state
-            .fs
-            .as_fake()
-            .insert_tree(
-                "/external-src",
-                json!({
-                    "test": {
-                        "third.rs": "// Third Rust file",
-                        "fourth.rs": "// Fourth Rust file",
-                    }
-                }),
-            )
-            .await;
-
-        let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
-        cx.update(|cx| {
-            project.update(cx, |project, cx| {
-                project.find_or_create_local_worktree("/external-src", false, cx)
-            })
-        })
-        .detach();
-        deterministic.run_until_parked();
-
-        let window = cx.add_window(|cx| Workspace::test_new(project, cx));
-        let workspace = window.root(cx);
-        let worktree_id = cx.read(|cx| {
-            let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
-            assert_eq!(worktrees.len(), 1,);
-
-            WorktreeId::from_usize(worktrees[0].id())
-        });
-        workspace
-            .update(cx, |workspace, cx| {
-                workspace.open_abs_path(PathBuf::from("/external-src/test/third.rs"), false, cx)
-            })
-            .detach();
-        deterministic.run_until_parked();
-        let external_worktree_id = cx.read(|cx| {
-            let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
-            assert_eq!(
-                worktrees.len(),
-                2,
-                "External file should get opened in a new worktree"
-            );
-
-            WorktreeId::from_usize(
-                worktrees
-                    .into_iter()
-                    .find(|worktree| worktree.id() != worktree_id.to_usize())
-                    .expect("New worktree should have a different id")
-                    .id(),
-            )
-        });
-        close_active_item(&workspace, &deterministic, cx).await;
-
-        let initial_history_items = open_close_queried_buffer(
-            "sec",
-            1,
-            "second.rs",
-            window.into(),
-            &workspace,
-            &deterministic,
-            cx,
-        )
-        .await;
-        assert_eq!(
-            initial_history_items,
-            vec![FoundPath::new(
-                ProjectPath {
-                    worktree_id: external_worktree_id,
-                    path: Arc::from(Path::new("")),
-                },
-                Some(PathBuf::from("/external-src/test/third.rs"))
-            )],
-            "Should show external file with its full path in the history after it was open"
-        );
-
-        let updated_history_items = open_close_queried_buffer(
-            "fir",
-            1,
-            "first.rs",
-            window.into(),
-            &workspace,
-            &deterministic,
-            cx,
-        )
-        .await;
-        assert_eq!(
-            updated_history_items,
-            vec![
-                FoundPath::new(
-                    ProjectPath {
-                        worktree_id,
-                        path: Arc::from(Path::new("test/second.rs")),
-                    },
-                    Some(PathBuf::from("/src/test/second.rs"))
-                ),
-                FoundPath::new(
-                    ProjectPath {
-                        worktree_id: external_worktree_id,
-                        path: Arc::from(Path::new("")),
-                    },
-                    Some(PathBuf::from("/external-src/test/third.rs"))
-                ),
-            ],
-            "Should keep external file with history updates",
-        );
-    }
-
-    #[gpui::test]
-    async fn test_toggle_panel_new_selections(
-        deterministic: Arc<gpui::executor::Deterministic>,
-        cx: &mut gpui::TestAppContext,
-    ) {
-        let app_state = init_test(cx);
-
-        app_state
-            .fs
-            .as_fake()
-            .insert_tree(
-                "/src",
-                json!({
-                    "test": {
-                        "first.rs": "// First Rust file",
-                        "second.rs": "// Second Rust file",
-                        "third.rs": "// Third Rust file",
-                    }
-                }),
-            )
-            .await;
-
-        let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
-        let window = cx.add_window(|cx| Workspace::test_new(project, cx));
-        let workspace = window.root(cx);
-
-        // generate some history to select from
-        open_close_queried_buffer(
-            "fir",
-            1,
-            "first.rs",
-            window.into(),
-            &workspace,
-            &deterministic,
-            cx,
-        )
-        .await;
-        open_close_queried_buffer(
-            "sec",
-            1,
-            "second.rs",
-            window.into(),
-            &workspace,
-            &deterministic,
-            cx,
-        )
-        .await;
-        open_close_queried_buffer(
-            "thi",
-            1,
-            "third.rs",
-            window.into(),
-            &workspace,
-            &deterministic,
-            cx,
-        )
-        .await;
-        let current_history = open_close_queried_buffer(
-            "sec",
-            1,
-            "second.rs",
-            window.into(),
-            &workspace,
-            &deterministic,
-            cx,
-        )
-        .await;
-
-        for expected_selected_index in 0..current_history.len() {
-            cx.dispatch_action(window.into(), Toggle);
-            let selected_index = cx.read(|cx| {
-                workspace
-                    .read(cx)
-                    .modal::<FileFinder>()
-                    .unwrap()
-                    .read(cx)
-                    .delegate()
-                    .selected_index()
-            });
-            assert_eq!(
-                selected_index, expected_selected_index,
-                "Should select the next item in the history"
-            );
-        }
-
-        cx.dispatch_action(window.into(), Toggle);
-        let selected_index = cx.read(|cx| {
-            workspace
-                .read(cx)
-                .modal::<FileFinder>()
-                .unwrap()
-                .read(cx)
-                .delegate()
-                .selected_index()
-        });
-        assert_eq!(
-            selected_index, 0,
-            "Should wrap around the history and start all over"
-        );
-    }
-
-    #[gpui::test]
-    async fn test_search_preserves_history_items(
-        deterministic: Arc<gpui::executor::Deterministic>,
-        cx: &mut gpui::TestAppContext,
-    ) {
-        let app_state = init_test(cx);
-
-        app_state
-            .fs
-            .as_fake()
-            .insert_tree(
-                "/src",
-                json!({
-                    "test": {
-                        "first.rs": "// First Rust file",
-                        "second.rs": "// Second Rust file",
-                        "third.rs": "// Third Rust file",
-                        "fourth.rs": "// Fourth Rust file",
-                    }
-                }),
-            )
-            .await;
-
-        let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
-        let window = cx.add_window(|cx| Workspace::test_new(project, cx));
-        let workspace = window.root(cx);
-        let worktree_id = cx.read(|cx| {
-            let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
-            assert_eq!(worktrees.len(), 1,);
-
-            WorktreeId::from_usize(worktrees[0].id())
-        });
-
-        // generate some history to select from
-        open_close_queried_buffer(
-            "fir",
-            1,
-            "first.rs",
-            window.into(),
-            &workspace,
-            &deterministic,
-            cx,
-        )
-        .await;
-        open_close_queried_buffer(
-            "sec",
-            1,
-            "second.rs",
-            window.into(),
-            &workspace,
-            &deterministic,
-            cx,
-        )
-        .await;
-        open_close_queried_buffer(
-            "thi",
-            1,
-            "third.rs",
-            window.into(),
-            &workspace,
-            &deterministic,
-            cx,
-        )
-        .await;
-        open_close_queried_buffer(
-            "sec",
-            1,
-            "second.rs",
-            window.into(),
-            &workspace,
-            &deterministic,
-            cx,
-        )
-        .await;
-
-        cx.dispatch_action(window.into(), Toggle);
-        let first_query = "f";
-        let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
-        finder
-            .update(cx, |finder, cx| {
-                finder
-                    .delegate_mut()
-                    .update_matches(first_query.to_string(), cx)
-            })
-            .await;
-        finder.read_with(cx, |finder, _| {
-            let delegate = finder.delegate();
-            assert_eq!(delegate.matches.history.len(), 1, "Only one history item contains {first_query}, it should be present and others should be filtered out");
-            let history_match = delegate.matches.history.first().unwrap();
-            assert!(history_match.1.is_some(), "Should have path matches for history items after querying");
-            assert_eq!(history_match.0, FoundPath::new(
-                ProjectPath {
-                    worktree_id,
-                    path: Arc::from(Path::new("test/first.rs")),
-                },
-                Some(PathBuf::from("/src/test/first.rs"))
-            ));
-            assert_eq!(delegate.matches.search.len(), 1, "Only one non-history item contains {first_query}, it should be present");
-            assert_eq!(delegate.matches.search.first().unwrap().path.as_ref(), Path::new("test/fourth.rs"));
-        });
-
-        let second_query = "fsdasdsa";
-        let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
-        finder
-            .update(cx, |finder, cx| {
-                finder
-                    .delegate_mut()
-                    .update_matches(second_query.to_string(), cx)
-            })
-            .await;
-        finder.read_with(cx, |finder, _| {
-            let delegate = finder.delegate();
-            assert!(
-                delegate.matches.history.is_empty(),
-                "No history entries should match {second_query}"
-            );
-            assert!(
-                delegate.matches.search.is_empty(),
-                "No search entries should match {second_query}"
-            );
-        });
-
-        let first_query_again = first_query;
-        let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
-        finder
-            .update(cx, |finder, cx| {
-                finder
-                    .delegate_mut()
-                    .update_matches(first_query_again.to_string(), cx)
-            })
-            .await;
-        finder.read_with(cx, |finder, _| {
-            let delegate = finder.delegate();
-            assert_eq!(delegate.matches.history.len(), 1, "Only one history item contains {first_query_again}, it should be present and others should be filtered out, even after non-matching query");
-            let history_match = delegate.matches.history.first().unwrap();
-            assert!(history_match.1.is_some(), "Should have path matches for history items after querying");
-            assert_eq!(history_match.0, FoundPath::new(
-                ProjectPath {
-                    worktree_id,
-                    path: Arc::from(Path::new("test/first.rs")),
-                },
-                Some(PathBuf::from("/src/test/first.rs"))
-            ));
-            assert_eq!(delegate.matches.search.len(), 1, "Only one non-history item contains {first_query_again}, it should be present, even after non-matching query");
-            assert_eq!(delegate.matches.search.first().unwrap().path.as_ref(), Path::new("test/fourth.rs"));
-        });
-    }
-
-    #[gpui::test]
-    async fn test_history_items_vs_very_good_external_match(
-        deterministic: Arc<gpui::executor::Deterministic>,
-        cx: &mut gpui::TestAppContext,
-    ) {
-        let app_state = init_test(cx);
-
-        app_state
-            .fs
-            .as_fake()
-            .insert_tree(
-                "/src",
-                json!({
-                    "collab_ui": {
-                        "first.rs": "// First Rust file",
-                        "second.rs": "// Second Rust file",
-                        "third.rs": "// Third Rust file",
-                        "collab_ui.rs": "// Fourth Rust file",
-                    }
-                }),
-            )
-            .await;
-
-        let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
-        let window = cx.add_window(|cx| Workspace::test_new(project, cx));
-        let workspace = window.root(cx);
-        // generate some history to select from
-        open_close_queried_buffer(
-            "fir",
-            1,
-            "first.rs",
-            window.into(),
-            &workspace,
-            &deterministic,
-            cx,
-        )
-        .await;
-        open_close_queried_buffer(
-            "sec",
-            1,
-            "second.rs",
-            window.into(),
-            &workspace,
-            &deterministic,
-            cx,
-        )
-        .await;
-        open_close_queried_buffer(
-            "thi",
-            1,
-            "third.rs",
-            window.into(),
-            &workspace,
-            &deterministic,
-            cx,
-        )
-        .await;
-        open_close_queried_buffer(
-            "sec",
-            1,
-            "second.rs",
-            window.into(),
-            &workspace,
-            &deterministic,
-            cx,
-        )
-        .await;
-
-        cx.dispatch_action(window.into(), Toggle);
-        let query = "collab_ui";
-        let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
-        finder
-            .update(cx, |finder, cx| {
-                finder.delegate_mut().update_matches(query.to_string(), cx)
-            })
-            .await;
-        finder.read_with(cx, |finder, _| {
-            let delegate = finder.delegate();
-            assert!(
-                delegate.matches.history.is_empty(),
-                "History items should not math query {query}, they should be matched by name only"
-            );
-
-            let search_entries = delegate
-                .matches
-                .search
-                .iter()
-                .map(|path_match| path_match.path.to_path_buf())
-                .collect::<Vec<_>>();
-            assert_eq!(
-                search_entries,
-                vec![
-                    PathBuf::from("collab_ui/collab_ui.rs"),
-                    PathBuf::from("collab_ui/third.rs"),
-                    PathBuf::from("collab_ui/first.rs"),
-                    PathBuf::from("collab_ui/second.rs"),
-                ],
-                "Despite all search results having the same directory name, the most matching one should be on top"
-            );
-        });
-    }
-
-    #[gpui::test]
-    async fn test_nonexistent_history_items_not_shown(
-        deterministic: Arc<gpui::executor::Deterministic>,
-        cx: &mut gpui::TestAppContext,
-    ) {
-        let app_state = init_test(cx);
-
-        app_state
-            .fs
-            .as_fake()
-            .insert_tree(
-                "/src",
-                json!({
-                    "test": {
-                        "first.rs": "// First Rust file",
-                        "nonexistent.rs": "// Second Rust file",
-                        "third.rs": "// Third Rust file",
-                    }
-                }),
-            )
-            .await;
-
-        let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
-        let window = cx.add_window(|cx| Workspace::test_new(project, cx));
-        let workspace = window.root(cx);
-        // generate some history to select from
-        open_close_queried_buffer(
-            "fir",
-            1,
-            "first.rs",
-            window.into(),
-            &workspace,
-            &deterministic,
-            cx,
-        )
-        .await;
-        open_close_queried_buffer(
-            "non",
-            1,
-            "nonexistent.rs",
-            window.into(),
-            &workspace,
-            &deterministic,
-            cx,
-        )
-        .await;
-        open_close_queried_buffer(
-            "thi",
-            1,
-            "third.rs",
-            window.into(),
-            &workspace,
-            &deterministic,
-            cx,
-        )
-        .await;
-        open_close_queried_buffer(
-            "fir",
-            1,
-            "first.rs",
-            window.into(),
-            &workspace,
-            &deterministic,
-            cx,
-        )
-        .await;
-
-        cx.dispatch_action(window.into(), Toggle);
-        let query = "rs";
-        let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
-        finder
-            .update(cx, |finder, cx| {
-                finder.delegate_mut().update_matches(query.to_string(), cx)
-            })
-            .await;
-        finder.read_with(cx, |finder, _| {
-            let delegate = finder.delegate();
-            let history_entries = delegate
-                .matches
-                .history
-                .iter()
-                .map(|(_, path_match)| path_match.as_ref().expect("should have a path match").path.to_path_buf())
-                .collect::<Vec<_>>();
-            assert_eq!(
-                history_entries,
-                vec![
-                    PathBuf::from("test/first.rs"),
-                    PathBuf::from("test/third.rs"),
-                ],
-                "Should have all opened files in the history, except the ones that do not exist on disk"
-            );
-        });
-    }
-
-    async fn open_close_queried_buffer(
-        input: &str,
-        expected_matches: usize,
-        expected_editor_title: &str,
-        window: gpui::AnyWindowHandle,
-        workspace: &ViewHandle<Workspace>,
-        deterministic: &gpui::executor::Deterministic,
-        cx: &mut gpui::TestAppContext,
-    ) -> Vec<FoundPath> {
-        cx.dispatch_action(window, Toggle);
-        let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
-        finder
-            .update(cx, |finder, cx| {
-                finder.delegate_mut().update_matches(input.to_string(), cx)
-            })
-            .await;
-        let history_items = finder.read_with(cx, |finder, _| {
-            assert_eq!(
-                finder.delegate().matches.len(),
-                expected_matches,
-                "Unexpected number of matches found for query {input}"
-            );
-            finder.delegate().history_items.clone()
-        });
-
-        let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone());
-        cx.dispatch_action(window, SelectNext);
-        cx.dispatch_action(window, Confirm);
-        deterministic.run_until_parked();
-        active_pane
-            .condition(cx, |pane, _| pane.active_item().is_some())
-            .await;
-        cx.read(|cx| {
-            let active_item = active_pane.read(cx).active_item().unwrap();
-            let active_editor_title = active_item
-                .as_any()
-                .downcast_ref::<Editor>()
-                .unwrap()
-                .read(cx)
-                .title(cx);
-            assert_eq!(
-                expected_editor_title, active_editor_title,
-                "Unexpected editor title for query {input}"
-            );
-        });
-
-        close_active_item(workspace, deterministic, cx).await;
-
-        history_items
-    }
-
-    async fn close_active_item(
-        workspace: &ViewHandle<Workspace>,
-        deterministic: &gpui::executor::Deterministic,
-        cx: &mut TestAppContext,
-    ) {
-        let mut original_items = HashMap::new();
-        cx.read(|cx| {
-            for pane in workspace.read(cx).panes() {
-                let pane_id = pane.id();
-                let pane = pane.read(cx);
-                let insertion_result = original_items.insert(pane_id, pane.items().count());
-                assert!(insertion_result.is_none(), "Pane id {pane_id} collision");
-            }
-        });
-
-        let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone());
-        active_pane
-            .update(cx, |pane, cx| {
-                pane.close_active_item(&workspace::CloseActiveItem { save_intent: None }, cx)
-                    .unwrap()
-            })
-            .await
-            .unwrap();
-        deterministic.run_until_parked();
-        cx.read(|cx| {
-            for pane in workspace.read(cx).panes() {
-                let pane_id = pane.id();
-                let pane = pane.read(cx);
-                match original_items.remove(&pane_id) {
-                    Some(original_items) => {
-                        assert_eq!(
-                            pane.items().count(),
-                            original_items.saturating_sub(1),
-                            "Pane id {pane_id} should have item closed"
-                        );
-                    }
-                    None => panic!("Pane id {pane_id} not found in original items"),
-                }
-            }
-        });
-        assert!(
-            original_items.len() <= 1,
-            "At most one panel should got closed"
-        );
-    }
-
-    fn init_test(cx: &mut TestAppContext) -> Arc<AppState> {
-        cx.foreground().forbid_parking();
-        cx.update(|cx| {
-            let state = AppState::test(cx);
-            theme::init((), cx);
-            language::init(cx);
-            super::init(cx);
-            editor::init(cx);
-            workspace::init_settings(cx);
-            Project::init_settings(cx);
-            state
-        })
-    }
-
-    fn test_path_like(test_str: &str) -> PathLikeWithPosition<FileSearchQuery> {
-        PathLikeWithPosition::parse_str(test_str, |path_like_str| {
-            Ok::<_, std::convert::Infallible>(FileSearchQuery {
-                raw_query: test_str.to_owned(),
-                file_query_end: if path_like_str == test_str {
-                    None
-                } else {
-                    Some(path_like_str.len())
-                },
-            })
-        })
-        .unwrap()
-    }
-
-    fn dummy_found_path(project_path: ProjectPath) -> FoundPath {
-        FoundPath {
-            project: project_path,
-            absolute: None,
-        }
     }
 }
+
+// #[cfg(test)]
+// mod tests {
+//     use std::{assert_eq, collections::HashMap, path::Path, time::Duration};
+
+//     use super::*;
+//     use editor::Editor;
+//     use gpui::{TestAppContext, ViewHandle};
+//     use menu::{Confirm, SelectNext};
+//     use serde_json::json;
+//     use workspace::{AppState, Workspace};
+
+//     #[ctor::ctor]
+//     fn init_logger() {
+//         if std::env::var("RUST_LOG").is_ok() {
+//             env_logger::init();
+//         }
+//     }
+
+//     #[gpui::test]
+//     async fn test_matching_paths(cx: &mut TestAppContext) {
+//         let app_state = init_test(cx);
+//         app_state
+//             .fs
+//             .as_fake()
+//             .insert_tree(
+//                 "/root",
+//                 json!({
+//                     "a": {
+//                         "banana": "",
+//                         "bandana": "",
+//                     }
+//                 }),
+//             )
+//             .await;
+
+//         let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
+//         let window = cx.add_window(|cx| Workspace::test_new(project, cx));
+//         let workspace = window.root(cx);
+//         cx.dispatch_action(window.into(), Toggle);
+
+//         let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
+//         finder
+//             .update(cx, |finder, cx| {
+//                 finder.delegate_mut().update_matches("bna".to_string(), cx)
+//             })
+//             .await;
+//         finder.read_with(cx, |finder, _| {
+//             assert_eq!(finder.delegate().matches.len(), 2);
+//         });
+
+//         let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone());
+//         cx.dispatch_action(window.into(), SelectNext);
+//         cx.dispatch_action(window.into(), Confirm);
+//         active_pane
+//             .condition(cx, |pane, _| pane.active_item().is_some())
+//             .await;
+//         cx.read(|cx| {
+//             let active_item = active_pane.read(cx).active_item().unwrap();
+//             assert_eq!(
+//                 active_item
+//                     .as_any()
+//                     .downcast_ref::<Editor>()
+//                     .unwrap()
+//                     .read(cx)
+//                     .title(cx),
+//                 "bandana"
+//             );
+//         });
+//     }
+
+//     #[gpui::test]
+//     async fn test_row_column_numbers_query_inside_file(cx: &mut TestAppContext) {
+//         let app_state = init_test(cx);
+
+//         let first_file_name = "first.rs";
+//         let first_file_contents = "// First Rust file";
+//         app_state
+//             .fs
+//             .as_fake()
+//             .insert_tree(
+//                 "/src",
+//                 json!({
+//                     "test": {
+//                         first_file_name: first_file_contents,
+//                         "second.rs": "// Second Rust file",
+//                     }
+//                 }),
+//             )
+//             .await;
+
+//         let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
+//         let window = cx.add_window(|cx| Workspace::test_new(project, cx));
+//         let workspace = window.root(cx);
+//         cx.dispatch_action(window.into(), Toggle);
+//         let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
+
+//         let file_query = &first_file_name[..3];
+//         let file_row = 1;
+//         let file_column = 3;
+//         assert!(file_column <= first_file_contents.len());
+//         let query_inside_file = format!("{file_query}:{file_row}:{file_column}");
+//         finder
+//             .update(cx, |finder, cx| {
+//                 finder
+//                     .delegate_mut()
+//                     .update_matches(query_inside_file.to_string(), cx)
+//             })
+//             .await;
+//         finder.read_with(cx, |finder, _| {
+//             let finder = finder.delegate();
+//             assert_eq!(finder.matches.len(), 1);
+//             let latest_search_query = finder
+//                 .latest_search_query
+//                 .as_ref()
+//                 .expect("Finder should have a query after the update_matches call");
+//             assert_eq!(latest_search_query.path_like.raw_query, query_inside_file);
+//             assert_eq!(
+//                 latest_search_query.path_like.file_query_end,
+//                 Some(file_query.len())
+//             );
+//             assert_eq!(latest_search_query.row, Some(file_row));
+//             assert_eq!(latest_search_query.column, Some(file_column as u32));
+//         });
+
+//         let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone());
+//         cx.dispatch_action(window.into(), SelectNext);
+//         cx.dispatch_action(window.into(), Confirm);
+//         active_pane
+//             .condition(cx, |pane, _| pane.active_item().is_some())
+//             .await;
+//         let editor = cx.update(|cx| {
+//             let active_item = active_pane.read(cx).active_item().unwrap();
+//             active_item.downcast::<Editor>().unwrap()
+//         });
+//         cx.foreground().advance_clock(Duration::from_secs(2));
+//         cx.foreground().start_waiting();
+//         cx.foreground().finish_waiting();
+//         editor.update(cx, |editor, cx| {
+//             let all_selections = editor.selections.all_adjusted(cx);
+//             assert_eq!(
+//                 all_selections.len(),
+//                 1,
+//                 "Expected to have 1 selection (caret) after file finder confirm, but got: {all_selections:?}"
+//             );
+//             let caret_selection = all_selections.into_iter().next().unwrap();
+//             assert_eq!(caret_selection.start, caret_selection.end,
+//                 "Caret selection should have its start and end at the same position");
+//             assert_eq!(file_row, caret_selection.start.row + 1,
+//                 "Query inside file should get caret with the same focus row");
+//             assert_eq!(file_column, caret_selection.start.column as usize + 1,
+//                 "Query inside file should get caret with the same focus column");
+//         });
+//     }
+
+//     #[gpui::test]
+//     async fn test_row_column_numbers_query_outside_file(cx: &mut TestAppContext) {
+//         let app_state = init_test(cx);
+
+//         let first_file_name = "first.rs";
+//         let first_file_contents = "// First Rust file";
+//         app_state
+//             .fs
+//             .as_fake()
+//             .insert_tree(
+//                 "/src",
+//                 json!({
+//                     "test": {
+//                         first_file_name: first_file_contents,
+//                         "second.rs": "// Second Rust file",
+//                     }
+//                 }),
+//             )
+//             .await;
+
+//         let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
+//         let window = cx.add_window(|cx| Workspace::test_new(project, cx));
+//         let workspace = window.root(cx);
+//         cx.dispatch_action(window.into(), Toggle);
+//         let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
+
+//         let file_query = &first_file_name[..3];
+//         let file_row = 200;
+//         let file_column = 300;
+//         assert!(file_column > first_file_contents.len());
+//         let query_outside_file = format!("{file_query}:{file_row}:{file_column}");
+//         finder
+//             .update(cx, |finder, cx| {
+//                 finder
+//                     .delegate_mut()
+//                     .update_matches(query_outside_file.to_string(), cx)
+//             })
+//             .await;
+//         finder.read_with(cx, |finder, _| {
+//             let finder = finder.delegate();
+//             assert_eq!(finder.matches.len(), 1);
+//             let latest_search_query = finder
+//                 .latest_search_query
+//                 .as_ref()
+//                 .expect("Finder should have a query after the update_matches call");
+//             assert_eq!(latest_search_query.path_like.raw_query, query_outside_file);
+//             assert_eq!(
+//                 latest_search_query.path_like.file_query_end,
+//                 Some(file_query.len())
+//             );
+//             assert_eq!(latest_search_query.row, Some(file_row));
+//             assert_eq!(latest_search_query.column, Some(file_column as u32));
+//         });
+
+//         let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone());
+//         cx.dispatch_action(window.into(), SelectNext);
+//         cx.dispatch_action(window.into(), Confirm);
+//         active_pane
+//             .condition(cx, |pane, _| pane.active_item().is_some())
+//             .await;
+//         let editor = cx.update(|cx| {
+//             let active_item = active_pane.read(cx).active_item().unwrap();
+//             active_item.downcast::<Editor>().unwrap()
+//         });
+//         cx.foreground().advance_clock(Duration::from_secs(2));
+//         cx.foreground().start_waiting();
+//         cx.foreground().finish_waiting();
+//         editor.update(cx, |editor, cx| {
+//             let all_selections = editor.selections.all_adjusted(cx);
+//             assert_eq!(
+//                 all_selections.len(),
+//                 1,
+//                 "Expected to have 1 selection (caret) after file finder confirm, but got: {all_selections:?}"
+//             );
+//             let caret_selection = all_selections.into_iter().next().unwrap();
+//             assert_eq!(caret_selection.start, caret_selection.end,
+//                 "Caret selection should have its start and end at the same position");
+//             assert_eq!(0, caret_selection.start.row,
+//                 "Excessive rows (as in query outside file borders) should get trimmed to last file row");
+//             assert_eq!(first_file_contents.len(), caret_selection.start.column as usize,
+//                 "Excessive columns (as in query outside file borders) should get trimmed to selected row's last column");
+//         });
+//     }
+
+//     #[gpui::test]
+//     async fn test_matching_cancellation(cx: &mut TestAppContext) {
+//         let app_state = init_test(cx);
+//         app_state
+//             .fs
+//             .as_fake()
+//             .insert_tree(
+//                 "/dir",
+//                 json!({
+//                     "hello": "",
+//                     "goodbye": "",
+//                     "halogen-light": "",
+//                     "happiness": "",
+//                     "height": "",
+//                     "hi": "",
+//                     "hiccup": "",
+//                 }),
+//             )
+//             .await;
+
+//         let project = Project::test(app_state.fs.clone(), ["/dir".as_ref()], cx).await;
+//         let workspace = cx
+//             .add_window(|cx| Workspace::test_new(project, cx))
+//             .root(cx);
+//         let finder = cx
+//             .add_window(|cx| {
+//                 Picker::new(
+//                     FileFinderDelegate::new(
+//                         workspace.downgrade(),
+//                         workspace.read(cx).project().clone(),
+//                         None,
+//                         Vec::new(),
+//                         cx,
+//                     ),
+//                     cx,
+//                 )
+//             })
+//             .root(cx);
+
+//         let query = test_path_like("hi");
+//         finder
+//             .update(cx, |f, cx| f.delegate_mut().spawn_search(query.clone(), cx))
+//             .await;
+//         finder.read_with(cx, |f, _| assert_eq!(f.delegate().matches.len(), 5));
+
+//         finder.update(cx, |finder, cx| {
+//             let delegate = finder.delegate_mut();
+//             assert!(
+//                 delegate.matches.history.is_empty(),
+//                 "Search matches expected"
+//             );
+//             let matches = delegate.matches.search.clone();
+
+//             // Simulate a search being cancelled after the time limit,
+//             // returning only a subset of the matches that would have been found.
+//             drop(delegate.spawn_search(query.clone(), cx));
+//             delegate.set_search_matches(
+//                 delegate.latest_search_id,
+//                 true, // did-cancel
+//                 query.clone(),
+//                 vec![matches[1].clone(), matches[3].clone()],
+//                 cx,
+//             );
+
+//             // Simulate another cancellation.
+//             drop(delegate.spawn_search(query.clone(), cx));
+//             delegate.set_search_matches(
+//                 delegate.latest_search_id,
+//                 true, // did-cancel
+//                 query.clone(),
+//                 vec![matches[0].clone(), matches[2].clone(), matches[3].clone()],
+//                 cx,
+//             );
+
+//             assert!(
+//                 delegate.matches.history.is_empty(),
+//                 "Search matches expected"
+//             );
+//             assert_eq!(delegate.matches.search.as_slice(), &matches[0..4]);
+//         });
+//     }
+
+//     #[gpui::test]
+//     async fn test_ignored_files(cx: &mut TestAppContext) {
+//         let app_state = init_test(cx);
+//         app_state
+//             .fs
+//             .as_fake()
+//             .insert_tree(
+//                 "/ancestor",
+//                 json!({
+//                     ".gitignore": "ignored-root",
+//                     "ignored-root": {
+//                         "happiness": "",
+//                         "height": "",
+//                         "hi": "",
+//                         "hiccup": "",
+//                     },
+//                     "tracked-root": {
+//                         ".gitignore": "height",
+//                         "happiness": "",
+//                         "height": "",
+//                         "hi": "",
+//                         "hiccup": "",
+//                     },
+//                 }),
+//             )
+//             .await;
+
+//         let project = Project::test(
+//             app_state.fs.clone(),
+//             [
+//                 "/ancestor/tracked-root".as_ref(),
+//                 "/ancestor/ignored-root".as_ref(),
+//             ],
+//             cx,
+//         )
+//         .await;
+//         let workspace = cx
+//             .add_window(|cx| Workspace::test_new(project, cx))
+//             .root(cx);
+//         let finder = cx
+//             .add_window(|cx| {
+//                 Picker::new(
+//                     FileFinderDelegate::new(
+//                         workspace.downgrade(),
+//                         workspace.read(cx).project().clone(),
+//                         None,
+//                         Vec::new(),
+//                         cx,
+//                     ),
+//                     cx,
+//                 )
+//             })
+//             .root(cx);
+//         finder
+//             .update(cx, |f, cx| {
+//                 f.delegate_mut().spawn_search(test_path_like("hi"), cx)
+//             })
+//             .await;
+//         finder.read_with(cx, |f, _| assert_eq!(f.delegate().matches.len(), 7));
+//     }
+
+//     #[gpui::test]
+//     async fn test_single_file_worktrees(cx: &mut TestAppContext) {
+//         let app_state = init_test(cx);
+//         app_state
+//             .fs
+//             .as_fake()
+//             .insert_tree("/root", json!({ "the-parent-dir": { "the-file": "" } }))
+//             .await;
+
+//         let project = Project::test(
+//             app_state.fs.clone(),
+//             ["/root/the-parent-dir/the-file".as_ref()],
+//             cx,
+//         )
+//         .await;
+//         let workspace = cx
+//             .add_window(|cx| Workspace::test_new(project, cx))
+//             .root(cx);
+//         let finder = cx
+//             .add_window(|cx| {
+//                 Picker::new(
+//                     FileFinderDelegate::new(
+//                         workspace.downgrade(),
+//                         workspace.read(cx).project().clone(),
+//                         None,
+//                         Vec::new(),
+//                         cx,
+//                     ),
+//                     cx,
+//                 )
+//             })
+//             .root(cx);
+
+//         // Even though there is only one worktree, that worktree's filename
+//         // is included in the matching, because the worktree is a single file.
+//         finder
+//             .update(cx, |f, cx| {
+//                 f.delegate_mut().spawn_search(test_path_like("thf"), cx)
+//             })
+//             .await;
+//         cx.read(|cx| {
+//             let finder = finder.read(cx);
+//             let delegate = finder.delegate();
+//             assert!(
+//                 delegate.matches.history.is_empty(),
+//                 "Search matches expected"
+//             );
+//             let matches = delegate.matches.search.clone();
+//             assert_eq!(matches.len(), 1);
+
+//             let (file_name, file_name_positions, full_path, full_path_positions) =
+//                 delegate.labels_for_path_match(&matches[0]);
+//             assert_eq!(file_name, "the-file");
+//             assert_eq!(file_name_positions, &[0, 1, 4]);
+//             assert_eq!(full_path, "the-file");
+//             assert_eq!(full_path_positions, &[0, 1, 4]);
+//         });
+
+//         // Since the worktree root is a file, searching for its name followed by a slash does
+//         // not match anything.
+//         finder
+//             .update(cx, |f, cx| {
+//                 f.delegate_mut().spawn_search(test_path_like("thf/"), cx)
+//             })
+//             .await;
+//         finder.read_with(cx, |f, _| assert_eq!(f.delegate().matches.len(), 0));
+//     }
+
+//     #[gpui::test]
+//     async fn test_path_distance_ordering(cx: &mut TestAppContext) {
+//         let app_state = init_test(cx);
+//         app_state
+//             .fs
+//             .as_fake()
+//             .insert_tree(
+//                 "/root",
+//                 json!({
+//                     "dir1": { "a.txt": "" },
+//                     "dir2": {
+//                         "a.txt": "",
+//                         "b.txt": ""
+//                     }
+//                 }),
+//             )
+//             .await;
+
+//         let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
+//         let workspace = cx
+//             .add_window(|cx| Workspace::test_new(project, cx))
+//             .root(cx);
+//         let worktree_id = cx.read(|cx| {
+//             let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
+//             assert_eq!(worktrees.len(), 1);
+//             WorktreeId::from_usize(worktrees[0].id())
+//         });
+
+//         // When workspace has an active item, sort items which are closer to that item
+//         // first when they have the same name. In this case, b.txt is closer to dir2's a.txt
+//         // so that one should be sorted earlier
+//         let b_path = Some(dummy_found_path(ProjectPath {
+//             worktree_id,
+//             path: Arc::from(Path::new("/root/dir2/b.txt")),
+//         }));
+//         let finder = cx
+//             .add_window(|cx| {
+//                 Picker::new(
+//                     FileFinderDelegate::new(
+//                         workspace.downgrade(),
+//                         workspace.read(cx).project().clone(),
+//                         b_path,
+//                         Vec::new(),
+//                         cx,
+//                     ),
+//                     cx,
+//                 )
+//             })
+//             .root(cx);
+
+//         finder
+//             .update(cx, |f, cx| {
+//                 f.delegate_mut().spawn_search(test_path_like("a.txt"), cx)
+//             })
+//             .await;
+
+//         finder.read_with(cx, |f, _| {
+//             let delegate = f.delegate();
+//             assert!(
+//                 delegate.matches.history.is_empty(),
+//                 "Search matches expected"
+//             );
+//             let matches = delegate.matches.search.clone();
+//             assert_eq!(matches[0].path.as_ref(), Path::new("dir2/a.txt"));
+//             assert_eq!(matches[1].path.as_ref(), Path::new("dir1/a.txt"));
+//         });
+//     }
+
+//     #[gpui::test]
+//     async fn test_search_worktree_without_files(cx: &mut TestAppContext) {
+//         let app_state = init_test(cx);
+//         app_state
+//             .fs
+//             .as_fake()
+//             .insert_tree(
+//                 "/root",
+//                 json!({
+//                     "dir1": {},
+//                     "dir2": {
+//                         "dir3": {}
+//                     }
+//                 }),
+//             )
+//             .await;
+
+//         let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
+//         let workspace = cx
+//             .add_window(|cx| Workspace::test_new(project, cx))
+//             .root(cx);
+//         let finder = cx
+//             .add_window(|cx| {
+//                 Picker::new(
+//                     FileFinderDelegate::new(
+//                         workspace.downgrade(),
+//                         workspace.read(cx).project().clone(),
+//                         None,
+//                         Vec::new(),
+//                         cx,
+//                     ),
+//                     cx,
+//                 )
+//             })
+//             .root(cx);
+//         finder
+//             .update(cx, |f, cx| {
+//                 f.delegate_mut().spawn_search(test_path_like("dir"), cx)
+//             })
+//             .await;
+//         cx.read(|cx| {
+//             let finder = finder.read(cx);
+//             assert_eq!(finder.delegate().matches.len(), 0);
+//         });
+//     }
+
+//     #[gpui::test]
+//     async fn test_query_history(
+//         deterministic: Arc<gpui::executor::Deterministic>,
+//         cx: &mut gpui::TestAppContext,
+//     ) {
+//         let app_state = init_test(cx);
+
+//         app_state
+//             .fs
+//             .as_fake()
+//             .insert_tree(
+//                 "/src",
+//                 json!({
+//                     "test": {
+//                         "first.rs": "// First Rust file",
+//                         "second.rs": "// Second Rust file",
+//                         "third.rs": "// Third Rust file",
+//                     }
+//                 }),
+//             )
+//             .await;
+
+//         let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
+//         let window = cx.add_window(|cx| Workspace::test_new(project, cx));
+//         let workspace = window.root(cx);
+//         let worktree_id = cx.read(|cx| {
+//             let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
+//             assert_eq!(worktrees.len(), 1);
+//             WorktreeId::from_usize(worktrees[0].id())
+//         });
+
+//         // Open and close panels, getting their history items afterwards.
+//         // Ensure history items get populated with opened items, and items are kept in a certain order.
+//         // The history lags one opened buffer behind, since it's updated in the search panel only on its reopen.
+//         //
+//         // TODO: without closing, the opened items do not propagate their history changes for some reason
+//         // it does work in real app though, only tests do not propagate.
+
+//         let initial_history = open_close_queried_buffer(
+//             "fir",
+//             1,
+//             "first.rs",
+//             window.into(),
+//             &workspace,
+//             &deterministic,
+//             cx,
+//         )
+//         .await;
+//         assert!(
+//             initial_history.is_empty(),
+//             "Should have no history before opening any files"
+//         );
+
+//         let history_after_first = open_close_queried_buffer(
+//             "sec",
+//             1,
+//             "second.rs",
+//             window.into(),
+//             &workspace,
+//             &deterministic,
+//             cx,
+//         )
+//         .await;
+//         assert_eq!(
+//             history_after_first,
+//             vec![FoundPath::new(
+//                 ProjectPath {
+//                     worktree_id,
+//                     path: Arc::from(Path::new("test/first.rs")),
+//                 },
+//                 Some(PathBuf::from("/src/test/first.rs"))
+//             )],
+//             "Should show 1st opened item in the history when opening the 2nd item"
+//         );
+
+//         let history_after_second = open_close_queried_buffer(
+//             "thi",
+//             1,
+//             "third.rs",
+//             window.into(),
+//             &workspace,
+//             &deterministic,
+//             cx,
+//         )
+//         .await;
+//         assert_eq!(
+//             history_after_second,
+//             vec![
+//                 FoundPath::new(
+//                     ProjectPath {
+//                         worktree_id,
+//                         path: Arc::from(Path::new("test/second.rs")),
+//                     },
+//                     Some(PathBuf::from("/src/test/second.rs"))
+//                 ),
+//                 FoundPath::new(
+//                     ProjectPath {
+//                         worktree_id,
+//                         path: Arc::from(Path::new("test/first.rs")),
+//                     },
+//                     Some(PathBuf::from("/src/test/first.rs"))
+//                 ),
+//             ],
+//             "Should show 1st and 2nd opened items in the history when opening the 3rd item. \
+// 2nd item should be the first in the history, as the last opened."
+//         );
+
+//         let history_after_third = open_close_queried_buffer(
+//             "sec",
+//             1,
+//             "second.rs",
+//             window.into(),
+//             &workspace,
+//             &deterministic,
+//             cx,
+//         )
+//         .await;
+//         assert_eq!(
+//             history_after_third,
+//             vec![
+//                 FoundPath::new(
+//                     ProjectPath {
+//                         worktree_id,
+//                         path: Arc::from(Path::new("test/third.rs")),
+//                     },
+//                     Some(PathBuf::from("/src/test/third.rs"))
+//                 ),
+//                 FoundPath::new(
+//                     ProjectPath {
+//                         worktree_id,
+//                         path: Arc::from(Path::new("test/second.rs")),
+//                     },
+//                     Some(PathBuf::from("/src/test/second.rs"))
+//                 ),
+//                 FoundPath::new(
+//                     ProjectPath {
+//                         worktree_id,
+//                         path: Arc::from(Path::new("test/first.rs")),
+//                     },
+//                     Some(PathBuf::from("/src/test/first.rs"))
+//                 ),
+//             ],
+//             "Should show 1st, 2nd and 3rd opened items in the history when opening the 2nd item again. \
+// 3rd item should be the first in the history, as the last opened."
+//         );
+
+//         let history_after_second_again = open_close_queried_buffer(
+//             "thi",
+//             1,
+//             "third.rs",
+//             window.into(),
+//             &workspace,
+//             &deterministic,
+//             cx,
+//         )
+//         .await;
+//         assert_eq!(
+//             history_after_second_again,
+//             vec![
+//                 FoundPath::new(
+//                     ProjectPath {
+//                         worktree_id,
+//                         path: Arc::from(Path::new("test/second.rs")),
+//                     },
+//                     Some(PathBuf::from("/src/test/second.rs"))
+//                 ),
+//                 FoundPath::new(
+//                     ProjectPath {
+//                         worktree_id,
+//                         path: Arc::from(Path::new("test/third.rs")),
+//                     },
+//                     Some(PathBuf::from("/src/test/third.rs"))
+//                 ),
+//                 FoundPath::new(
+//                     ProjectPath {
+//                         worktree_id,
+//                         path: Arc::from(Path::new("test/first.rs")),
+//                     },
+//                     Some(PathBuf::from("/src/test/first.rs"))
+//                 ),
+//             ],
+//             "Should show 1st, 2nd and 3rd opened items in the history when opening the 3rd item again. \
+// 2nd item, as the last opened, 3rd item should go next as it was opened right before."
+//         );
+//     }
+
+//     #[gpui::test]
+//     async fn test_external_files_history(
+//         deterministic: Arc<gpui::executor::Deterministic>,
+//         cx: &mut gpui::TestAppContext,
+//     ) {
+//         let app_state = init_test(cx);
+
+//         app_state
+//             .fs
+//             .as_fake()
+//             .insert_tree(
+//                 "/src",
+//                 json!({
+//                     "test": {
+//                         "first.rs": "// First Rust file",
+//                         "second.rs": "// Second Rust file",
+//                     }
+//                 }),
+//             )
+//             .await;
+
+//         app_state
+//             .fs
+//             .as_fake()
+//             .insert_tree(
+//                 "/external-src",
+//                 json!({
+//                     "test": {
+//                         "third.rs": "// Third Rust file",
+//                         "fourth.rs": "// Fourth Rust file",
+//                     }
+//                 }),
+//             )
+//             .await;
+
+//         let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
+//         cx.update(|cx| {
+//             project.update(cx, |project, cx| {
+//                 project.find_or_create_local_worktree("/external-src", false, cx)
+//             })
+//         })
+//         .detach();
+//         deterministic.run_until_parked();
+
+//         let window = cx.add_window(|cx| Workspace::test_new(project, cx));
+//         let workspace = window.root(cx);
+//         let worktree_id = cx.read(|cx| {
+//             let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
+//             assert_eq!(worktrees.len(), 1,);
+
+//             WorktreeId::from_usize(worktrees[0].id())
+//         });
+//         workspace
+//             .update(cx, |workspace, cx| {
+//                 workspace.open_abs_path(PathBuf::from("/external-src/test/third.rs"), false, cx)
+//             })
+//             .detach();
+//         deterministic.run_until_parked();
+//         let external_worktree_id = cx.read(|cx| {
+//             let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
+//             assert_eq!(
+//                 worktrees.len(),
+//                 2,
+//                 "External file should get opened in a new worktree"
+//             );
+
+//             WorktreeId::from_usize(
+//                 worktrees
+//                     .into_iter()
+//                     .find(|worktree| worktree.id() != worktree_id.to_usize())
+//                     .expect("New worktree should have a different id")
+//                     .id(),
+//             )
+//         });
+//         close_active_item(&workspace, &deterministic, cx).await;
+
+//         let initial_history_items = open_close_queried_buffer(
+//             "sec",
+//             1,
+//             "second.rs",
+//             window.into(),
+//             &workspace,
+//             &deterministic,
+//             cx,
+//         )
+//         .await;
+//         assert_eq!(
+//             initial_history_items,
+//             vec![FoundPath::new(
+//                 ProjectPath {
+//                     worktree_id: external_worktree_id,
+//                     path: Arc::from(Path::new("")),
+//                 },
+//                 Some(PathBuf::from("/external-src/test/third.rs"))
+//             )],
+//             "Should show external file with its full path in the history after it was open"
+//         );
+
+//         let updated_history_items = open_close_queried_buffer(
+//             "fir",
+//             1,
+//             "first.rs",
+//             window.into(),
+//             &workspace,
+//             &deterministic,
+//             cx,
+//         )
+//         .await;
+//         assert_eq!(
+//             updated_history_items,
+//             vec![
+//                 FoundPath::new(
+//                     ProjectPath {
+//                         worktree_id,
+//                         path: Arc::from(Path::new("test/second.rs")),
+//                     },
+//                     Some(PathBuf::from("/src/test/second.rs"))
+//                 ),
+//                 FoundPath::new(
+//                     ProjectPath {
+//                         worktree_id: external_worktree_id,
+//                         path: Arc::from(Path::new("")),
+//                     },
+//                     Some(PathBuf::from("/external-src/test/third.rs"))
+//                 ),
+//             ],
+//             "Should keep external file with history updates",
+//         );
+//     }
+
+//     #[gpui::test]
+//     async fn test_toggle_panel_new_selections(
+//         deterministic: Arc<gpui::executor::Deterministic>,
+//         cx: &mut gpui::TestAppContext,
+//     ) {
+//         let app_state = init_test(cx);
+
+//         app_state
+//             .fs
+//             .as_fake()
+//             .insert_tree(
+//                 "/src",
+//                 json!({
+//                     "test": {
+//                         "first.rs": "// First Rust file",
+//                         "second.rs": "// Second Rust file",
+//                         "third.rs": "// Third Rust file",
+//                     }
+//                 }),
+//             )
+//             .await;
+
+//         let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
+//         let window = cx.add_window(|cx| Workspace::test_new(project, cx));
+//         let workspace = window.root(cx);
+
+//         // generate some history to select from
+//         open_close_queried_buffer(
+//             "fir",
+//             1,
+//             "first.rs",
+//             window.into(),
+//             &workspace,
+//             &deterministic,
+//             cx,
+//         )
+//         .await;
+//         open_close_queried_buffer(
+//             "sec",
+//             1,
+//             "second.rs",
+//             window.into(),
+//             &workspace,
+//             &deterministic,
+//             cx,
+//         )
+//         .await;
+//         open_close_queried_buffer(
+//             "thi",
+//             1,
+//             "third.rs",
+//             window.into(),
+//             &workspace,
+//             &deterministic,
+//             cx,
+//         )
+//         .await;
+//         let current_history = open_close_queried_buffer(
+//             "sec",
+//             1,
+//             "second.rs",
+//             window.into(),
+//             &workspace,
+//             &deterministic,
+//             cx,
+//         )
+//         .await;
+
+//         for expected_selected_index in 0..current_history.len() {
+//             cx.dispatch_action(window.into(), Toggle);
+//             let selected_index = cx.read(|cx| {
+//                 workspace
+//                     .read(cx)
+//                     .modal::<FileFinder>()
+//                     .unwrap()
+//                     .read(cx)
+//                     .delegate()
+//                     .selected_index()
+//             });
+//             assert_eq!(
+//                 selected_index, expected_selected_index,
+//                 "Should select the next item in the history"
+//             );
+//         }
+
+//         cx.dispatch_action(window.into(), Toggle);
+//         let selected_index = cx.read(|cx| {
+//             workspace
+//                 .read(cx)
+//                 .modal::<FileFinder>()
+//                 .unwrap()
+//                 .read(cx)
+//                 .delegate()
+//                 .selected_index()
+//         });
+//         assert_eq!(
+//             selected_index, 0,
+//             "Should wrap around the history and start all over"
+//         );
+//     }
+
+//     #[gpui::test]
+//     async fn test_search_preserves_history_items(
+//         deterministic: Arc<gpui::executor::Deterministic>,
+//         cx: &mut gpui::TestAppContext,
+//     ) {
+//         let app_state = init_test(cx);
+
+//         app_state
+//             .fs
+//             .as_fake()
+//             .insert_tree(
+//                 "/src",
+//                 json!({
+//                     "test": {
+//                         "first.rs": "// First Rust file",
+//                         "second.rs": "// Second Rust file",
+//                         "third.rs": "// Third Rust file",
+//                         "fourth.rs": "// Fourth Rust file",
+//                     }
+//                 }),
+//             )
+//             .await;
+
+//         let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
+//         let window = cx.add_window(|cx| Workspace::test_new(project, cx));
+//         let workspace = window.root(cx);
+//         let worktree_id = cx.read(|cx| {
+//             let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
+//             assert_eq!(worktrees.len(), 1,);
+
+//             WorktreeId::from_usize(worktrees[0].id())
+//         });
+
+//         // generate some history to select from
+//         open_close_queried_buffer(
+//             "fir",
+//             1,
+//             "first.rs",
+//             window.into(),
+//             &workspace,
+//             &deterministic,
+//             cx,
+//         )
+//         .await;
+//         open_close_queried_buffer(
+//             "sec",
+//             1,
+//             "second.rs",
+//             window.into(),
+//             &workspace,
+//             &deterministic,
+//             cx,
+//         )
+//         .await;
+//         open_close_queried_buffer(
+//             "thi",
+//             1,
+//             "third.rs",
+//             window.into(),
+//             &workspace,
+//             &deterministic,
+//             cx,
+//         )
+//         .await;
+//         open_close_queried_buffer(
+//             "sec",
+//             1,
+//             "second.rs",
+//             window.into(),
+//             &workspace,
+//             &deterministic,
+//             cx,
+//         )
+//         .await;
+
+//         cx.dispatch_action(window.into(), Toggle);
+//         let first_query = "f";
+//         let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
+//         finder
+//             .update(cx, |finder, cx| {
+//                 finder
+//                     .delegate_mut()
+//                     .update_matches(first_query.to_string(), cx)
+//             })
+//             .await;
+//         finder.read_with(cx, |finder, _| {
+//             let delegate = finder.delegate();
+//             assert_eq!(delegate.matches.history.len(), 1, "Only one history item contains {first_query}, it should be present and others should be filtered out");
+//             let history_match = delegate.matches.history.first().unwrap();
+//             assert!(history_match.1.is_some(), "Should have path matches for history items after querying");
+//             assert_eq!(history_match.0, FoundPath::new(
+//                 ProjectPath {
+//                     worktree_id,
+//                     path: Arc::from(Path::new("test/first.rs")),
+//                 },
+//                 Some(PathBuf::from("/src/test/first.rs"))
+//             ));
+//             assert_eq!(delegate.matches.search.len(), 1, "Only one non-history item contains {first_query}, it should be present");
+//             assert_eq!(delegate.matches.search.first().unwrap().path.as_ref(), Path::new("test/fourth.rs"));
+//         });
+
+//         let second_query = "fsdasdsa";
+//         let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
+//         finder
+//             .update(cx, |finder, cx| {
+//                 finder
+//                     .delegate_mut()
+//                     .update_matches(second_query.to_string(), cx)
+//             })
+//             .await;
+//         finder.read_with(cx, |finder, _| {
+//             let delegate = finder.delegate();
+//             assert!(
+//                 delegate.matches.history.is_empty(),
+//                 "No history entries should match {second_query}"
+//             );
+//             assert!(
+//                 delegate.matches.search.is_empty(),
+//                 "No search entries should match {second_query}"
+//             );
+//         });
+
+//         let first_query_again = first_query;
+//         let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
+//         finder
+//             .update(cx, |finder, cx| {
+//                 finder
+//                     .delegate_mut()
+//                     .update_matches(first_query_again.to_string(), cx)
+//             })
+//             .await;
+//         finder.read_with(cx, |finder, _| {
+//             let delegate = finder.delegate();
+//             assert_eq!(delegate.matches.history.len(), 1, "Only one history item contains {first_query_again}, it should be present and others should be filtered out, even after non-matching query");
+//             let history_match = delegate.matches.history.first().unwrap();
+//             assert!(history_match.1.is_some(), "Should have path matches for history items after querying");
+//             assert_eq!(history_match.0, FoundPath::new(
+//                 ProjectPath {
+//                     worktree_id,
+//                     path: Arc::from(Path::new("test/first.rs")),
+//                 },
+//                 Some(PathBuf::from("/src/test/first.rs"))
+//             ));
+//             assert_eq!(delegate.matches.search.len(), 1, "Only one non-history item contains {first_query_again}, it should be present, even after non-matching query");
+//             assert_eq!(delegate.matches.search.first().unwrap().path.as_ref(), Path::new("test/fourth.rs"));
+//         });
+//     }
+
+//     #[gpui::test]
+//     async fn test_history_items_vs_very_good_external_match(
+//         deterministic: Arc<gpui::executor::Deterministic>,
+//         cx: &mut gpui::TestAppContext,
+//     ) {
+//         let app_state = init_test(cx);
+
+//         app_state
+//             .fs
+//             .as_fake()
+//             .insert_tree(
+//                 "/src",
+//                 json!({
+//                     "collab_ui": {
+//                         "first.rs": "// First Rust file",
+//                         "second.rs": "// Second Rust file",
+//                         "third.rs": "// Third Rust file",
+//                         "collab_ui.rs": "// Fourth Rust file",
+//                     }
+//                 }),
+//             )
+//             .await;
+
+//         let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
+//         let window = cx.add_window(|cx| Workspace::test_new(project, cx));
+//         let workspace = window.root(cx);
+//         // generate some history to select from
+//         open_close_queried_buffer(
+//             "fir",
+//             1,
+//             "first.rs",
+//             window.into(),
+//             &workspace,
+//             &deterministic,
+//             cx,
+//         )
+//         .await;
+//         open_close_queried_buffer(
+//             "sec",
+//             1,
+//             "second.rs",
+//             window.into(),
+//             &workspace,
+//             &deterministic,
+//             cx,
+//         )
+//         .await;
+//         open_close_queried_buffer(
+//             "thi",
+//             1,
+//             "third.rs",
+//             window.into(),
+//             &workspace,
+//             &deterministic,
+//             cx,
+//         )
+//         .await;
+//         open_close_queried_buffer(
+//             "sec",
+//             1,
+//             "second.rs",
+//             window.into(),
+//             &workspace,
+//             &deterministic,
+//             cx,
+//         )
+//         .await;
+
+//         cx.dispatch_action(window.into(), Toggle);
+//         let query = "collab_ui";
+//         let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
+//         finder
+//             .update(cx, |finder, cx| {
+//                 finder.delegate_mut().update_matches(query.to_string(), cx)
+//             })
+//             .await;
+//         finder.read_with(cx, |finder, _| {
+//             let delegate = finder.delegate();
+//             assert!(
+//                 delegate.matches.history.is_empty(),
+//                 "History items should not math query {query}, they should be matched by name only"
+//             );
+
+//             let search_entries = delegate
+//                 .matches
+//                 .search
+//                 .iter()
+//                 .map(|path_match| path_match.path.to_path_buf())
+//                 .collect::<Vec<_>>();
+//             assert_eq!(
+//                 search_entries,
+//                 vec![
+//                     PathBuf::from("collab_ui/collab_ui.rs"),
+//                     PathBuf::from("collab_ui/third.rs"),
+//                     PathBuf::from("collab_ui/first.rs"),
+//                     PathBuf::from("collab_ui/second.rs"),
+//                 ],
+//                 "Despite all search results having the same directory name, the most matching one should be on top"
+//             );
+//         });
+//     }
+
+//     #[gpui::test]
+//     async fn test_nonexistent_history_items_not_shown(
+//         deterministic: Arc<gpui::executor::Deterministic>,
+//         cx: &mut gpui::TestAppContext,
+//     ) {
+//         let app_state = init_test(cx);
+
+//         app_state
+//             .fs
+//             .as_fake()
+//             .insert_tree(
+//                 "/src",
+//                 json!({
+//                     "test": {
+//                         "first.rs": "// First Rust file",
+//                         "nonexistent.rs": "// Second Rust file",
+//                         "third.rs": "// Third Rust file",
+//                     }
+//                 }),
+//             )
+//             .await;
+
+//         let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
+//         let window = cx.add_window(|cx| Workspace::test_new(project, cx));
+//         let workspace = window.root(cx);
+//         // generate some history to select from
+//         open_close_queried_buffer(
+//             "fir",
+//             1,
+//             "first.rs",
+//             window.into(),
+//             &workspace,
+//             &deterministic,
+//             cx,
+//         )
+//         .await;
+//         open_close_queried_buffer(
+//             "non",
+//             1,
+//             "nonexistent.rs",
+//             window.into(),
+//             &workspace,
+//             &deterministic,
+//             cx,
+//         )
+//         .await;
+//         open_close_queried_buffer(
+//             "thi",
+//             1,
+//             "third.rs",
+//             window.into(),
+//             &workspace,
+//             &deterministic,
+//             cx,
+//         )
+//         .await;
+//         open_close_queried_buffer(
+//             "fir",
+//             1,
+//             "first.rs",
+//             window.into(),
+//             &workspace,
+//             &deterministic,
+//             cx,
+//         )
+//         .await;
+
+//         cx.dispatch_action(window.into(), Toggle);
+//         let query = "rs";
+//         let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
+//         finder
+//             .update(cx, |finder, cx| {
+//                 finder.delegate_mut().update_matches(query.to_string(), cx)
+//             })
+//             .await;
+//         finder.read_with(cx, |finder, _| {
+//             let delegate = finder.delegate();
+//             let history_entries = delegate
+//                 .matches
+//                 .history
+//                 .iter()
+//                 .map(|(_, path_match)| path_match.as_ref().expect("should have a path match").path.to_path_buf())
+//                 .collect::<Vec<_>>();
+//             assert_eq!(
+//                 history_entries,
+//                 vec![
+//                     PathBuf::from("test/first.rs"),
+//                     PathBuf::from("test/third.rs"),
+//                 ],
+//                 "Should have all opened files in the history, except the ones that do not exist on disk"
+//             );
+//         });
+//     }
+
+//     async fn open_close_queried_buffer(
+//         input: &str,
+//         expected_matches: usize,
+//         expected_editor_title: &str,
+//         window: gpui::AnyWindowHandle,
+//         workspace: &ViewHandle<Workspace>,
+//         deterministic: &gpui::executor::Deterministic,
+//         cx: &mut gpui::TestAppContext,
+//     ) -> Vec<FoundPath> {
+//         cx.dispatch_action(window, Toggle);
+//         let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
+//         finder
+//             .update(cx, |finder, cx| {
+//                 finder.delegate_mut().update_matches(input.to_string(), cx)
+//             })
+//             .await;
+//         let history_items = finder.read_with(cx, |finder, _| {
+//             assert_eq!(
+//                 finder.delegate().matches.len(),
+//                 expected_matches,
+//                 "Unexpected number of matches found for query {input}"
+//             );
+//             finder.delegate().history_items.clone()
+//         });
+
+//         let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone());
+//         cx.dispatch_action(window, SelectNext);
+//         cx.dispatch_action(window, Confirm);
+//         deterministic.run_until_parked();
+//         active_pane
+//             .condition(cx, |pane, _| pane.active_item().is_some())
+//             .await;
+//         cx.read(|cx| {
+//             let active_item = active_pane.read(cx).active_item().unwrap();
+//             let active_editor_title = active_item
+//                 .as_any()
+//                 .downcast_ref::<Editor>()
+//                 .unwrap()
+//                 .read(cx)
+//                 .title(cx);
+//             assert_eq!(
+//                 expected_editor_title, active_editor_title,
+//                 "Unexpected editor title for query {input}"
+//             );
+//         });
+
+//         close_active_item(workspace, deterministic, cx).await;
+
+//         history_items
+//     }
+
+//     async fn close_active_item(
+//         workspace: &ViewHandle<Workspace>,
+//         deterministic: &gpui::executor::Deterministic,
+//         cx: &mut TestAppContext,
+//     ) {
+//         let mut original_items = HashMap::new();
+//         cx.read(|cx| {
+//             for pane in workspace.read(cx).panes() {
+//                 let pane_id = pane.id();
+//                 let pane = pane.read(cx);
+//                 let insertion_result = original_items.insert(pane_id, pane.items().count());
+//                 assert!(insertion_result.is_none(), "Pane id {pane_id} collision");
+//             }
+//         });
+
+//         let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone());
+//         active_pane
+//             .update(cx, |pane, cx| {
+//                 pane.close_active_item(&workspace::CloseActiveItem { save_intent: None }, cx)
+//                     .unwrap()
+//             })
+//             .await
+//             .unwrap();
+//         deterministic.run_until_parked();
+//         cx.read(|cx| {
+//             for pane in workspace.read(cx).panes() {
+//                 let pane_id = pane.id();
+//                 let pane = pane.read(cx);
+//                 match original_items.remove(&pane_id) {
+//                     Some(original_items) => {
+//                         assert_eq!(
+//                             pane.items().count(),
+//                             original_items.saturating_sub(1),
+//                             "Pane id {pane_id} should have item closed"
+//                         );
+//                     }
+//                     None => panic!("Pane id {pane_id} not found in original items"),
+//                 }
+//             }
+//         });
+//         assert!(
+//             original_items.len() <= 1,
+//             "At most one panel should got closed"
+//         );
+//     }
+
+//     fn init_test(cx: &mut TestAppContext) -> Arc<AppState> {
+//         cx.foreground_executor().forbid_parking();
+//         cx.update(|cx| {
+//             let state = AppState::test(cx);
+//             theme::init(cx);
+//             language::init(cx);
+//             super::init(cx);
+//             editor::init(cx);
+//             workspace::init_settings(cx);
+//             Project::init_settings(cx);
+//             state
+//         })
+//     }
+
+//     fn test_path_like(test_str: &str) -> PathLikeWithPosition<FileSearchQuery> {
+//         PathLikeWithPosition::parse_str(test_str, |path_like_str| {
+//             Ok::<_, std::convert::Infallible>(FileSearchQuery {
+//                 raw_query: test_str.to_owned(),
+//                 file_query_end: if path_like_str == test_str {
+//                     None
+//                 } else {
+//                     Some(path_like_str.len())
+//                 },
+//             })
+//         })
+//         .unwrap()
+//     }
+
+//     fn dummy_found_path(project_path: ProjectPath) -> FoundPath {
+//         FoundPath {
+//             project: project_path,
+//             absolute: None,
+//         }
+//     }
+// }

crates/picker2/src/picker2.rs 🔗

@@ -146,6 +146,11 @@ impl<D: PickerDelegate> Picker<D> {
         }
     }
 
+    pub fn refresh(&mut self, cx: &mut ViewContext<Self>) {
+        let query = self.editor.read(cx).text(cx);
+        self.update_matches(query, cx);
+    }
+
     pub fn update_matches(&mut self, query: String, cx: &mut ViewContext<Self>) {
         let update = self.delegate.update_matches(query, cx);
         self.matches_updated(cx);

crates/workspace2/src/workspace2.rs 🔗

@@ -1961,50 +1961,50 @@ impl Workspace {
         })
     }
 
-    //     pub fn open_abs_path(
-    //         &mut self,
-    //         abs_path: PathBuf,
-    //         visible: bool,
-    //         cx: &mut ViewContext<Self>,
-    //     ) -> Task<anyhow::Result<Box<dyn ItemHandle>>> {
-    //         cx.spawn(|workspace, mut cx| async move {
-    //             let open_paths_task_result = workspace
-    //                 .update(&mut cx, |workspace, cx| {
-    //                     workspace.open_paths(vec![abs_path.clone()], visible, cx)
-    //                 })
-    //                 .with_context(|| format!("open abs path {abs_path:?} task spawn"))?
-    //                 .await;
-    //             anyhow::ensure!(
-    //                 open_paths_task_result.len() == 1,
-    //                 "open abs path {abs_path:?} task returned incorrect number of results"
-    //             );
-    //             match open_paths_task_result
-    //                 .into_iter()
-    //                 .next()
-    //                 .expect("ensured single task result")
-    //             {
-    //                 Some(open_result) => {
-    //                     open_result.with_context(|| format!("open abs path {abs_path:?} task join"))
-    //                 }
-    //                 None => anyhow::bail!("open abs path {abs_path:?} task returned None"),
-    //             }
-    //         })
-    //     }
+    pub fn open_abs_path(
+        &mut self,
+        abs_path: PathBuf,
+        visible: bool,
+        cx: &mut ViewContext<Self>,
+    ) -> Task<anyhow::Result<Box<dyn ItemHandle>>> {
+        cx.spawn(|workspace, mut cx| async move {
+            let open_paths_task_result = workspace
+                .update(&mut cx, |workspace, cx| {
+                    workspace.open_paths(vec![abs_path.clone()], visible, cx)
+                })
+                .with_context(|| format!("open abs path {abs_path:?} task spawn"))?
+                .await;
+            anyhow::ensure!(
+                open_paths_task_result.len() == 1,
+                "open abs path {abs_path:?} task returned incorrect number of results"
+            );
+            match open_paths_task_result
+                .into_iter()
+                .next()
+                .expect("ensured single task result")
+            {
+                Some(open_result) => {
+                    open_result.with_context(|| format!("open abs path {abs_path:?} task join"))
+                }
+                None => anyhow::bail!("open abs path {abs_path:?} task returned None"),
+            }
+        })
+    }
 
-    //     pub fn split_abs_path(
-    //         &mut self,
-    //         abs_path: PathBuf,
-    //         visible: bool,
-    //         cx: &mut ViewContext<Self>,
-    //     ) -> Task<anyhow::Result<Box<dyn ItemHandle>>> {
-    //         let project_path_task =
-    //             Workspace::project_path_for_path(self.project.clone(), &abs_path, visible, cx);
-    //         cx.spawn(|this, mut cx| async move {
-    //             let (_, path) = project_path_task.await?;
-    //             this.update(&mut cx, |this, cx| this.split_path(path, cx))?
-    //                 .await
-    //         })
-    //     }
+    pub fn split_abs_path(
+        &mut self,
+        abs_path: PathBuf,
+        visible: bool,
+        cx: &mut ViewContext<Self>,
+    ) -> Task<anyhow::Result<Box<dyn ItemHandle>>> {
+        let project_path_task =
+            Workspace::project_path_for_path(self.project.clone(), &abs_path, visible, cx);
+        cx.spawn(|this, mut cx| async move {
+            let (_, path) = project_path_task.await?;
+            this.update(&mut cx, |this, cx| this.split_path(path, cx))?
+                .await
+        })
+    }
 
     pub fn open_path(
         &mut self,
@@ -2031,37 +2031,37 @@ impl Workspace {
         })
     }
 
-    //     pub fn split_path(
-    //         &mut self,
-    //         path: impl Into<ProjectPath>,
-    //         cx: &mut ViewContext<Self>,
-    //     ) -> Task<Result<Box<dyn ItemHandle>, anyhow::Error>> {
-    //         let pane = self.last_active_center_pane.clone().unwrap_or_else(|| {
-    //             self.panes
-    //                 .first()
-    //                 .expect("There must be an active pane")
-    //                 .downgrade()
-    //         });
+    pub fn split_path(
+        &mut self,
+        path: impl Into<ProjectPath>,
+        cx: &mut ViewContext<Self>,
+    ) -> Task<Result<Box<dyn ItemHandle>, anyhow::Error>> {
+        let pane = self.last_active_center_pane.clone().unwrap_or_else(|| {
+            self.panes
+                .first()
+                .expect("There must be an active pane")
+                .downgrade()
+        });
 
-    //         if let Member::Pane(center_pane) = &self.center.root {
-    //             if center_pane.read(cx).items_len() == 0 {
-    //                 return self.open_path(path, Some(pane), true, cx);
-    //             }
-    //         }
+        if let Member::Pane(center_pane) = &self.center.root {
+            if center_pane.read(cx).items_len() == 0 {
+                return self.open_path(path, Some(pane), true, cx);
+            }
+        }
 
-    //         let task = self.load_path(path.into(), cx);
-    //         cx.spawn(|this, mut cx| async move {
-    //             let (project_entry_id, build_item) = task.await?;
-    //             this.update(&mut cx, move |this, cx| -> Option<_> {
-    //                 let pane = pane.upgrade(cx)?;
-    //                 let new_pane = this.split_pane(pane, SplitDirection::Right, cx);
-    //                 new_pane.update(cx, |new_pane, cx| {
-    //                     Some(new_pane.open_item(project_entry_id, true, cx, build_item))
-    //                 })
-    //             })
-    //             .map(|option| option.ok_or_else(|| anyhow!("pane was dropped")))?
-    //         })
-    //     }
+        let task = self.load_path(path.into(), cx);
+        cx.spawn(|this, mut cx| async move {
+            let (project_entry_id, build_item) = task.await?;
+            this.update(&mut cx, move |this, cx| -> Option<_> {
+                let pane = pane.upgrade()?;
+                let new_pane = this.split_pane(pane, SplitDirection::Right, cx);
+                new_pane.update(cx, |new_pane, cx| {
+                    Some(new_pane.open_item(project_entry_id, true, cx, build_item))
+                })
+            })
+            .map(|option| option.ok_or_else(|| anyhow!("pane was dropped")))?
+        })
+    }
 
     pub(crate) fn load_path(
         &mut self,