assistant: Allow accepting terminal inline assist suggestion without executing command (#17299)

This adds a new button that on click, accepts the suggestion but does
not run the generated command.


https://github.com/user-attachments/assets/426b0ff3-8e19-435a-aa7f-89e062aefd4c

@danilo-leal @iamnbutler Any ideas on how to make both options
discoverable without having an extra button?

Release Notes:

- Added a way to accept terminal inline assist suggestions without
executing them

---------

Co-authored-by: Danilo Leal <67129314+danilo-leal@users.noreply.github.com>
This commit is contained in:
Bennet Bo Fenner 2024-09-04 10:54:32 +02:00 committed by GitHub
parent 3bdc35f1ac
commit 5b0d64890f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 51 additions and 25 deletions

View file

@ -157,11 +157,11 @@ impl TerminalInlineAssistant {
PromptEditorEvent::StopRequested => {
self.stop_assist(assist_id, cx);
}
PromptEditorEvent::ConfirmRequested => {
self.finish_assist(assist_id, false, cx);
PromptEditorEvent::ConfirmRequested { execute } => {
self.finish_assist(assist_id, false, *execute, cx);
}
PromptEditorEvent::CancelRequested => {
self.finish_assist(assist_id, true, cx);
self.finish_assist(assist_id, true, false, cx);
}
PromptEditorEvent::DismissRequested => {
self.dismiss_assist(assist_id, cx);
@ -292,6 +292,7 @@ impl TerminalInlineAssistant {
&mut self,
assist_id: TerminalInlineAssistId,
undo: bool,
execute: bool,
cx: &mut WindowContext,
) {
self.dismiss_assist(assist_id, cx);
@ -307,7 +308,7 @@ impl TerminalInlineAssistant {
assist.codegen.update(cx, |codegen, cx| {
if undo {
codegen.undo(cx);
} else {
} else if execute {
codegen.complete(cx);
}
});
@ -423,7 +424,7 @@ impl TerminalInlineAssist {
}
if assist.prompt_editor.is_none() {
this.finish_assist(assist_id, false, cx);
this.finish_assist(assist_id, false, false, cx);
}
}
})
@ -436,7 +437,7 @@ impl TerminalInlineAssist {
enum PromptEditorEvent {
StartRequested,
StopRequested,
ConfirmRequested,
ConfirmRequested { execute: bool },
CancelRequested,
DismissRequested,
Resized { height_in_lines: u8 },
@ -509,15 +510,15 @@ impl Render for PromptEditor {
]
}
CodegenStatus::Error(_) | CodegenStatus::Done => {
vec![
IconButton::new("cancel", IconName::Close)
.icon_color(Color::Muted)
.shape(IconButtonShape::Square)
.tooltip(|cx| Tooltip::for_action("Cancel Assist", &menu::Cancel, cx))
.on_click(
cx.listener(|_, _, cx| cx.emit(PromptEditorEvent::CancelRequested)),
),
if self.edited_since_done {
let cancel = IconButton::new("cancel", IconName::Close)
.icon_color(Color::Muted)
.shape(IconButtonShape::Square)
.tooltip(|cx| Tooltip::for_action("Cancel Assist", &menu::Cancel, cx))
.on_click(cx.listener(|_, _, cx| cx.emit(PromptEditorEvent::CancelRequested)));
if self.edited_since_done {
vec![
cancel,
IconButton::new("restart", IconName::RotateCw)
.icon_color(Color::Info)
.shape(IconButtonShape::Square)
@ -531,19 +532,35 @@ impl Render for PromptEditor {
})
.on_click(cx.listener(|_, _, cx| {
cx.emit(PromptEditorEvent::StartRequested);
}))
} else {
})),
]
} else {
vec![
cancel,
IconButton::new("accept", IconName::Check)
.icon_color(Color::Info)
.shape(IconButtonShape::Square)
.tooltip(|cx| {
Tooltip::for_action("Accept Generated Command", &menu::Confirm, cx)
})
.on_click(cx.listener(|_, _, cx| {
cx.emit(PromptEditorEvent::ConfirmRequested { execute: false });
})),
IconButton::new("confirm", IconName::Play)
.icon_color(Color::Info)
.shape(IconButtonShape::Square)
.tooltip(|cx| {
Tooltip::for_action("Execute generated command", &menu::Confirm, cx)
Tooltip::for_action(
"Execute Generated Command",
&menu::SecondaryConfirm,
cx,
)
})
.on_click(cx.listener(|_, _, cx| {
cx.emit(PromptEditorEvent::ConfirmRequested);
}))
},
]
cx.emit(PromptEditorEvent::ConfirmRequested { execute: true });
})),
]
}
}
};
@ -555,6 +572,7 @@ impl Render for PromptEditor {
.h_full()
.w_full()
.on_action(cx.listener(Self::confirm))
.on_action(cx.listener(Self::secondary_confirm))
.on_action(cx.listener(Self::cancel))
.on_action(cx.listener(Self::move_up))
.on_action(cx.listener(Self::move_down))
@ -605,7 +623,7 @@ impl Render for PromptEditor {
.child(div().flex_1().child(self.render_prompt_editor(cx)))
.child(
h_flex()
.gap_2()
.gap_1()
.pr_4()
.children(self.render_token_count(cx))
.children(buttons),
@ -809,7 +827,7 @@ impl PromptEditor {
if self.edited_since_done {
cx.emit(PromptEditorEvent::StartRequested);
} else {
cx.emit(PromptEditorEvent::ConfirmRequested);
cx.emit(PromptEditorEvent::ConfirmRequested { execute: false });
}
}
CodegenStatus::Error(_) => {
@ -818,6 +836,12 @@ impl PromptEditor {
}
}
fn secondary_confirm(&mut self, _: &menu::SecondaryConfirm, cx: &mut ViewContext<Self>) {
if matches!(self.codegen.read(cx).status, CodegenStatus::Done) {
cx.emit(PromptEditorEvent::ConfirmRequested { execute: true });
}
}
fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
if let Some(ix) = self.prompt_history_ix {
if ix > 0 {