assistant2: Add keybinding for "Remove All Context" action (#22783)

Danilo Leal , Agus Zubiaga , and Marshall Bowers created

Ensuring all of the assistant 2 actions have keybindings.

Release Notes:

- N/A

---------

Co-authored-by: Agus Zubiaga <hi@aguz.me>
Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>

Change summary

assets/keymaps/default-macos.json             |  4 ++
crates/assistant2/src/assistant.rs            |  1 
crates/assistant2/src/context_strip.rs        | 27 +++++++++++++------
crates/assistant2/src/inline_prompt_editor.rs | 15 +++++++++--
crates/assistant2/src/message_editor.rs       |  8 +++++
5 files changed, 41 insertions(+), 14 deletions(-)

Detailed changes

assets/keymaps/default-macos.json 🔗

@@ -227,7 +227,8 @@
       "cmd-n": "assistant2::NewThread",
       "cmd-shift-h": "assistant2::OpenHistory",
       "cmd-shift-m": "assistant2::ToggleModelSelector",
-      "cmd-shift-a": "assistant2::ToggleContextPicker"
+      "cmd-shift-a": "assistant2::ToggleContextPicker",
+      "cmd-alt-e": "assistant2::RemoveAllContext"
     }
   },
   {
@@ -615,6 +616,7 @@
     "use_key_equivalents": true,
     "bindings": {
       "cmd-shift-a": "assistant2::ToggleContextPicker",
+      "cmd-alt-e": "assistant2::RemoveAllContext",
       "ctrl-[": "assistant::CyclePreviousInlineAssist",
       "ctrl-]": "assistant::CycleNextInlineAssist"
     }

crates/assistant2/src/context_strip.rs 🔗

@@ -15,7 +15,7 @@ use crate::context_store::ContextStore;
 use crate::thread::Thread;
 use crate::thread_store::ThreadStore;
 use crate::ui::ContextPill;
-use crate::{AssistantPanel, ToggleContextPicker};
+use crate::{AssistantPanel, RemoveAllContext, ToggleContextPicker};
 
 pub struct ContextStrip {
     context_store: Model<ContextStore>,
@@ -226,14 +226,23 @@ impl Render for ContextStrip {
                     parent.child(
                         IconButton::new("remove-all-context", IconName::Eraser)
                             .icon_size(IconSize::Small)
-                            .tooltip(move |cx| Tooltip::text("Remove All Context", cx))
-                            .on_click({
-                                let context_store = self.context_store.clone();
-                                cx.listener(move |_this, _event, cx| {
-                                    context_store.update(cx, |this, _cx| this.clear());
-                                    cx.notify();
-                                })
-                            }),
+                            .tooltip({
+                                let focus_handle = focus_handle.clone();
+                                move |cx| {
+                                    Tooltip::for_action_in(
+                                        "Remove All Context",
+                                        &RemoveAllContext,
+                                        &focus_handle,
+                                        cx,
+                                    )
+                                }
+                            })
+                            .on_click(cx.listener({
+                                let focus_handle = focus_handle.clone();
+                                move |_this, _event, cx| {
+                                    focus_handle.dispatch_action(&RemoveAllContext, cx);
+                                }
+                            })),
                     )
                 }
             })

crates/assistant2/src/inline_prompt_editor.rs 🔗

@@ -6,7 +6,7 @@ use crate::context_strip::{ContextStrip, ContextStripEvent, SuggestContextKind};
 use crate::terminal_codegen::TerminalCodegen;
 use crate::thread_store::ThreadStore;
 use crate::{CycleNextInlineAssist, CyclePreviousInlineAssist};
-use crate::{ToggleContextPicker, ToggleModelSelector};
+use crate::{RemoveAllContext, ToggleContextPicker, ToggleModelSelector};
 use client::ErrorExt;
 use collections::VecDeque;
 use editor::{
@@ -37,6 +37,7 @@ use workspace::Workspace;
 pub struct PromptEditor<T> {
     pub editor: View<Editor>,
     mode: PromptEditorMode,
+    context_store: Model<ContextStore>,
     context_strip: View<ContextStrip>,
     context_picker_menu_handle: PopoverMenuHandle<ContextPicker>,
     model_selector: View<AssistantModelSelector>,
@@ -109,6 +110,7 @@ impl<T: 'static> Render for PromptEditor<T> {
                     .on_action(cx.listener(Self::cancel))
                     .on_action(cx.listener(Self::move_up))
                     .on_action(cx.listener(Self::move_down))
+                    .on_action(cx.listener(Self::remove_all_context))
                     .capture_action(cx.listener(Self::cycle_prev))
                     .capture_action(cx.listener(Self::cycle_next))
                     .child(
@@ -339,6 +341,11 @@ impl<T: 'static> PromptEditor<T> {
         self.model_selector_menu_handle.toggle(cx);
     }
 
+    pub fn remove_all_context(&mut self, _: &RemoveAllContext, cx: &mut ViewContext<Self>) {
+        self.context_store.update(cx, |store, _cx| store.clear());
+        cx.notify();
+    }
+
     fn cancel(&mut self, _: &editor::actions::Cancel, cx: &mut ViewContext<Self>) {
         match self.codegen_status(cx) {
             CodegenStatus::Idle | CodegenStatus::Done | CodegenStatus::Error(_) => {
@@ -816,7 +823,7 @@ impl PromptEditor<BufferCodegen> {
 
         let context_strip = cx.new_view(|cx| {
             ContextStrip::new(
-                context_store,
+                context_store.clone(),
                 workspace.clone(),
                 thread_store.clone(),
                 prompt_editor.focus_handle(cx),
@@ -831,6 +838,7 @@ impl PromptEditor<BufferCodegen> {
 
         let mut this: PromptEditor<BufferCodegen> = PromptEditor {
             editor: prompt_editor.clone(),
+            context_store,
             context_strip,
             context_picker_menu_handle,
             model_selector: cx.new_view(|cx| {
@@ -962,7 +970,7 @@ impl PromptEditor<TerminalCodegen> {
 
         let context_strip = cx.new_view(|cx| {
             ContextStrip::new(
-                context_store,
+                context_store.clone(),
                 workspace.clone(),
                 thread_store.clone(),
                 prompt_editor.focus_handle(cx),
@@ -977,6 +985,7 @@ impl PromptEditor<TerminalCodegen> {
 
         let mut this = Self {
             editor: prompt_editor.clone(),
+            context_store,
             context_strip,
             context_picker_menu_handle,
             model_selector: cx.new_view(|cx| {

crates/assistant2/src/message_editor.rs 🔗

@@ -23,7 +23,7 @@ use crate::context_store::ContextStore;
 use crate::context_strip::{ContextStrip, ContextStripEvent, SuggestContextKind};
 use crate::thread::{RequestKind, Thread};
 use crate::thread_store::ThreadStore;
-use crate::{Chat, ToggleContextPicker, ToggleModelSelector};
+use crate::{Chat, RemoveAllContext, ToggleContextPicker, ToggleModelSelector};
 
 pub struct MessageEditor {
     thread: Model<Thread>,
@@ -116,6 +116,11 @@ impl MessageEditor {
         self.context_picker_menu_handle.toggle(cx);
     }
 
+    pub fn remove_all_context(&mut self, _: &RemoveAllContext, cx: &mut ViewContext<Self>) {
+        self.context_store.update(cx, |store, _cx| store.clear());
+        cx.notify();
+    }
+
     fn chat(&mut self, _: &Chat, cx: &mut ViewContext<Self>) {
         self.send_to_model(RequestKind::Chat, cx);
     }
@@ -233,6 +238,7 @@ impl Render for MessageEditor {
             .on_action(cx.listener(Self::chat))
             .on_action(cx.listener(Self::toggle_model_selector))
             .on_action(cx.listener(Self::toggle_context_picker))
+            .on_action(cx.listener(Self::remove_all_context))
             .size_full()
             .gap_2()
             .p_2()