assistant2: List directories in directory context picker (#22300)
This PR updates the directory context picker in Assistant2 to show the available directories. Release Notes: - N/A
This commit is contained in:
parent
62f5ca562e
commit
d566792ae1
1 changed files with 131 additions and 13 deletions
|
@ -1,6 +1,8 @@
|
||||||
// TODO: Remove this once we've implemented the functionality.
|
// TODO: Remove this when we finish the implementation.
|
||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
|
|
||||||
|
use std::path::Path;
|
||||||
|
use std::sync::atomic::AtomicBool;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use fuzzy::PathMatch;
|
use fuzzy::PathMatch;
|
||||||
|
@ -11,6 +13,7 @@ use ui::{prelude::*, ListItem};
|
||||||
use util::ResultExt as _;
|
use util::ResultExt as _;
|
||||||
use workspace::Workspace;
|
use workspace::Workspace;
|
||||||
|
|
||||||
|
use crate::context::ContextKind;
|
||||||
use crate::context_picker::{ConfirmBehavior, ContextPicker};
|
use crate::context_picker::{ConfirmBehavior, ContextPicker};
|
||||||
use crate::context_store::ContextStore;
|
use crate::context_store::ContextStore;
|
||||||
|
|
||||||
|
@ -75,6 +78,65 @@ impl DirectoryContextPickerDelegate {
|
||||||
selected_index: 0,
|
selected_index: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn search(
|
||||||
|
&mut self,
|
||||||
|
query: String,
|
||||||
|
cancellation_flag: Arc<AtomicBool>,
|
||||||
|
workspace: &View<Workspace>,
|
||||||
|
cx: &mut ViewContext<Picker<Self>>,
|
||||||
|
) -> Task<Vec<PathMatch>> {
|
||||||
|
if query.is_empty() {
|
||||||
|
let workspace = workspace.read(cx);
|
||||||
|
let project = workspace.project().read(cx);
|
||||||
|
let directory_matches = project.worktrees(cx).flat_map(|worktree| {
|
||||||
|
let worktree = worktree.read(cx);
|
||||||
|
let path_prefix: Arc<str> = worktree.root_name().into();
|
||||||
|
worktree.directories(false, 0).map(move |entry| PathMatch {
|
||||||
|
score: 0.,
|
||||||
|
positions: Vec::new(),
|
||||||
|
worktree_id: worktree.id().to_usize(),
|
||||||
|
path: entry.path.clone(),
|
||||||
|
path_prefix: path_prefix.clone(),
|
||||||
|
distance_to_relative_ancestor: 0,
|
||||||
|
is_dir: true,
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
Task::ready(directory_matches.collect())
|
||||||
|
} else {
|
||||||
|
let worktrees = workspace.read(cx).visible_worktrees(cx).collect::<Vec<_>>();
|
||||||
|
let candidate_sets = worktrees
|
||||||
|
.into_iter()
|
||||||
|
.map(|worktree| {
|
||||||
|
let worktree = worktree.read(cx);
|
||||||
|
|
||||||
|
PathMatchCandidateSet {
|
||||||
|
snapshot: worktree.snapshot(),
|
||||||
|
include_ignored: worktree
|
||||||
|
.root_entry()
|
||||||
|
.map_or(false, |entry| entry.is_ignored),
|
||||||
|
include_root_name: true,
|
||||||
|
candidates: project::Candidates::Directories,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let executor = cx.background_executor().clone();
|
||||||
|
cx.foreground_executor().spawn(async move {
|
||||||
|
fuzzy::match_path_sets(
|
||||||
|
candidate_sets.as_slice(),
|
||||||
|
query.as_str(),
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
100,
|
||||||
|
&cancellation_flag,
|
||||||
|
executor,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PickerDelegate for DirectoryContextPickerDelegate {
|
impl PickerDelegate for DirectoryContextPickerDelegate {
|
||||||
|
@ -88,7 +150,7 @@ impl PickerDelegate for DirectoryContextPickerDelegate {
|
||||||
self.selected_index
|
self.selected_index
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_selected_index(&mut self, ix: usize, cx: &mut ViewContext<Picker<Self>>) {
|
fn set_selected_index(&mut self, ix: usize, _cx: &mut ViewContext<Picker<Self>>) {
|
||||||
self.selected_index = ix;
|
self.selected_index = ix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,17 +158,65 @@ impl PickerDelegate for DirectoryContextPickerDelegate {
|
||||||
"Search folders…".into()
|
"Search folders…".into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_matches(&mut self, _query: String, _cx: &mut ViewContext<Picker<Self>>) -> Task<()> {
|
fn update_matches(&mut self, query: String, cx: &mut ViewContext<Picker<Self>>) -> Task<()> {
|
||||||
// TODO: Implement this once we fix the issues with the file context picker.
|
let Some(workspace) = self.workspace.upgrade() else {
|
||||||
Task::ready(())
|
return Task::ready(());
|
||||||
|
};
|
||||||
|
|
||||||
|
let search_task = self.search(query, Arc::<AtomicBool>::default(), &workspace, cx);
|
||||||
|
|
||||||
|
cx.spawn(|this, mut cx| async move {
|
||||||
|
let mut paths = search_task.await;
|
||||||
|
let empty_path = Path::new("");
|
||||||
|
paths.retain(|path_match| path_match.path.as_ref() != empty_path);
|
||||||
|
|
||||||
|
this.update(&mut cx, |this, _cx| {
|
||||||
|
this.delegate.matches = paths;
|
||||||
|
})
|
||||||
|
.log_err();
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn confirm(&mut self, _secondary: bool, cx: &mut ViewContext<Picker<Self>>) {
|
fn confirm(&mut self, _secondary: bool, cx: &mut ViewContext<Picker<Self>>) {
|
||||||
// TODO: Implement this once we fix the issues with the file context picker.
|
let mat = &self.matches[self.selected_index];
|
||||||
match self.confirm_behavior {
|
|
||||||
ConfirmBehavior::KeepOpen => {}
|
let workspace = self.workspace.clone();
|
||||||
ConfirmBehavior::Close => self.dismissed(cx),
|
let Some(project) = workspace
|
||||||
}
|
.upgrade()
|
||||||
|
.map(|workspace| workspace.read(cx).project().clone())
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let path = mat.path.clone();
|
||||||
|
let worktree_id = WorktreeId::from_usize(mat.worktree_id);
|
||||||
|
let confirm_behavior = self.confirm_behavior;
|
||||||
|
cx.spawn(|this, mut cx| async move {
|
||||||
|
this.update(&mut cx, |this, cx| {
|
||||||
|
let mut text = String::new();
|
||||||
|
|
||||||
|
// TODO: Add the files from the selected directory.
|
||||||
|
|
||||||
|
this.delegate
|
||||||
|
.context_store
|
||||||
|
.update(cx, |context_store, cx| {
|
||||||
|
context_store.insert_context(
|
||||||
|
ContextKind::Directory,
|
||||||
|
path.to_string_lossy().to_string(),
|
||||||
|
text,
|
||||||
|
);
|
||||||
|
})?;
|
||||||
|
|
||||||
|
match confirm_behavior {
|
||||||
|
ConfirmBehavior::KeepOpen => {}
|
||||||
|
ConfirmBehavior::Close => this.delegate.dismissed(cx),
|
||||||
|
}
|
||||||
|
|
||||||
|
anyhow::Ok(())
|
||||||
|
})??;
|
||||||
|
|
||||||
|
anyhow::Ok(())
|
||||||
|
})
|
||||||
|
.detach_and_log_err(cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {
|
fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {
|
||||||
|
@ -120,10 +230,18 @@ impl PickerDelegate for DirectoryContextPickerDelegate {
|
||||||
|
|
||||||
fn render_match(
|
fn render_match(
|
||||||
&self,
|
&self,
|
||||||
_ix: usize,
|
ix: usize,
|
||||||
_selected: bool,
|
selected: bool,
|
||||||
_cx: &mut ViewContext<Picker<Self>>,
|
_cx: &mut ViewContext<Picker<Self>>,
|
||||||
) -> Option<Self::ListItem> {
|
) -> Option<Self::ListItem> {
|
||||||
None
|
let path_match = &self.matches[ix];
|
||||||
|
let directory_name = path_match.path.to_string_lossy().to_string();
|
||||||
|
|
||||||
|
Some(
|
||||||
|
ListItem::new(ix)
|
||||||
|
.inset(true)
|
||||||
|
.toggle_state(selected)
|
||||||
|
.child(h_flex().gap_2().child(Label::new(directory_name))),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue