Add search in directory action in the project panel

This commit is contained in:
Kirill Bulatov 2023-07-20 16:01:01 +03:00
parent e002d9efb0
commit 595bc16749
5 changed files with 287 additions and 5 deletions

View file

@ -125,7 +125,8 @@ actions!(
Paste,
Delete,
Rename,
ToggleFocus
ToggleFocus,
NewSearchInDirectory,
]
);
@ -151,6 +152,7 @@ pub fn init(assets: impl AssetSource, cx: &mut AppContext) {
cx.add_action(ProjectPanel::copy_path);
cx.add_action(ProjectPanel::copy_relative_path);
cx.add_action(ProjectPanel::reveal_in_finder);
cx.add_action(ProjectPanel::new_search_in_directory);
cx.add_action(
|this: &mut ProjectPanel, action: &Paste, cx: &mut ViewContext<ProjectPanel>| {
this.paste(action, cx);
@ -169,6 +171,9 @@ pub enum Event {
},
DockPositionChanged,
Focus,
NewSearchInDirectory {
dir_entry: Entry,
},
}
#[derive(Serialize, Deserialize)]
@ -417,6 +422,12 @@ impl ProjectPanel {
CopyRelativePath,
));
menu_entries.push(ContextMenuItem::action("Reveal in Finder", RevealInFinder));
if entry.is_dir() {
menu_entries.push(ContextMenuItem::action(
"Search inside",
NewSearchInDirectory,
));
}
if let Some(clipboard_entry) = self.clipboard_entry {
if clipboard_entry.worktree_id() == worktree.id() {
menu_entries.push(ContextMenuItem::action("Paste", Paste));
@ -928,6 +939,20 @@ impl ProjectPanel {
}
}
pub fn new_search_in_directory(
&mut self,
_: &NewSearchInDirectory,
cx: &mut ViewContext<Self>,
) {
if let Some((_, entry)) = self.selected_entry(cx) {
if entry.is_dir() {
cx.emit(Event::NewSearchInDirectory {
dir_entry: entry.clone(),
});
}
}
}
fn move_entry(
&mut self,
entry_to_move: ProjectEntryId,
@ -1677,7 +1702,11 @@ mod tests {
use project::FakeFs;
use serde_json::json;
use settings::SettingsStore;
use std::{collections::HashSet, path::Path};
use std::{
collections::HashSet,
path::Path,
sync::atomic::{self, AtomicUsize},
};
use workspace::{pane, AppState};
#[gpui::test]
@ -2516,6 +2545,83 @@ mod tests {
);
}
#[gpui::test]
async fn test_new_search_in_directory_trigger(cx: &mut gpui::TestAppContext) {
init_test_with_editor(cx);
let fs = FakeFs::new(cx.background());
fs.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(fs.clone(), ["/src".as_ref()], cx).await;
let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
let panel = workspace.update(cx, |workspace, cx| ProjectPanel::new(workspace, cx));
let new_search_events_count = Arc::new(AtomicUsize::new(0));
let _subscription = panel.update(cx, |_, cx| {
let subcription_count = Arc::clone(&new_search_events_count);
cx.subscribe(&cx.handle(), move |_, _, event, _| {
if matches!(event, Event::NewSearchInDirectory { .. }) {
subcription_count.fetch_add(1, atomic::Ordering::SeqCst);
}
})
});
toggle_expand_dir(&panel, "src/test", cx);
select_path(&panel, "src/test/first.rs", cx);
panel.update(cx, |panel, cx| panel.confirm(&Confirm, cx));
cx.foreground().run_until_parked();
assert_eq!(
visible_entries_as_strings(&panel, 0..10, cx),
&[
"v src",
" v test",
" first.rs <== selected",
" second.rs",
" third.rs"
]
);
panel.update(cx, |panel, cx| {
panel.new_search_in_directory(&NewSearchInDirectory, cx)
});
assert_eq!(
new_search_events_count.load(atomic::Ordering::SeqCst),
0,
"Should not trigger new search in directory when called on a file"
);
select_path(&panel, "src/test", cx);
panel.update(cx, |panel, cx| panel.confirm(&Confirm, cx));
cx.foreground().run_until_parked();
assert_eq!(
visible_entries_as_strings(&panel, 0..10, cx),
&[
"v src",
" v test <== selected",
" first.rs",
" second.rs",
" third.rs"
]
);
panel.update(cx, |panel, cx| {
panel.new_search_in_directory(&NewSearchInDirectory, cx)
});
assert_eq!(
new_search_events_count.load(atomic::Ordering::SeqCst),
1,
"Should trigger new search in directory when called on a directory"
);
}
fn toggle_expand_dir(
panel: &ViewHandle<ProjectPanel>,
path: impl AsRef<Path>,