assistant2: Sketch in directory context picker (#22148)
This PR sketches in the structure for the directory context picker. Waiting on implementing the actual behavior until we fix the issues with the file context picker. Release Notes: - N/A
This commit is contained in:
parent
68e3d79847
commit
b17f2089a2
3 changed files with 151 additions and 0 deletions
|
@ -24,6 +24,7 @@ pub struct Context {
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum ContextKind {
|
pub enum ContextKind {
|
||||||
File,
|
File,
|
||||||
|
Directory,
|
||||||
FetchedUrl,
|
FetchedUrl,
|
||||||
Thread,
|
Thread,
|
||||||
}
|
}
|
||||||
|
@ -33,6 +34,7 @@ pub fn attach_context_to_message(
|
||||||
context: impl IntoIterator<Item = Context>,
|
context: impl IntoIterator<Item = Context>,
|
||||||
) {
|
) {
|
||||||
let mut file_context = String::new();
|
let mut file_context = String::new();
|
||||||
|
let mut directory_context = String::new();
|
||||||
let mut fetch_context = String::new();
|
let mut fetch_context = String::new();
|
||||||
let mut thread_context = String::new();
|
let mut thread_context = String::new();
|
||||||
|
|
||||||
|
@ -42,6 +44,10 @@ pub fn attach_context_to_message(
|
||||||
file_context.push_str(&context.text);
|
file_context.push_str(&context.text);
|
||||||
file_context.push('\n');
|
file_context.push('\n');
|
||||||
}
|
}
|
||||||
|
ContextKind::Directory => {
|
||||||
|
directory_context.push_str(&context.text);
|
||||||
|
directory_context.push('\n');
|
||||||
|
}
|
||||||
ContextKind::FetchedUrl => {
|
ContextKind::FetchedUrl => {
|
||||||
fetch_context.push_str(&context.name);
|
fetch_context.push_str(&context.name);
|
||||||
fetch_context.push('\n');
|
fetch_context.push('\n');
|
||||||
|
@ -63,6 +69,11 @@ pub fn attach_context_to_message(
|
||||||
context_text.push_str(&file_context);
|
context_text.push_str(&file_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !directory_context.is_empty() {
|
||||||
|
context_text.push_str("The following directories are available:\n");
|
||||||
|
context_text.push_str(&directory_context);
|
||||||
|
}
|
||||||
|
|
||||||
if !fetch_context.is_empty() {
|
if !fetch_context.is_empty() {
|
||||||
context_text.push_str("The following fetched results are available\n");
|
context_text.push_str("The following fetched results are available\n");
|
||||||
context_text.push_str(&fetch_context);
|
context_text.push_str(&fetch_context);
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
mod directory_context_picker;
|
||||||
mod fetch_context_picker;
|
mod fetch_context_picker;
|
||||||
mod file_context_picker;
|
mod file_context_picker;
|
||||||
mod thread_context_picker;
|
mod thread_context_picker;
|
||||||
|
@ -14,6 +15,7 @@ use util::ResultExt;
|
||||||
use workspace::Workspace;
|
use workspace::Workspace;
|
||||||
|
|
||||||
use crate::context::ContextKind;
|
use crate::context::ContextKind;
|
||||||
|
use crate::context_picker::directory_context_picker::DirectoryContextPicker;
|
||||||
use crate::context_picker::fetch_context_picker::FetchContextPicker;
|
use crate::context_picker::fetch_context_picker::FetchContextPicker;
|
||||||
use crate::context_picker::file_context_picker::FileContextPicker;
|
use crate::context_picker::file_context_picker::FileContextPicker;
|
||||||
use crate::context_picker::thread_context_picker::ThreadContextPicker;
|
use crate::context_picker::thread_context_picker::ThreadContextPicker;
|
||||||
|
@ -24,6 +26,7 @@ use crate::thread_store::ThreadStore;
|
||||||
enum ContextPickerMode {
|
enum ContextPickerMode {
|
||||||
Default,
|
Default,
|
||||||
File(View<FileContextPicker>),
|
File(View<FileContextPicker>),
|
||||||
|
Directory(View<DirectoryContextPicker>),
|
||||||
Fetch(View<FetchContextPicker>),
|
Fetch(View<FetchContextPicker>),
|
||||||
Thread(View<ThreadContextPicker>),
|
Thread(View<ThreadContextPicker>),
|
||||||
}
|
}
|
||||||
|
@ -46,6 +49,11 @@ impl ContextPicker {
|
||||||
kind: ContextKind::File,
|
kind: ContextKind::File,
|
||||||
icon: IconName::File,
|
icon: IconName::File,
|
||||||
},
|
},
|
||||||
|
ContextPickerEntry {
|
||||||
|
name: "Folder".into(),
|
||||||
|
kind: ContextKind::Directory,
|
||||||
|
icon: IconName::Folder,
|
||||||
|
},
|
||||||
ContextPickerEntry {
|
ContextPickerEntry {
|
||||||
name: "Fetch".into(),
|
name: "Fetch".into(),
|
||||||
kind: ContextKind::FetchedUrl,
|
kind: ContextKind::FetchedUrl,
|
||||||
|
@ -92,6 +100,7 @@ impl FocusableView for ContextPicker {
|
||||||
match &self.mode {
|
match &self.mode {
|
||||||
ContextPickerMode::Default => self.picker.focus_handle(cx),
|
ContextPickerMode::Default => self.picker.focus_handle(cx),
|
||||||
ContextPickerMode::File(file_picker) => file_picker.focus_handle(cx),
|
ContextPickerMode::File(file_picker) => file_picker.focus_handle(cx),
|
||||||
|
ContextPickerMode::Directory(directory_picker) => directory_picker.focus_handle(cx),
|
||||||
ContextPickerMode::Fetch(fetch_picker) => fetch_picker.focus_handle(cx),
|
ContextPickerMode::Fetch(fetch_picker) => fetch_picker.focus_handle(cx),
|
||||||
ContextPickerMode::Thread(thread_picker) => thread_picker.focus_handle(cx),
|
ContextPickerMode::Thread(thread_picker) => thread_picker.focus_handle(cx),
|
||||||
}
|
}
|
||||||
|
@ -106,6 +115,9 @@ impl Render for ContextPicker {
|
||||||
.map(|parent| match &self.mode {
|
.map(|parent| match &self.mode {
|
||||||
ContextPickerMode::Default => parent.child(self.picker.clone()),
|
ContextPickerMode::Default => parent.child(self.picker.clone()),
|
||||||
ContextPickerMode::File(file_picker) => parent.child(file_picker.clone()),
|
ContextPickerMode::File(file_picker) => parent.child(file_picker.clone()),
|
||||||
|
ContextPickerMode::Directory(directory_picker) => {
|
||||||
|
parent.child(directory_picker.clone())
|
||||||
|
}
|
||||||
ContextPickerMode::Fetch(fetch_picker) => parent.child(fetch_picker.clone()),
|
ContextPickerMode::Fetch(fetch_picker) => parent.child(fetch_picker.clone()),
|
||||||
ContextPickerMode::Thread(thread_picker) => parent.child(thread_picker.clone()),
|
ContextPickerMode::Thread(thread_picker) => parent.child(thread_picker.clone()),
|
||||||
})
|
})
|
||||||
|
@ -167,6 +179,16 @@ impl PickerDelegate for ContextPickerDelegate {
|
||||||
)
|
)
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
ContextKind::Directory => {
|
||||||
|
this.mode = ContextPickerMode::Directory(cx.new_view(|cx| {
|
||||||
|
DirectoryContextPicker::new(
|
||||||
|
self.context_picker.clone(),
|
||||||
|
self.workspace.clone(),
|
||||||
|
self.context_store.clone(),
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
}));
|
||||||
|
}
|
||||||
ContextKind::FetchedUrl => {
|
ContextKind::FetchedUrl => {
|
||||||
this.mode = ContextPickerMode::Fetch(cx.new_view(|cx| {
|
this.mode = ContextPickerMode::Fetch(cx.new_view(|cx| {
|
||||||
FetchContextPicker::new(
|
FetchContextPicker::new(
|
||||||
|
@ -202,6 +224,7 @@ impl PickerDelegate for ContextPickerDelegate {
|
||||||
.update(cx, |this, cx| match this.mode {
|
.update(cx, |this, cx| match this.mode {
|
||||||
ContextPickerMode::Default => cx.emit(DismissEvent),
|
ContextPickerMode::Default => cx.emit(DismissEvent),
|
||||||
ContextPickerMode::File(_)
|
ContextPickerMode::File(_)
|
||||||
|
| ContextPickerMode::Directory(_)
|
||||||
| ContextPickerMode::Fetch(_)
|
| ContextPickerMode::Fetch(_)
|
||||||
| ContextPickerMode::Thread(_) => {}
|
| ContextPickerMode::Thread(_) => {}
|
||||||
})
|
})
|
||||||
|
|
117
crates/assistant2/src/context_picker/directory_context_picker.rs
Normal file
117
crates/assistant2/src/context_picker/directory_context_picker.rs
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
// TODO: Remove this once we've implemented the functionality.
|
||||||
|
#![allow(unused)]
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use fuzzy::PathMatch;
|
||||||
|
use gpui::{AppContext, DismissEvent, FocusHandle, FocusableView, Task, View, WeakModel, WeakView};
|
||||||
|
use picker::{Picker, PickerDelegate};
|
||||||
|
use project::{PathMatchCandidateSet, WorktreeId};
|
||||||
|
use ui::{prelude::*, ListItem};
|
||||||
|
use util::ResultExt as _;
|
||||||
|
use workspace::Workspace;
|
||||||
|
|
||||||
|
use crate::context_picker::ContextPicker;
|
||||||
|
use crate::context_store::ContextStore;
|
||||||
|
|
||||||
|
pub struct DirectoryContextPicker {
|
||||||
|
picker: View<Picker<DirectoryContextPickerDelegate>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DirectoryContextPicker {
|
||||||
|
pub fn new(
|
||||||
|
context_picker: WeakView<ContextPicker>,
|
||||||
|
workspace: WeakView<Workspace>,
|
||||||
|
context_store: WeakModel<ContextStore>,
|
||||||
|
cx: &mut ViewContext<Self>,
|
||||||
|
) -> Self {
|
||||||
|
let delegate =
|
||||||
|
DirectoryContextPickerDelegate::new(context_picker, workspace, context_store);
|
||||||
|
let picker = cx.new_view(|cx| Picker::uniform_list(delegate, cx));
|
||||||
|
|
||||||
|
Self { picker }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FocusableView for DirectoryContextPicker {
|
||||||
|
fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
|
||||||
|
self.picker.focus_handle(cx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Render for DirectoryContextPicker {
|
||||||
|
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||||
|
self.picker.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DirectoryContextPickerDelegate {
|
||||||
|
context_picker: WeakView<ContextPicker>,
|
||||||
|
workspace: WeakView<Workspace>,
|
||||||
|
context_store: WeakModel<ContextStore>,
|
||||||
|
matches: Vec<PathMatch>,
|
||||||
|
selected_index: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DirectoryContextPickerDelegate {
|
||||||
|
pub fn new(
|
||||||
|
context_picker: WeakView<ContextPicker>,
|
||||||
|
workspace: WeakView<Workspace>,
|
||||||
|
context_store: WeakModel<ContextStore>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
context_picker,
|
||||||
|
workspace,
|
||||||
|
context_store,
|
||||||
|
matches: Vec::new(),
|
||||||
|
selected_index: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PickerDelegate for DirectoryContextPickerDelegate {
|
||||||
|
type ListItem = ListItem;
|
||||||
|
|
||||||
|
fn match_count(&self) -> usize {
|
||||||
|
self.matches.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn selected_index(&self) -> usize {
|
||||||
|
self.selected_index
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_selected_index(&mut self, ix: usize, cx: &mut ViewContext<Picker<Self>>) {
|
||||||
|
self.selected_index = ix;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
|
||||||
|
"Search folders…".into()
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
Task::ready(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn confirm(&mut self, _secondary: bool, _cx: &mut ViewContext<Picker<Self>>) {
|
||||||
|
// TODO: Implement this once we fix the issues with the file context picker.
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {
|
||||||
|
self.context_picker
|
||||||
|
.update(cx, |this, cx| {
|
||||||
|
this.reset_mode();
|
||||||
|
cx.emit(DismissEvent);
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_match(
|
||||||
|
&self,
|
||||||
|
_ix: usize,
|
||||||
|
_selected: bool,
|
||||||
|
_cx: &mut ViewContext<Picker<Self>>,
|
||||||
|
) -> Option<Self::ListItem> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue