Skip to content

Commit

Permalink
assistant2: Add keybinding to toggle ContextPicker (zed-industries#…
Browse files Browse the repository at this point in the history
…22124)

This PR adds an action and associated keybinding
(<kbd>Cmd+Shift+A</kbd>) to toggle the context picker.

This allows for adding context via the keyboard.

Release Notes:

- N/A
  • Loading branch information
maxdeviant authored and helgemahrt committed Dec 18, 2024
1 parent 4356ebd commit 26d268c
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 21 deletions.
4 changes: 3 additions & 1 deletion assets/keymaps/default-macos.json
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,8 @@
"bindings": {
"cmd-n": "assistant2::NewThread",
"cmd-shift-h": "assistant2::OpenHistory",
"cmd-shift-m": "assistant2::ToggleModelSelector"
"cmd-shift-m": "assistant2::ToggleModelSelector",
"cmd-shift-a": "assistant2::ToggleContextPicker"
}
},
{
Expand Down Expand Up @@ -618,6 +619,7 @@
"context": "PromptEditor",
"use_key_equivalents": true,
"bindings": {
"cmd-shift-a": "assistant2::ToggleContextPicker",
"ctrl-[": "assistant::CyclePreviousInlineAssist",
"ctrl-]": "assistant::CycleNextInlineAssist"
}
Expand Down
1 change: 1 addition & 0 deletions crates/assistant2/src/assistant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ actions!(
[
ToggleFocus,
NewThread,
ToggleContextPicker,
ToggleModelSelector,
OpenHistory,
Chat,
Expand Down
24 changes: 19 additions & 5 deletions crates/assistant2/src/context_strip.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
use std::rc::Rc;

use gpui::{Model, View, WeakModel, WeakView};
use gpui::{FocusHandle, Model, View, WeakModel, WeakView};
use ui::{prelude::*, PopoverMenu, PopoverMenuHandle, Tooltip};
use workspace::Workspace;

use crate::context_picker::ContextPicker;
use crate::context_store::ContextStore;
use crate::thread_store::ThreadStore;
use crate::ui::ContextPill;
use crate::ToggleContextPicker;

pub struct ContextStrip {
context_store: Model<ContextStore>,
context_picker: View<ContextPicker>,
pub(crate) context_picker_handle: PopoverMenuHandle<ContextPicker>,
context_picker_menu_handle: PopoverMenuHandle<ContextPicker>,
focus_handle: FocusHandle,
}

impl ContextStrip {
pub fn new(
context_store: Model<ContextStore>,
workspace: WeakView<Workspace>,
thread_store: Option<WeakModel<ThreadStore>>,
focus_handle: FocusHandle,
context_picker_menu_handle: PopoverMenuHandle<ContextPicker>,
cx: &mut ViewContext<Self>,
) -> Self {
Self {
Expand All @@ -32,7 +36,8 @@ impl ContextStrip {
cx,
)
}),
context_picker_handle: PopoverMenuHandle::default(),
context_picker_menu_handle,
focus_handle,
}
}
}
Expand All @@ -41,6 +46,7 @@ impl Render for ContextStrip {
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let context = self.context_store.read(cx).context();
let context_picker = self.context_picker.clone();
let focus_handle = self.focus_handle.clone();

h_flex()
.flex_wrap()
Expand All @@ -51,15 +57,23 @@ impl Render for ContextStrip {
.trigger(
IconButton::new("add-context", IconName::Plus)
.icon_size(IconSize::Small)
.style(ui::ButtonStyle::Filled),
.style(ui::ButtonStyle::Filled)
.tooltip(move |cx| {
Tooltip::for_action_in(
"Add Context",
&ToggleContextPicker,
&focus_handle,
cx,
)
}),
)
.attach(gpui::AnchorCorner::TopLeft)
.anchor(gpui::AnchorCorner::BottomLeft)
.offset(gpui::Point {
x: px(0.0),
y: px(-16.0),
})
.with_handle(self.context_picker_handle.clone()),
.with_handle(self.context_picker_menu_handle.clone()),
)
.children(context.iter().map(|context| {
ContextPill::new(context.clone()).on_remove({
Expand Down
26 changes: 22 additions & 4 deletions crates/assistant2/src/inline_assistant.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
use crate::context::attach_context_to_message;
use crate::context_picker::ContextPicker;
use crate::context_store::ContextStore;
use crate::context_strip::ContextStrip;
use crate::thread_store::ThreadStore;
use crate::AssistantPanel;
use crate::{
assistant_settings::AssistantSettings,
prompts::PromptBuilder,
streaming_diff::{CharOperation, LineDiff, LineOperation, StreamingDiff},
terminal_inline_assistant::TerminalInlineAssistant,
CycleNextInlineAssist, CyclePreviousInlineAssist, ToggleInlineAssist,
};
use crate::{AssistantPanel, ToggleContextPicker};
use anyhow::{Context as _, Result};
use client::{telemetry::Telemetry, ErrorExt};
use collections::{hash_map, HashMap, HashSet, VecDeque};
Expand Down Expand Up @@ -60,7 +61,9 @@ use telemetry_events::{AssistantEvent, AssistantKind, AssistantPhase};
use terminal_view::{terminal_panel::TerminalPanel, TerminalView};
use text::{OffsetRangeExt, ToPoint as _};
use theme::ThemeSettings;
use ui::{prelude::*, CheckboxWithLabel, IconButtonShape, KeyBinding, Popover, Tooltip};
use ui::{
prelude::*, CheckboxWithLabel, IconButtonShape, KeyBinding, Popover, PopoverMenuHandle, Tooltip,
};
use util::{RangeExt, ResultExt};
use workspace::{dock::Panel, ShowConfiguration};
use workspace::{notifications::NotificationId, ItemHandle, Toast, Workspace};
Expand Down Expand Up @@ -1486,6 +1489,7 @@ struct PromptEditor {
id: InlineAssistId,
editor: View<Editor>,
context_strip: View<ContextStrip>,
context_picker_menu_handle: PopoverMenuHandle<ContextPicker>,
language_model_selector: View<LanguageModelSelector>,
edited_since_done: bool,
gutter_dimensions: Arc<Mutex<GutterDimensions>>,
Expand Down Expand Up @@ -1607,6 +1611,7 @@ impl Render for PromptEditor {
.bg(cx.theme().colors().editor_background)
.block_mouse_down()
.cursor(CursorStyle::Arrow)
.on_action(cx.listener(Self::toggle_context_picker))
.on_action(cx.listener(Self::confirm))
.on_action(cx.listener(Self::cancel))
.on_action(cx.listener(Self::move_up))
Expand Down Expand Up @@ -1747,13 +1752,22 @@ impl PromptEditor {
editor.set_placeholder_text(Self::placeholder_text(codegen.read(cx)), cx);
editor
});
let context_picker_menu_handle = PopoverMenuHandle::default();

let mut this = Self {
id,
editor: prompt_editor,
editor: prompt_editor.clone(),
context_strip: cx.new_view(|cx| {
ContextStrip::new(context_store, workspace.clone(), thread_store.clone(), cx)
ContextStrip::new(
context_store,
workspace.clone(),
thread_store.clone(),
prompt_editor.focus_handle(cx),
context_picker_menu_handle.clone(),
cx,
)
}),
context_picker_menu_handle,
language_model_selector: cx.new_view(|cx| {
let fs = fs.clone();
LanguageModelSelector::new(
Expand Down Expand Up @@ -1911,6 +1925,10 @@ impl PromptEditor {
}
}

fn toggle_context_picker(&mut self, _: &ToggleContextPicker, cx: &mut ViewContext<Self>) {
self.context_picker_menu_handle.toggle(cx);
}

fn cancel(&mut self, _: &editor::actions::Cancel, cx: &mut ViewContext<Self>) {
match self.codegen.read(cx).status(cx) {
CodegenStatus::Idle | CodegenStatus::Done | CodegenStatus::Error(_) => {
Expand Down
29 changes: 21 additions & 8 deletions crates/assistant2/src/message_editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,19 @@ use ui::{
use workspace::Workspace;

use crate::assistant_settings::AssistantSettings;
use crate::context_picker::ContextPicker;
use crate::context_store::ContextStore;
use crate::context_strip::ContextStrip;
use crate::thread::{RequestKind, Thread};
use crate::thread_store::ThreadStore;
use crate::{Chat, ToggleModelSelector};
use crate::{Chat, ToggleContextPicker, ToggleModelSelector};

pub struct MessageEditor {
thread: Model<Thread>,
editor: View<Editor>,
context_store: Model<ContextStore>,
context_strip: View<ContextStrip>,
context_picker_menu_handle: PopoverMenuHandle<ContextPicker>,
language_model_selector: View<LanguageModelSelector>,
language_model_selector_menu_handle: PopoverMenuHandle<LanguageModelSelector>,
use_tools: bool,
Expand All @@ -39,25 +41,31 @@ impl MessageEditor {
cx: &mut ViewContext<Self>,
) -> Self {
let context_store = cx.new_model(|_cx| ContextStore::new());
let context_picker_menu_handle = PopoverMenuHandle::default();

let editor = cx.new_view(|cx| {
let mut editor = Editor::auto_height(80, cx);
editor.set_placeholder_text("Ask anything, @ to add context", cx);
editor.set_show_indent_guides(false, cx);

editor
});

Self {
thread,
editor: cx.new_view(|cx| {
let mut editor = Editor::auto_height(80, cx);
editor.set_placeholder_text("Ask anything, @ to add context", cx);
editor.set_show_indent_guides(false, cx);

editor
}),
editor: editor.clone(),
context_store: context_store.clone(),
context_strip: cx.new_view(|cx| {
ContextStrip::new(
context_store,
workspace.clone(),
Some(thread_store.clone()),
editor.focus_handle(cx),
context_picker_menu_handle.clone(),
cx,
)
}),
context_picker_menu_handle,
language_model_selector: cx.new_view(|cx| {
let fs = fs.clone();
LanguageModelSelector::new(
Expand All @@ -80,6 +88,10 @@ impl MessageEditor {
self.language_model_selector_menu_handle.toggle(cx);
}

fn toggle_context_picker(&mut self, _: &ToggleContextPicker, cx: &mut ViewContext<Self>) {
self.context_picker_menu_handle.toggle(cx);
}

fn chat(&mut self, _: &Chat, cx: &mut ViewContext<Self>) {
self.send_to_model(RequestKind::Chat, cx);
}
Expand Down Expand Up @@ -193,6 +205,7 @@ impl Render for MessageEditor {
.key_context("MessageEditor")
.on_action(cx.listener(Self::chat))
.on_action(cx.listener(Self::toggle_model_selector))
.on_action(cx.listener(Self::toggle_context_picker))
.size_full()
.gap_2()
.p_2()
Expand Down
24 changes: 21 additions & 3 deletions crates/assistant2/src/terminal_inline_assistant.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use crate::assistant_settings::AssistantSettings;
use crate::context::attach_context_to_message;
use crate::context_picker::ContextPicker;
use crate::context_store::ContextStore;
use crate::context_strip::ContextStrip;
use crate::prompts::PromptBuilder;
use crate::thread_store::ThreadStore;
use crate::ToggleContextPicker;
use anyhow::{Context as _, Result};
use client::telemetry::Telemetry;
use collections::{HashMap, VecDeque};
Expand All @@ -29,7 +31,7 @@ use telemetry_events::{AssistantEvent, AssistantKind, AssistantPhase};
use terminal::Terminal;
use terminal_view::TerminalView;
use theme::ThemeSettings;
use ui::{prelude::*, text_for_action, IconButtonShape, Tooltip};
use ui::{prelude::*, text_for_action, IconButtonShape, PopoverMenuHandle, Tooltip};
use util::ResultExt;
use workspace::{notifications::NotificationId, Toast, Workspace};

Expand Down Expand Up @@ -460,6 +462,7 @@ struct PromptEditor {
height_in_lines: u8,
editor: View<Editor>,
context_strip: View<ContextStrip>,
context_picker_menu_handle: PopoverMenuHandle<ContextPicker>,
language_model_selector: View<LanguageModelSelector>,
edited_since_done: bool,
prompt_history: VecDeque<String>,
Expand Down Expand Up @@ -580,7 +583,9 @@ impl Render for PromptEditor {
.size_full()
.child(
h_flex()
.key_context("PromptEditor")
.bg(cx.theme().colors().editor_background)
.on_action(cx.listener(Self::toggle_context_picker))
.on_action(cx.listener(Self::confirm))
.on_action(cx.listener(Self::secondary_confirm))
.on_action(cx.listener(Self::cancel))
Expand Down Expand Up @@ -674,14 +679,23 @@ impl PromptEditor {
editor.set_placeholder_text(Self::placeholder_text(cx), cx);
editor
});
let context_picker_menu_handle = PopoverMenuHandle::default();

let mut this = Self {
id,
height_in_lines: 1,
editor: prompt_editor,
editor: prompt_editor.clone(),
context_strip: cx.new_view(|cx| {
ContextStrip::new(context_store, workspace.clone(), thread_store.clone(), cx)
ContextStrip::new(
context_store,
workspace.clone(),
thread_store.clone(),
prompt_editor.focus_handle(cx),
context_picker_menu_handle.clone(),
cx,
)
}),
context_picker_menu_handle,
language_model_selector: cx.new_view(|cx| {
let fs = fs.clone();
LanguageModelSelector::new(
Expand Down Expand Up @@ -790,6 +804,10 @@ impl PromptEditor {
}
}

fn toggle_context_picker(&mut self, _: &ToggleContextPicker, cx: &mut ViewContext<Self>) {
self.context_picker_menu_handle.toggle(cx);
}

fn cancel(&mut self, _: &editor::actions::Cancel, cx: &mut ViewContext<Self>) {
match &self.codegen.read(cx).status {
CodegenStatus::Idle | CodegenStatus::Done | CodegenStatus::Error(_) => {
Expand Down

0 comments on commit 26d268c

Please sign in to comment.