TEMP

Conrad Irwin created

Change summary

Cargo.lock                             |  1 
crates/file_finder2/Cargo.toml         |  1 
crates/file_finder2/src/file_finder.rs | 91 ++++++++++++++++++++++++---
crates/picker2/src/picker2.rs          | 11 +++
4 files changed, 92 insertions(+), 12 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -3081,6 +3081,7 @@ dependencies = [
  "settings2",
  "text2",
  "theme2",
+ "ui2",
  "util",
  "workspace2",
 ]

crates/file_finder2/Cargo.toml 🔗

@@ -20,6 +20,7 @@ settings = { package = "settings2", path = "../settings2" }
 text = { package = "text2", path = "../text2" }
 util = { path = "../util" }
 theme = { package = "theme2", path = "../theme2" }
+ui = { package = "ui2", path = "../ui2" }
 workspace = { package = "workspace2", path = "../workspace2" }
 postage.workspace = true
 serde.workspace = true

crates/file_finder2/src/file_finder.rs 🔗

@@ -1,7 +1,9 @@
 use collections::HashMap;
 use editor::{scroll::autoscroll::Autoscroll, Bias, Editor};
 use fuzzy::{CharBag, PathMatch, PathMatchCandidate};
-use gpui::{actions, AppContext, Task, ViewContext, View, EventEmitter, WindowContext};
+use gpui::{
+    actions, AppContext, Div, EventEmitter, Render, Task, View, ViewContext, WindowContext,
+};
 use picker::{Picker, PickerDelegate};
 use project::{PathMatchCandidateSet, Project, ProjectPath, WorktreeId};
 use std::{
@@ -12,13 +14,13 @@ use std::{
     },
 };
 use text::Point;
-use util::{paths::PathLikeWithPosition, post_inc, ResultExt};
-use workspace::{Workspace, Modal, ModalEvent};
+use util::{paths::PathLikeWithPosition, post_inc};
+use workspace::{Modal, ModalEvent, Workspace};
 
 actions!(Toggle);
 
 pub struct FileFinder {
-    picker: View<Picker<FileFinderDelegate>>
+    picker: View<Picker<FileFinderDelegate>>,
 }
 
 pub fn init(cx: &mut AppContext) {
@@ -28,21 +30,88 @@ pub fn init(cx: &mut AppContext) {
 impl FileFinder {
     fn register(workspace: &mut Workspace, _: &mut ViewContext<Workspace>) {
         workspace.register_action(|workspace, _: &Toggle, cx| {
-            workspace.toggle_modal(cx, |cx| FileFinder::new(cx));
+            let Some(file_finder) = workspace.current_modal::<Self>(cx) else {
+                workspace.toggle_modal(cx, |cx| FileFinder::new(workspace, cx));
+                return;
+            };
+            file_finder.update(cx, |file_finder, cx| {
+                file_finder
+                    .picker
+                    .update(cx, |picker, cx| picker.cycle_selection(cx))
+            })
         });
     }
 
-    fn new(cx: &mut ViewContext<Self>) -> Self {
-        FileFinder{
+    fn new(workspace: &mut Workspace, cx: &mut ViewContext<Self>) -> Self {
+        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
     }
 }
 
-impl EventEmitter<ModalEvent> for FileFinder;
-impl Modal for FileFinder{
+impl EventEmitter<ModalEvent> for FileFinder {}
+impl Modal for FileFinder {
     fn focus(&self, cx: &mut WindowContext) {
-        self.picker.update(cx, |picker, cx| { picker.focus(cx) })
+        self.picker.update(cx, |picker, cx| picker.focus(cx))
+    }
+}
+impl Render for FileFinder {
+    type Element = Div<Self>;
+
+    fn render(&mut self, _cx: &mut ViewContext<Self>) -> Self::Element {
+        v_stack().w_96().child(self.picker.clone())
     }
 }
 

crates/picker2/src/picker2.rs 🔗

@@ -58,7 +58,7 @@ impl<D: PickerDelegate> Picker<D> {
         self.editor.update(cx, |editor, cx| editor.focus(cx));
     }
 
-    fn select_next(&mut self, _: &menu::SelectNext, cx: &mut ViewContext<Self>) {
+    pub fn select_next(&mut self, _: &menu::SelectNext, cx: &mut ViewContext<Self>) {
         let count = self.delegate.match_count();
         if count > 0 {
             let index = self.delegate.selected_index();
@@ -98,6 +98,15 @@ impl<D: PickerDelegate> Picker<D> {
         }
     }
 
+    pub fn cycle_selection(&mut self, cx: &mut ViewContext<Self>) {
+        let count = self.delegate.match_count();
+        let index = self.delegate.selected_index();
+        let new_index = if index + 1 == count { 0 } else { index + 1 };
+        self.delegate.set_selected_index(new_index, cx);
+        self.scroll_handle.scroll_to_item(new_index);
+        cx.notify();
+    }
+
     fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext<Self>) {
         self.delegate.dismissed(cx);
     }