acp: Rename assistant::QuoteSelection
and support it in agent2 threads (#36628)
Release Notes: - N/A
This commit is contained in:
parent
b070dc66b3
commit
1ee07a4baf
11 changed files with 148 additions and 79 deletions
|
@ -138,7 +138,7 @@
|
|||
"find": "buffer_search::Deploy",
|
||||
"ctrl-f": "buffer_search::Deploy",
|
||||
"ctrl-h": "buffer_search::DeployReplace",
|
||||
"ctrl->": "assistant::QuoteSelection",
|
||||
"ctrl->": "agent::QuoteSelection",
|
||||
"ctrl-<": "assistant::InsertIntoEditor",
|
||||
"ctrl-alt-e": "editor::SelectEnclosingSymbol",
|
||||
"ctrl-shift-backspace": "editor::GoToPreviousChange",
|
||||
|
@ -241,7 +241,7 @@
|
|||
"ctrl-shift-i": "agent::ToggleOptionsMenu",
|
||||
"ctrl-alt-shift-n": "agent::ToggleNewThreadMenu",
|
||||
"shift-alt-escape": "agent::ExpandMessageEditor",
|
||||
"ctrl->": "assistant::QuoteSelection",
|
||||
"ctrl->": "agent::QuoteSelection",
|
||||
"ctrl-alt-e": "agent::RemoveAllContext",
|
||||
"ctrl-shift-e": "project_panel::ToggleFocus",
|
||||
"ctrl-shift-enter": "agent::ContinueThread",
|
||||
|
|
|
@ -162,7 +162,7 @@
|
|||
"cmd-alt-f": "buffer_search::DeployReplace",
|
||||
"cmd-alt-l": ["buffer_search::Deploy", { "selection_search_enabled": true }],
|
||||
"cmd-e": ["buffer_search::Deploy", { "focus": false }],
|
||||
"cmd->": "assistant::QuoteSelection",
|
||||
"cmd->": "agent::QuoteSelection",
|
||||
"cmd-<": "assistant::InsertIntoEditor",
|
||||
"cmd-alt-e": "editor::SelectEnclosingSymbol",
|
||||
"alt-enter": "editor::OpenSelectionsInMultibuffer"
|
||||
|
@ -281,7 +281,7 @@
|
|||
"cmd-shift-i": "agent::ToggleOptionsMenu",
|
||||
"cmd-alt-shift-n": "agent::ToggleNewThreadMenu",
|
||||
"shift-alt-escape": "agent::ExpandMessageEditor",
|
||||
"cmd->": "assistant::QuoteSelection",
|
||||
"cmd->": "agent::QuoteSelection",
|
||||
"cmd-alt-e": "agent::RemoveAllContext",
|
||||
"cmd-shift-e": "project_panel::ToggleFocus",
|
||||
"cmd-ctrl-b": "agent::ToggleBurnMode",
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
"bindings": {
|
||||
"ctrl-i": "agent::ToggleFocus",
|
||||
"ctrl-shift-i": "agent::ToggleFocus",
|
||||
"ctrl-shift-l": "assistant::QuoteSelection", // In cursor uses "Ask" mode
|
||||
"ctrl-l": "assistant::QuoteSelection", // In cursor uses "Agent" mode
|
||||
"ctrl-shift-l": "agent::QuoteSelection", // In cursor uses "Ask" mode
|
||||
"ctrl-l": "agent::QuoteSelection", // In cursor uses "Agent" mode
|
||||
"ctrl-k": "assistant::InlineAssist",
|
||||
"ctrl-shift-k": "assistant::InsertIntoEditor"
|
||||
}
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
"bindings": {
|
||||
"cmd-i": "agent::ToggleFocus",
|
||||
"cmd-shift-i": "agent::ToggleFocus",
|
||||
"cmd-shift-l": "assistant::QuoteSelection", // In cursor uses "Ask" mode
|
||||
"cmd-l": "assistant::QuoteSelection", // In cursor uses "Agent" mode
|
||||
"cmd-shift-l": "agent::QuoteSelection", // In cursor uses "Ask" mode
|
||||
"cmd-l": "agent::QuoteSelection", // In cursor uses "Agent" mode
|
||||
"cmd-k": "assistant::InlineAssist",
|
||||
"cmd-shift-k": "assistant::InsertIntoEditor"
|
||||
}
|
||||
|
|
|
@ -108,62 +108,7 @@ impl ContextPickerCompletionProvider {
|
|||
confirm: Some(Arc::new(|_, _, _| true)),
|
||||
}),
|
||||
ContextPickerEntry::Action(action) => {
|
||||
let (new_text, on_action) = match action {
|
||||
ContextPickerAction::AddSelections => {
|
||||
const PLACEHOLDER: &str = "selection ";
|
||||
let selections = selection_ranges(workspace, cx)
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(ix, (buffer, range))| {
|
||||
(
|
||||
buffer,
|
||||
range,
|
||||
(PLACEHOLDER.len() * ix)..(PLACEHOLDER.len() * (ix + 1) - 1),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let new_text: String = PLACEHOLDER.repeat(selections.len());
|
||||
|
||||
let callback = Arc::new({
|
||||
let source_range = source_range.clone();
|
||||
move |_, window: &mut Window, cx: &mut App| {
|
||||
let selections = selections.clone();
|
||||
let message_editor = message_editor.clone();
|
||||
let source_range = source_range.clone();
|
||||
window.defer(cx, move |window, cx| {
|
||||
message_editor
|
||||
.update(cx, |message_editor, cx| {
|
||||
message_editor.confirm_mention_for_selection(
|
||||
source_range,
|
||||
selections,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.ok();
|
||||
});
|
||||
false
|
||||
}
|
||||
});
|
||||
|
||||
(new_text, callback)
|
||||
}
|
||||
};
|
||||
|
||||
Some(Completion {
|
||||
replace_range: source_range,
|
||||
new_text,
|
||||
label: CodeLabel::plain(action.label().to_string(), None),
|
||||
icon_path: Some(action.icon().path().into()),
|
||||
documentation: None,
|
||||
source: project::CompletionSource::Custom,
|
||||
insert_text_mode: None,
|
||||
// This ensures that when a user accepts this completion, the
|
||||
// completion menu will still be shown after "@category " is
|
||||
// inserted
|
||||
confirm: Some(on_action),
|
||||
})
|
||||
Self::completion_for_action(action, source_range, message_editor, workspace, cx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -359,6 +304,71 @@ impl ContextPickerCompletionProvider {
|
|||
})
|
||||
}
|
||||
|
||||
pub(crate) fn completion_for_action(
|
||||
action: ContextPickerAction,
|
||||
source_range: Range<Anchor>,
|
||||
message_editor: WeakEntity<MessageEditor>,
|
||||
workspace: &Entity<Workspace>,
|
||||
cx: &mut App,
|
||||
) -> Option<Completion> {
|
||||
let (new_text, on_action) = match action {
|
||||
ContextPickerAction::AddSelections => {
|
||||
const PLACEHOLDER: &str = "selection ";
|
||||
let selections = selection_ranges(workspace, cx)
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(ix, (buffer, range))| {
|
||||
(
|
||||
buffer,
|
||||
range,
|
||||
(PLACEHOLDER.len() * ix)..(PLACEHOLDER.len() * (ix + 1) - 1),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let new_text: String = PLACEHOLDER.repeat(selections.len());
|
||||
|
||||
let callback = Arc::new({
|
||||
let source_range = source_range.clone();
|
||||
move |_, window: &mut Window, cx: &mut App| {
|
||||
let selections = selections.clone();
|
||||
let message_editor = message_editor.clone();
|
||||
let source_range = source_range.clone();
|
||||
window.defer(cx, move |window, cx| {
|
||||
message_editor
|
||||
.update(cx, |message_editor, cx| {
|
||||
message_editor.confirm_mention_for_selection(
|
||||
source_range,
|
||||
selections,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.ok();
|
||||
});
|
||||
false
|
||||
}
|
||||
});
|
||||
|
||||
(new_text, callback)
|
||||
}
|
||||
};
|
||||
|
||||
Some(Completion {
|
||||
replace_range: source_range,
|
||||
new_text,
|
||||
label: CodeLabel::plain(action.label().to_string(), None),
|
||||
icon_path: Some(action.icon().path().into()),
|
||||
documentation: None,
|
||||
source: project::CompletionSource::Custom,
|
||||
insert_text_mode: None,
|
||||
// This ensures that when a user accepts this completion, the
|
||||
// completion menu will still be shown after "@category " is
|
||||
// inserted
|
||||
confirm: Some(on_action),
|
||||
})
|
||||
}
|
||||
|
||||
fn search(
|
||||
&self,
|
||||
mode: Option<ContextPickerMode>,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
acp::completion_provider::ContextPickerCompletionProvider,
|
||||
context_picker::fetch_context_picker::fetch_url_content,
|
||||
context_picker::{ContextPickerAction, fetch_context_picker::fetch_url_content},
|
||||
};
|
||||
use acp_thread::{MentionUri, selection_name};
|
||||
use agent_client_protocol as acp;
|
||||
|
@ -27,7 +27,7 @@ use gpui::{
|
|||
};
|
||||
use language::{Buffer, Language};
|
||||
use language_model::LanguageModelImage;
|
||||
use project::{Project, ProjectPath, Worktree};
|
||||
use project::{CompletionIntent, Project, ProjectItem, ProjectPath, Worktree};
|
||||
use prompt_store::PromptStore;
|
||||
use rope::Point;
|
||||
use settings::Settings;
|
||||
|
@ -561,21 +561,24 @@ impl MessageEditor {
|
|||
let range = snapshot.anchor_after(offset + range_to_fold.start)
|
||||
..snapshot.anchor_after(offset + range_to_fold.end);
|
||||
|
||||
let path = buffer
|
||||
.read(cx)
|
||||
.file()
|
||||
.map_or(PathBuf::from("untitled"), |file| file.path().to_path_buf());
|
||||
// TODO support selections from buffers with no path
|
||||
let Some(project_path) = buffer.read(cx).project_path(cx) else {
|
||||
continue;
|
||||
};
|
||||
let Some(abs_path) = self.project.read(cx).absolute_path(&project_path, cx) else {
|
||||
continue;
|
||||
};
|
||||
let snapshot = buffer.read(cx).snapshot();
|
||||
|
||||
let point_range = selection_range.to_point(&snapshot);
|
||||
let line_range = point_range.start.row..point_range.end.row;
|
||||
|
||||
let uri = MentionUri::Selection {
|
||||
path: path.clone(),
|
||||
path: abs_path.clone(),
|
||||
line_range: line_range.clone(),
|
||||
};
|
||||
let crease = crate::context_picker::crease_for_mention(
|
||||
selection_name(&path, &line_range).into(),
|
||||
selection_name(&abs_path, &line_range).into(),
|
||||
uri.icon_path(cx),
|
||||
range,
|
||||
self.editor.downgrade(),
|
||||
|
@ -587,8 +590,7 @@ impl MessageEditor {
|
|||
crease_ids.first().copied().unwrap()
|
||||
});
|
||||
|
||||
self.mention_set
|
||||
.insert_uri(crease_id, MentionUri::Selection { path, line_range });
|
||||
self.mention_set.insert_uri(crease_id, uri);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -948,6 +950,38 @@ impl MessageEditor {
|
|||
.detach();
|
||||
}
|
||||
|
||||
pub fn insert_selections(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let buffer = self.editor.read(cx).buffer().clone();
|
||||
let Some(buffer) = buffer.read(cx).as_singleton() else {
|
||||
return;
|
||||
};
|
||||
let anchor = buffer.update(cx, |buffer, _cx| buffer.anchor_before(buffer.len()));
|
||||
let Some(workspace) = self.workspace.upgrade() else {
|
||||
return;
|
||||
};
|
||||
let Some(completion) = ContextPickerCompletionProvider::completion_for_action(
|
||||
ContextPickerAction::AddSelections,
|
||||
anchor..anchor,
|
||||
cx.weak_entity(),
|
||||
&workspace,
|
||||
cx,
|
||||
) else {
|
||||
return;
|
||||
};
|
||||
self.editor.update(cx, |message_editor, cx| {
|
||||
message_editor.edit(
|
||||
[(
|
||||
multi_buffer::Anchor::max()..multi_buffer::Anchor::max(),
|
||||
completion.new_text,
|
||||
)],
|
||||
cx,
|
||||
);
|
||||
});
|
||||
if let Some(confirm) = completion.confirm {
|
||||
confirm(CompletionIntent::Complete, window, cx);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_read_only(&mut self, read_only: bool, cx: &mut Context<Self>) {
|
||||
self.editor.update(cx, |message_editor, cx| {
|
||||
message_editor.set_read_only(read_only);
|
||||
|
|
|
@ -4097,6 +4097,12 @@ impl AcpThreadView {
|
|||
})
|
||||
}
|
||||
|
||||
pub(crate) fn insert_selections(&self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
self.message_editor.update(cx, |message_editor, cx| {
|
||||
message_editor.insert_selections(window, cx);
|
||||
})
|
||||
}
|
||||
|
||||
fn render_thread_retry_status_callout(
|
||||
&self,
|
||||
_window: &mut Window,
|
||||
|
|
|
@ -903,6 +903,16 @@ impl AgentPanel {
|
|||
}
|
||||
}
|
||||
|
||||
fn active_thread_view(&self) -> Option<&Entity<AcpThreadView>> {
|
||||
match &self.active_view {
|
||||
ActiveView::ExternalAgentThread { thread_view } => Some(thread_view),
|
||||
ActiveView::Thread { .. }
|
||||
| ActiveView::TextThread { .. }
|
||||
| ActiveView::History
|
||||
| ActiveView::Configuration => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn new_thread(&mut self, action: &NewThread, window: &mut Window, cx: &mut Context<Self>) {
|
||||
if cx.has_flag::<GeminiAndNativeFeatureFlag>() {
|
||||
return self.new_agent_thread(AgentType::NativeAgent, window, cx);
|
||||
|
@ -3882,7 +3892,11 @@ impl AgentPanelDelegate for ConcreteAssistantPanelDelegate {
|
|||
// Wait to create a new context until the workspace is no longer
|
||||
// being updated.
|
||||
cx.defer_in(window, move |panel, window, cx| {
|
||||
if let Some(message_editor) = panel.active_message_editor() {
|
||||
if let Some(thread_view) = panel.active_thread_view() {
|
||||
thread_view.update(cx, |thread_view, cx| {
|
||||
thread_view.insert_selections(window, cx);
|
||||
});
|
||||
} else if let Some(message_editor) = panel.active_message_editor() {
|
||||
message_editor.update(cx, |message_editor, cx| {
|
||||
message_editor.context_store().update(cx, |store, cx| {
|
||||
let buffer = buffer.read(cx);
|
||||
|
|
|
@ -128,6 +128,12 @@ actions!(
|
|||
]
|
||||
);
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Action)]
|
||||
#[action(namespace = agent)]
|
||||
#[action(deprecated_aliases = ["assistant::QuoteSelection"])]
|
||||
/// Quotes the current selection in the agent panel's message editor.
|
||||
pub struct QuoteSelection;
|
||||
|
||||
/// Creates a new conversation thread, optionally based on an existing thread.
|
||||
#[derive(Default, Clone, PartialEq, Deserialize, JsonSchema, Action)]
|
||||
#[action(namespace = agent)]
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::{
|
||||
QuoteSelection,
|
||||
language_model_selector::{LanguageModelSelector, language_model_selector},
|
||||
ui::BurnModeTooltip,
|
||||
};
|
||||
|
@ -89,8 +90,6 @@ actions!(
|
|||
CycleMessageRole,
|
||||
/// Inserts the selected text into the active editor.
|
||||
InsertIntoEditor,
|
||||
/// Quotes the current selection in the assistant conversation.
|
||||
QuoteSelection,
|
||||
/// Splits the conversation at the current cursor position.
|
||||
Split,
|
||||
]
|
||||
|
|
|
@ -16,7 +16,7 @@ To begin, type a message in a `You` block.
|
|||
|
||||
As you type, the remaining tokens count for the selected model is updated.
|
||||
|
||||
Inserting text from an editor is as simple as highlighting the text and running `assistant: quote selection` ({#kb assistant::QuoteSelection}); Zed will wrap it in a fenced code block if it is code.
|
||||
Inserting text from an editor is as simple as highlighting the text and running `agent: quote selection` ({#kb agent::QuoteSelection}); Zed will wrap it in a fenced code block if it is code.
|
||||
|
||||

|
||||
|
||||
|
@ -148,7 +148,7 @@ Usage: `/terminal [<number>]`
|
|||
|
||||
The `/selection` command inserts the selected text in the editor into the context. This is useful for referencing specific parts of your code.
|
||||
|
||||
This is equivalent to the `assistant: quote selection` command ({#kb assistant::QuoteSelection}).
|
||||
This is equivalent to the `agent: quote selection` command ({#kb agent::QuoteSelection}).
|
||||
|
||||
Usage: `/selection`
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue