From 11125a62c711b69c8474515c3e529ca5536902f9 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Tue, 20 Jun 2023 16:48:30 -0700 Subject: [PATCH] Add copy-on-click to diagnostic messages --- crates/diagnostics/src/diagnostics.rs | 4 +- crates/editor/src/display_map/block_map.rs | 1 + crates/editor/src/editor.rs | 48 +++++++++++++++------- crates/editor/src/element.rs | 10 +++-- crates/workspace/src/workspace.rs | 6 ++- 5 files changed, 49 insertions(+), 20 deletions(-) diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index 5350e53d6a..d0cd437946 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -1509,7 +1509,8 @@ mod tests { let snapshot = editor.snapshot(cx); snapshot .blocks_in_range(0..snapshot.max_point().row()) - .filter_map(|(row, block)| { + .enumerate() + .filter_map(|(ix, (row, block))| { let name = match block { TransformBlock::Custom(block) => block .render(&mut BlockContext { @@ -1520,6 +1521,7 @@ mod tests { gutter_width: 0., line_height: 0., em_width: 0., + block_id: ix, }) .name()? .to_string(), diff --git a/crates/editor/src/display_map/block_map.rs b/crates/editor/src/display_map/block_map.rs index 0cf5bacc65..b20ecaef1c 100644 --- a/crates/editor/src/display_map/block_map.rs +++ b/crates/editor/src/display_map/block_map.rs @@ -88,6 +88,7 @@ pub struct BlockContext<'a, 'b, 'c> { pub gutter_padding: f32, pub em_width: f32, pub line_height: f32, + pub block_id: usize, } #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 2e0d444e04..dd9952e870 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -7949,6 +7949,7 @@ impl Deref for EditorStyle { pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock { let mut highlighted_lines = Vec::new(); + for (index, line) in diagnostic.message.lines().enumerate() { let line = match &diagnostic.source { Some(source) if index == 0 => { @@ -7960,25 +7961,44 @@ pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> Rend }; highlighted_lines.push(line); } - + let message = diagnostic.message; Arc::new(move |cx: &mut BlockContext| { + let message = message.clone(); let settings = settings::get::(cx); + let tooltip_style = settings.theme.tooltip.clone(); let theme = &settings.theme.editor; let style = diagnostic_style(diagnostic.severity, is_valid, theme); let font_size = (style.text_scale_factor * settings.buffer_font_size(cx)).round(); - Flex::column() - .with_children(highlighted_lines.iter().map(|(line, highlights)| { - Label::new( - line.clone(), - style.message.clone().with_font_size(font_size), - ) - .with_highlights(highlights.clone()) - .contained() - .with_margin_left(cx.anchor_x) - })) - .aligned() - .left() - .into_any() + let anchor_x = cx.anchor_x; + enum BlockContextToolip {} + MouseEventHandler::::new(cx.block_id, cx, |_, _| { + Flex::column() + .with_children(highlighted_lines.iter().map(|(line, highlights)| { + Label::new( + line.clone(), + style.message.clone().with_font_size(font_size), + ) + .with_highlights(highlights.clone()) + .contained() + .with_margin_left(anchor_x) + })) + .aligned() + .left() + .into_any() + }) + .with_cursor_style(CursorStyle::PointingHand) + .on_click(MouseButton::Left, move |_, _, cx| { + cx.write_to_clipboard(ClipboardItem::new(message.clone())); + }) + // We really need to rethink this ID system... + .with_tooltip::( + cx.block_id, + "Copy diagnostic message".to_string(), + None, + tooltip_style, + cx, + ) + .into_any() }) } diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index d6f9a2e906..5be745162a 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -1467,6 +1467,7 @@ impl EditorElement { editor: &mut Editor, cx: &mut LayoutContext, ) -> (f32, Vec) { + let mut block_id = 0; let scroll_x = snapshot.scroll_anchor.offset.x(); let (fixed_blocks, non_fixed_blocks) = snapshot .blocks_in_range(rows.clone()) @@ -1474,7 +1475,7 @@ impl EditorElement { TransformBlock::ExcerptHeader { .. } => false, TransformBlock::Custom(block) => block.style() == BlockStyle::Fixed, }); - let mut render_block = |block: &TransformBlock, width: f32| { + let mut render_block = |block: &TransformBlock, width: f32, block_id: usize| { let mut element = match block { TransformBlock::Custom(block) => { let align_to = block @@ -1499,6 +1500,7 @@ impl EditorElement { scroll_x, gutter_width, em_width, + block_id, }) } TransformBlock::ExcerptHeader { @@ -1634,7 +1636,8 @@ impl EditorElement { let mut fixed_block_max_width = 0f32; let mut blocks = Vec::new(); for (row, block) in fixed_blocks { - let element = render_block(block, f32::INFINITY); + let element = render_block(block, f32::INFINITY, block_id); + block_id += 1; fixed_block_max_width = fixed_block_max_width.max(element.size().x() + em_width); blocks.push(BlockLayout { row, @@ -1654,7 +1657,8 @@ impl EditorElement { .max(gutter_width + scroll_width), BlockStyle::Fixed => unreachable!(), }; - let element = render_block(block, width); + let element = render_block(block, width, block_id); + block_id += 1; blocks.push(BlockLayout { row, element, diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 43ca41ab1d..a4974fc173 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -140,9 +140,11 @@ pub struct OpenPaths { #[derive(Clone, Deserialize, PartialEq)] pub struct ActivatePane(pub usize); +#[derive(Deserialize)] pub struct Toast { id: usize, msg: Cow<'static, str>, + #[serde(skip)] on_click: Option<(Cow<'static, str>, Arc)>, } @@ -183,9 +185,9 @@ impl Clone for Toast { } } -pub type WorkspaceId = i64; +impl_actions!(workspace, [ActivatePane, Toast]); -impl_actions!(workspace, [ActivatePane]); +pub type WorkspaceId = i64; pub fn init_settings(cx: &mut AppContext) { settings::register::(cx);