Allow an initial prompt to be associated with inline assist (#14816)

Release Notes:

- Added the ability to create custom inline assist bindings that
pre-fill a prompt from your keymap, e.g.:
    ```json
    [
        {
            "context": "Editor && mode == full",
            "bindings": {
                "ctrl-shift-enter": [
                    "assistant::InlineAssist",
                    { "prompt": "Build a snake game" }
                ]
            }
        }
    ]
    ```

---------

Co-authored-by: Nathan <nathan@zed.dev>
This commit is contained in:
Antonio Scandurra 2024-07-19 17:13:48 +02:00 committed by GitHub
parent d61eaea4b9
commit 4c7f1032a4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 52 additions and 54 deletions

View file

@ -20,7 +20,7 @@ pub use completion_provider::*;
pub use context::*;
pub use context_store::*;
use fs::Fs;
use gpui::{actions, AppContext, Global, SharedString, UpdateGlobal};
use gpui::{actions, impl_actions, AppContext, Global, SharedString, UpdateGlobal};
use indexed_docs::IndexedDocsRegistry;
pub(crate) use inline_assistant::*;
pub(crate) use model_selector::*;
@ -48,7 +48,6 @@ actions!(
InsertIntoEditor,
ToggleFocus,
ResetKey,
InlineAssist,
InsertActivePrompt,
DeployHistory,
DeployPromptLibrary,
@ -58,6 +57,13 @@ actions!(
]
);
#[derive(Clone, Default, Deserialize, PartialEq)]
pub struct InlineAssist {
prompt: Option<String>,
}
impl_actions!(assistant, [InlineAssist]);
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct MessageId(clock::Lamport);

View file

@ -454,7 +454,7 @@ impl AssistantPanel {
pub fn inline_assist(
workspace: &mut Workspace,
_: &InlineAssist,
action: &InlineAssist,
cx: &mut ViewContext<Workspace>,
) {
let settings = AssistantSettings::get_global(cx);
@ -472,6 +472,7 @@ impl AssistantPanel {
return;
};
let initial_prompt = action.prompt.clone();
if assistant_panel.update(cx, |assistant, cx| assistant.is_authenticated(cx)) {
match inline_assist_target {
InlineAssistTarget::Editor(active_editor, include_context) => {
@ -480,6 +481,7 @@ impl AssistantPanel {
&active_editor,
Some(cx.view().downgrade()),
include_context.then_some(&assistant_panel),
initial_prompt,
cx,
)
})
@ -490,6 +492,7 @@ impl AssistantPanel {
&active_terminal,
Some(cx.view().downgrade()),
Some(&assistant_panel),
initial_prompt,
cx,
)
})
@ -514,6 +517,7 @@ impl AssistantPanel {
&active_editor,
Some(workspace),
assistant_panel.as_ref(),
initial_prompt,
cx,
)
})
@ -524,6 +528,7 @@ impl AssistantPanel {
&active_terminal,
Some(workspace),
assistant_panel.upgrade().as_ref(),
initial_prompt,
cx,
)
})

View file

@ -87,6 +87,7 @@ impl InlineAssistant {
editor: &View<Editor>,
workspace: Option<WeakView<Workspace>>,
assistant_panel: Option<&View<AssistantPanel>>,
initial_prompt: Option<String>,
cx: &mut WindowContext,
) {
let snapshot = editor.read(cx).buffer().read(cx).snapshot(cx);
@ -138,7 +139,8 @@ impl InlineAssistant {
}
let assist_group_id = self.next_assist_group_id.post_inc();
let prompt_buffer = cx.new_model(|cx| Buffer::local("", cx));
let prompt_buffer =
cx.new_model(|cx| Buffer::local(initial_prompt.unwrap_or_default(), cx));
let prompt_buffer = cx.new_model(|cx| MultiBuffer::singleton(prompt_buffer, cx));
let mut assists = Vec::new();

View file

@ -628,7 +628,7 @@ impl PromptLibrary {
self.picker.update(cx, |picker, cx| picker.focus(cx));
}
pub fn inline_assist(&mut self, _: &InlineAssist, cx: &mut ViewContext<Self>) {
pub fn inline_assist(&mut self, action: &InlineAssist, cx: &mut ViewContext<Self>) {
let Some(active_prompt_id) = self.active_prompt_id else {
cx.propagate();
return;
@ -636,9 +636,10 @@ impl PromptLibrary {
let prompt_editor = &self.prompt_editors[&active_prompt_id].body_editor;
let provider = CompletionProvider::global(cx);
let initial_prompt = action.prompt.clone();
if provider.is_authenticated() {
InlineAssistant::update_global(cx, |assistant, cx| {
assistant.assist(&prompt_editor, None, None, cx)
assistant.assist(&prompt_editor, None, None, initial_prompt, cx)
})
} else {
for window in cx.windows() {

View file

@ -73,11 +73,13 @@ impl TerminalInlineAssistant {
terminal_view: &View<TerminalView>,
workspace: Option<WeakView<Workspace>>,
assistant_panel: Option<&View<AssistantPanel>>,
initial_prompt: Option<String>,
cx: &mut WindowContext,
) {
let terminal = terminal_view.read(cx).terminal().clone();
let assist_id = self.next_assist_id.post_inc();
let prompt_buffer = cx.new_model(|cx| Buffer::local("", cx));
let prompt_buffer =
cx.new_model(|cx| Buffer::local(initial_prompt.unwrap_or_default(), cx));
let prompt_buffer = cx.new_model(|cx| MultiBuffer::singleton(prompt_buffer, cx));
let codegen = cx.new_model(|_| Codegen::new(terminal, self.telemetry.clone()));