Add copy-on-click to diagnostic messages

This commit is contained in:
Mikayla Maki 2023-06-20 16:48:30 -07:00
parent 6ed86781b2
commit 11125a62c7
No known key found for this signature in database
5 changed files with 49 additions and 20 deletions

View file

@ -1509,7 +1509,8 @@ mod tests {
let snapshot = editor.snapshot(cx); let snapshot = editor.snapshot(cx);
snapshot snapshot
.blocks_in_range(0..snapshot.max_point().row()) .blocks_in_range(0..snapshot.max_point().row())
.filter_map(|(row, block)| { .enumerate()
.filter_map(|(ix, (row, block))| {
let name = match block { let name = match block {
TransformBlock::Custom(block) => block TransformBlock::Custom(block) => block
.render(&mut BlockContext { .render(&mut BlockContext {
@ -1520,6 +1521,7 @@ mod tests {
gutter_width: 0., gutter_width: 0.,
line_height: 0., line_height: 0.,
em_width: 0., em_width: 0.,
block_id: ix,
}) })
.name()? .name()?
.to_string(), .to_string(),

View file

@ -88,6 +88,7 @@ pub struct BlockContext<'a, 'b, 'c> {
pub gutter_padding: f32, pub gutter_padding: f32,
pub em_width: f32, pub em_width: f32,
pub line_height: f32, pub line_height: f32,
pub block_id: usize,
} }
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]

View file

@ -7949,6 +7949,7 @@ impl Deref for EditorStyle {
pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock { pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
let mut highlighted_lines = Vec::new(); let mut highlighted_lines = Vec::new();
for (index, line) in diagnostic.message.lines().enumerate() { for (index, line) in diagnostic.message.lines().enumerate() {
let line = match &diagnostic.source { let line = match &diagnostic.source {
Some(source) if index == 0 => { Some(source) if index == 0 => {
@ -7960,12 +7961,17 @@ pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> Rend
}; };
highlighted_lines.push(line); highlighted_lines.push(line);
} }
let message = diagnostic.message;
Arc::new(move |cx: &mut BlockContext| { Arc::new(move |cx: &mut BlockContext| {
let message = message.clone();
let settings = settings::get::<ThemeSettings>(cx); let settings = settings::get::<ThemeSettings>(cx);
let tooltip_style = settings.theme.tooltip.clone();
let theme = &settings.theme.editor; let theme = &settings.theme.editor;
let style = diagnostic_style(diagnostic.severity, is_valid, theme); let style = diagnostic_style(diagnostic.severity, is_valid, theme);
let font_size = (style.text_scale_factor * settings.buffer_font_size(cx)).round(); let font_size = (style.text_scale_factor * settings.buffer_font_size(cx)).round();
let anchor_x = cx.anchor_x;
enum BlockContextToolip {}
MouseEventHandler::<BlockContext, _>::new(cx.block_id, cx, |_, _| {
Flex::column() Flex::column()
.with_children(highlighted_lines.iter().map(|(line, highlights)| { .with_children(highlighted_lines.iter().map(|(line, highlights)| {
Label::new( Label::new(
@ -7974,12 +7980,26 @@ pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> Rend
) )
.with_highlights(highlights.clone()) .with_highlights(highlights.clone())
.contained() .contained()
.with_margin_left(cx.anchor_x) .with_margin_left(anchor_x)
})) }))
.aligned() .aligned()
.left() .left()
.into_any() .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::<BlockContextToolip>(
cx.block_id,
"Copy diagnostic message".to_string(),
None,
tooltip_style,
cx,
)
.into_any()
})
} }
pub fn highlight_diagnostic_message( pub fn highlight_diagnostic_message(

View file

@ -1467,6 +1467,7 @@ impl EditorElement {
editor: &mut Editor, editor: &mut Editor,
cx: &mut LayoutContext<Editor>, cx: &mut LayoutContext<Editor>,
) -> (f32, Vec<BlockLayout>) { ) -> (f32, Vec<BlockLayout>) {
let mut block_id = 0;
let scroll_x = snapshot.scroll_anchor.offset.x(); let scroll_x = snapshot.scroll_anchor.offset.x();
let (fixed_blocks, non_fixed_blocks) = snapshot let (fixed_blocks, non_fixed_blocks) = snapshot
.blocks_in_range(rows.clone()) .blocks_in_range(rows.clone())
@ -1474,7 +1475,7 @@ impl EditorElement {
TransformBlock::ExcerptHeader { .. } => false, TransformBlock::ExcerptHeader { .. } => false,
TransformBlock::Custom(block) => block.style() == BlockStyle::Fixed, 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 { let mut element = match block {
TransformBlock::Custom(block) => { TransformBlock::Custom(block) => {
let align_to = block let align_to = block
@ -1499,6 +1500,7 @@ impl EditorElement {
scroll_x, scroll_x,
gutter_width, gutter_width,
em_width, em_width,
block_id,
}) })
} }
TransformBlock::ExcerptHeader { TransformBlock::ExcerptHeader {
@ -1634,7 +1636,8 @@ impl EditorElement {
let mut fixed_block_max_width = 0f32; let mut fixed_block_max_width = 0f32;
let mut blocks = Vec::new(); let mut blocks = Vec::new();
for (row, block) in fixed_blocks { 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); fixed_block_max_width = fixed_block_max_width.max(element.size().x() + em_width);
blocks.push(BlockLayout { blocks.push(BlockLayout {
row, row,
@ -1654,7 +1657,8 @@ impl EditorElement {
.max(gutter_width + scroll_width), .max(gutter_width + scroll_width),
BlockStyle::Fixed => unreachable!(), BlockStyle::Fixed => unreachable!(),
}; };
let element = render_block(block, width); let element = render_block(block, width, block_id);
block_id += 1;
blocks.push(BlockLayout { blocks.push(BlockLayout {
row, row,
element, element,

View file

@ -140,9 +140,11 @@ pub struct OpenPaths {
#[derive(Clone, Deserialize, PartialEq)] #[derive(Clone, Deserialize, PartialEq)]
pub struct ActivatePane(pub usize); pub struct ActivatePane(pub usize);
#[derive(Deserialize)]
pub struct Toast { pub struct Toast {
id: usize, id: usize,
msg: Cow<'static, str>, msg: Cow<'static, str>,
#[serde(skip)]
on_click: Option<(Cow<'static, str>, Arc<dyn Fn(&mut WindowContext)>)>, on_click: Option<(Cow<'static, str>, Arc<dyn Fn(&mut WindowContext)>)>,
} }
@ -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) { pub fn init_settings(cx: &mut AppContext) {
settings::register::<WorkspaceSettings>(cx); settings::register::<WorkspaceSettings>(cx);