Start on assistant::QuoteSelection
This commit is contained in:
parent
dc365472a6
commit
69e8a166e4
4 changed files with 101 additions and 3 deletions
|
@ -199,7 +199,8 @@
|
||||||
"context": "ContextEditor > Editor",
|
"context": "ContextEditor > Editor",
|
||||||
"bindings": {
|
"bindings": {
|
||||||
"cmd-enter": "assistant::Assist",
|
"cmd-enter": "assistant::Assist",
|
||||||
"escape": "assistant::CancelLastAssist"
|
"escape": "assistant::CancelLastAssist",
|
||||||
|
"cmd-?": "assistant::QuoteSelection"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,11 +19,15 @@ use workspace::{
|
||||||
pane, Pane, Workspace,
|
pane, Pane, Workspace,
|
||||||
};
|
};
|
||||||
|
|
||||||
actions!(assistant, [NewContext, Assist, CancelLastAssist]);
|
actions!(
|
||||||
|
assistant,
|
||||||
|
[NewContext, Assist, CancelLastAssist, QuoteSelection]
|
||||||
|
);
|
||||||
|
|
||||||
pub fn init(cx: &mut AppContext) {
|
pub fn init(cx: &mut AppContext) {
|
||||||
cx.add_action(AssistantEditor::assist);
|
cx.add_action(AssistantEditor::assist);
|
||||||
cx.capture_action(AssistantEditor::cancel_last_assist);
|
cx.capture_action(AssistantEditor::cancel_last_assist);
|
||||||
|
cx.add_action(AssistantEditor::quote_selection);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum AssistantPanelEvent {
|
pub enum AssistantPanelEvent {
|
||||||
|
@ -136,6 +140,12 @@ impl View for AssistantPanel {
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
|
||||||
ChildView::new(&self.pane, cx).into_any()
|
ChildView::new(&self.pane, cx).into_any()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn focus_in(&mut self, _: gpui::AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||||
|
if cx.is_self_focused() {
|
||||||
|
cx.focus(&self.pane);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Panel for AssistantPanel {
|
impl Panel for AssistantPanel {
|
||||||
|
@ -361,7 +371,7 @@ impl AssistantEditor {
|
||||||
editor.set_render_excerpt_header(
|
editor.set_render_excerpt_header(
|
||||||
{
|
{
|
||||||
let assistant = assistant.clone();
|
let assistant = assistant.clone();
|
||||||
move |editor, params: editor::RenderExcerptHeaderParams, cx| {
|
move |_editor, params: editor::RenderExcerptHeaderParams, cx| {
|
||||||
let style = &theme::current(cx).assistant;
|
let style = &theme::current(cx).assistant;
|
||||||
if let Some(message) = assistant.read(cx).messages_by_id.get(¶ms.id) {
|
if let Some(message) = assistant.read(cx).messages_by_id.get(¶ms.id) {
|
||||||
let sender = match message.role {
|
let sender = match message.role {
|
||||||
|
@ -421,6 +431,71 @@ impl AssistantEditor {
|
||||||
cx.propagate_action();
|
cx.propagate_action();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn quote_selection(
|
||||||
|
workspace: &mut Workspace,
|
||||||
|
_: &QuoteSelection,
|
||||||
|
cx: &mut ViewContext<Workspace>,
|
||||||
|
) {
|
||||||
|
let Some(panel) = workspace.panel::<AssistantPanel>(cx) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let Some(editor) = workspace.active_item(cx).and_then(|item| item.downcast::<Editor>()) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let text = editor.read_with(cx, |editor, cx| {
|
||||||
|
let range = editor.selections.newest::<usize>(cx).range();
|
||||||
|
let buffer = editor.buffer().read(cx).snapshot(cx);
|
||||||
|
let start_language = buffer.language_at(range.start);
|
||||||
|
let end_language = buffer.language_at(range.end);
|
||||||
|
let language_name = if start_language == end_language {
|
||||||
|
start_language.map(|language| language.name())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
let language_name = language_name.as_deref().unwrap_or("").to_lowercase();
|
||||||
|
|
||||||
|
let selected_text = buffer.text_for_range(range).collect::<String>();
|
||||||
|
if selected_text.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(if language_name == "markdown" {
|
||||||
|
selected_text
|
||||||
|
.lines()
|
||||||
|
.map(|line| format!("> {}", line))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n")
|
||||||
|
} else {
|
||||||
|
format!("```{language_name}\n{selected_text}\n```")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Activate the panel
|
||||||
|
if !panel.read(cx).has_focus(cx) {
|
||||||
|
workspace.toggle_panel_focus::<AssistantPanel>(cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(text) = text {
|
||||||
|
panel.update(cx, |panel, cx| {
|
||||||
|
if let Some(assistant) = panel
|
||||||
|
.pane
|
||||||
|
.read(cx)
|
||||||
|
.active_item()
|
||||||
|
.and_then(|item| item.downcast::<AssistantEditor>())
|
||||||
|
.ok_or_else(|| anyhow!("no active context"))
|
||||||
|
.log_err()
|
||||||
|
{
|
||||||
|
assistant.update(cx, |assistant, cx| {
|
||||||
|
assistant
|
||||||
|
.editor
|
||||||
|
.update(cx, |editor, cx| editor.insert(&text, cx))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Entity for AssistantEditor {
|
impl Entity for AssistantEditor {
|
||||||
|
@ -440,6 +515,12 @@ impl View for AssistantEditor {
|
||||||
.with_style(theme.container)
|
.with_style(theme.container)
|
||||||
.into_any()
|
.into_any()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn focus_in(&mut self, _: gpui::AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||||
|
if cx.is_self_focused() {
|
||||||
|
cx.focus(&self.editor);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Item for AssistantEditor {
|
impl Item for AssistantEditor {
|
||||||
|
|
|
@ -184,6 +184,12 @@ impl Dock {
|
||||||
.map_or(false, |panel| panel.has_focus(cx))
|
.map_or(false, |panel| panel.has_focus(cx))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn panel<T: Panel>(&self) -> Option<ViewHandle<T>> {
|
||||||
|
self.panel_entries
|
||||||
|
.iter()
|
||||||
|
.find_map(|entry| entry.panel.as_any().clone().downcast())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn panel_index_for_type<T: Panel>(&self) -> Option<usize> {
|
pub fn panel_index_for_type<T: Panel>(&self) -> Option<usize> {
|
||||||
self.panel_entries
|
self.panel_entries
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
@ -1678,6 +1678,16 @@ impl Workspace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn panel<T: Panel>(&self, cx: &WindowContext) -> Option<ViewHandle<T>> {
|
||||||
|
for dock in [&self.left_dock, &self.bottom_dock, &self.right_dock] {
|
||||||
|
let dock = dock.read(cx);
|
||||||
|
if let Some(panel) = dock.panel::<T>() {
|
||||||
|
return Some(panel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
fn zoom_out(&mut self, cx: &mut ViewContext<Self>) {
|
fn zoom_out(&mut self, cx: &mut ViewContext<Self>) {
|
||||||
for pane in &self.panes {
|
for pane in &self.panes {
|
||||||
pane.update(cx, |pane, cx| pane.set_zoomed(false, cx));
|
pane.update(cx, |pane, cx| pane.set_zoomed(false, cx));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue