assistant: Improve discoverability of slash command errors (#13331)

https://github.com/zed-industries/zed/assets/53836821/fca5deef-3a4b-4670-8b92-79f052ea8417



Release Notes:

- N/A
This commit is contained in:
Bennet Bo Fenner 2024-06-20 21:39:53 +02:00 committed by GitHub
parent 58e9952d7b
commit 2c545ce0bc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -17,7 +17,9 @@ use client::telemetry::Telemetry;
use collections::{BTreeSet, HashMap, HashSet}; use collections::{BTreeSet, HashMap, HashSet};
use editor::{ use editor::{
actions::{FoldAt, MoveToEndOfLine, Newline, ShowCompletions, UnfoldAt}, actions::{FoldAt, MoveToEndOfLine, Newline, ShowCompletions, UnfoldAt},
display_map::{BlockDisposition, BlockId, BlockProperties, BlockStyle, Crease, ToDisplayPoint}, display_map::{
BlockDisposition, BlockId, BlockProperties, BlockStyle, Crease, RenderBlock, ToDisplayPoint,
},
scroll::{Autoscroll, AutoscrollStrategy}, scroll::{Autoscroll, AutoscrollStrategy},
Anchor, Editor, EditorEvent, RowExt, ToOffset as _, ToPoint, Anchor, Editor, EditorEvent, RowExt, ToOffset as _, ToPoint,
}; };
@ -2200,6 +2202,7 @@ pub struct ContextEditor {
blocks: HashSet<BlockId>, blocks: HashSet<BlockId>,
scroll_position: Option<ScrollPosition>, scroll_position: Option<ScrollPosition>,
pending_slash_command_creases: HashMap<Range<language::Anchor>, CreaseId>, pending_slash_command_creases: HashMap<Range<language::Anchor>, CreaseId>,
pending_slash_command_blocks: HashMap<Range<language::Anchor>, BlockId>,
_subscriptions: Vec<Subscription>, _subscriptions: Vec<Subscription>,
} }
@ -2273,6 +2276,7 @@ impl ContextEditor {
fs, fs,
workspace: workspace.downgrade(), workspace: workspace.downgrade(),
pending_slash_command_creases: HashMap::default(), pending_slash_command_creases: HashMap::default(),
pending_slash_command_blocks: HashMap::default(),
_subscriptions, _subscriptions,
}; };
this.update_message_headers(cx); this.update_message_headers(cx);
@ -2534,7 +2538,8 @@ impl ContextEditor {
ContextEvent::PendingSlashCommandsUpdated { removed, updated } => { ContextEvent::PendingSlashCommandsUpdated { removed, updated } => {
self.editor.update(cx, |editor, cx| { self.editor.update(cx, |editor, cx| {
let buffer = editor.buffer().read(cx).snapshot(cx); let buffer = editor.buffer().read(cx).snapshot(cx);
let excerpt_id = *buffer.as_singleton().unwrap().0; let (excerpt_id, buffer_id, _) = buffer.as_singleton().unwrap();
let excerpt_id = *excerpt_id;
editor.remove_creases( editor.remove_creases(
removed removed
@ -2543,6 +2548,16 @@ impl ContextEditor {
cx, cx,
); );
editor.remove_blocks(
HashSet::from_iter(
removed.iter().filter_map(|range| {
self.pending_slash_command_blocks.remove(range)
}),
),
None,
cx,
);
let crease_ids = editor.insert_creases( let crease_ids = editor.insert_creases(
updated.iter().map(|command| { updated.iter().map(|command| {
let workspace = self.workspace.clone(); let workspace = self.workspace.clone();
@ -2575,7 +2590,7 @@ impl ContextEditor {
move |row, _, _, _cx: &mut WindowContext| { move |row, _, _, _cx: &mut WindowContext| {
render_pending_slash_command_gutter_decoration( render_pending_slash_command_gutter_decoration(
row, row,
command.status.clone(), &command.status,
confirm_command.clone(), confirm_command.clone(),
) )
} }
@ -2609,12 +2624,43 @@ impl ContextEditor {
cx, cx,
); );
let block_ids = editor.insert_blocks(
updated
.iter()
.filter_map(|command| match &command.status {
PendingSlashCommandStatus::Error(error) => {
Some((command, error.clone()))
}
_ => None,
})
.map(|(command, error_message)| BlockProperties {
style: BlockStyle::Fixed,
position: Anchor {
buffer_id: Some(buffer_id),
excerpt_id,
text_anchor: command.source_range.start,
},
height: 1,
disposition: BlockDisposition::Below,
render: slash_command_error_block_renderer(error_message),
}),
None,
cx,
);
self.pending_slash_command_creases.extend( self.pending_slash_command_creases.extend(
updated updated
.iter() .iter()
.map(|command| command.source_range.clone()) .map(|command| command.source_range.clone())
.zip(crease_ids), .zip(crease_ids),
); );
self.pending_slash_command_blocks.extend(
updated
.iter()
.map(|command| command.source_range.clone())
.zip(block_ids),
);
}) })
} }
ContextEvent::SlashCommandFinished { ContextEvent::SlashCommandFinished {
@ -3204,7 +3250,7 @@ fn render_slash_command_output_toggle(
fn render_pending_slash_command_gutter_decoration( fn render_pending_slash_command_gutter_decoration(
row: MultiBufferRow, row: MultiBufferRow,
status: PendingSlashCommandStatus, status: &PendingSlashCommandStatus,
confirm_command: Arc<dyn Fn(&mut WindowContext)>, confirm_command: Arc<dyn Fn(&mut WindowContext)>,
) -> AnyElement { ) -> AnyElement {
let mut icon = IconButton::new( let mut icon = IconButton::new(
@ -3222,11 +3268,7 @@ fn render_pending_slash_command_gutter_decoration(
PendingSlashCommandStatus::Running { .. } => { PendingSlashCommandStatus::Running { .. } => {
icon = icon.selected(true); icon = icon.selected(true);
} }
PendingSlashCommandStatus::Error(error) => { PendingSlashCommandStatus::Error(_) => icon = icon.icon_color(Color::Error),
icon = icon
.icon_color(Color::Error)
.tooltip(move |cx| Tooltip::text(format!("error: {error}"), cx));
}
} }
icon.into_any_element() icon.into_any_element()
@ -3277,6 +3319,19 @@ fn make_lsp_adapter_delegate(
}) })
} }
fn slash_command_error_block_renderer(message: String) -> RenderBlock {
Box::new(move |_| {
div()
.pl_6()
.child(
Label::new(format!("error: {}", message))
.single_line()
.color(Color::Error),
)
.into_any()
})
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;