Skip to content

Commit

Permalink
assistant2: Sketch in directory context picker (#22148)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
maxdeviant authored Dec 17, 2024
1 parent 68e3d79 commit b17f208
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 0 deletions.
11 changes: 11 additions & 0 deletions crates/assistant2/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub struct Context {
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum ContextKind {
File,
Directory,
FetchedUrl,
Thread,
}
Expand All @@ -33,6 +34,7 @@ pub fn attach_context_to_message(
context: impl IntoIterator<Item = Context>,
) {
let mut file_context = String::new();
let mut directory_context = String::new();
let mut fetch_context = String::new();
let mut thread_context = String::new();

Expand All @@ -42,6 +44,10 @@ pub fn attach_context_to_message(
file_context.push_str(&context.text);
file_context.push('\n');
}
ContextKind::Directory => {
directory_context.push_str(&context.text);
directory_context.push('\n');
}
ContextKind::FetchedUrl => {
fetch_context.push_str(&context.name);
fetch_context.push('\n');
Expand All @@ -63,6 +69,11 @@ pub fn attach_context_to_message(
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() {
context_text.push_str("The following fetched results are available\n");
context_text.push_str(&fetch_context);
Expand Down
23 changes: 23 additions & 0 deletions crates/assistant2/src/context_picker.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod directory_context_picker;
mod fetch_context_picker;
mod file_context_picker;
mod thread_context_picker;
Expand All @@ -14,6 +15,7 @@ use util::ResultExt;
use workspace::Workspace;

use crate::context::ContextKind;
use crate::context_picker::directory_context_picker::DirectoryContextPicker;
use crate::context_picker::fetch_context_picker::FetchContextPicker;
use crate::context_picker::file_context_picker::FileContextPicker;
use crate::context_picker::thread_context_picker::ThreadContextPicker;
Expand All @@ -24,6 +26,7 @@ use crate::thread_store::ThreadStore;
enum ContextPickerMode {
Default,
File(View<FileContextPicker>),
Directory(View<DirectoryContextPicker>),
Fetch(View<FetchContextPicker>),
Thread(View<ThreadContextPicker>),
}
Expand All @@ -46,6 +49,11 @@ impl ContextPicker {
kind: ContextKind::File,
icon: IconName::File,
},
ContextPickerEntry {
name: "Folder".into(),
kind: ContextKind::Directory,
icon: IconName::Folder,
},
ContextPickerEntry {
name: "Fetch".into(),
kind: ContextKind::FetchedUrl,
Expand Down Expand Up @@ -92,6 +100,7 @@ impl FocusableView for ContextPicker {
match &self.mode {
ContextPickerMode::Default => self.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::Thread(thread_picker) => thread_picker.focus_handle(cx),
}
Expand All @@ -106,6 +115,9 @@ impl Render for ContextPicker {
.map(|parent| match &self.mode {
ContextPickerMode::Default => parent.child(self.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::Thread(thread_picker) => parent.child(thread_picker.clone()),
})
Expand Down Expand Up @@ -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 => {
this.mode = ContextPickerMode::Fetch(cx.new_view(|cx| {
FetchContextPicker::new(
Expand Down Expand Up @@ -202,6 +224,7 @@ impl PickerDelegate for ContextPickerDelegate {
.update(cx, |this, cx| match this.mode {
ContextPickerMode::Default => cx.emit(DismissEvent),
ContextPickerMode::File(_)
| ContextPickerMode::Directory(_)
| ContextPickerMode::Fetch(_)
| ContextPickerMode::Thread(_) => {}
})
Expand Down
117 changes: 117 additions & 0 deletions crates/assistant2/src/context_picker/directory_context_picker.rs
Original file line number Diff line number Diff line change
@@ -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
}
}

0 comments on commit b17f208

Please sign in to comment.