From 7826d79a400725ea9cdabf2b1536cf35d83307a0 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 3 Jan 2025 13:24:04 -0500 Subject: [PATCH] markdown: Make `push_div` work with `Stateful
`s (#22622) This PR updates the `push_div` method in the `MarkdownElementBuilder` to support taking in a `Stateful
`. This is some groundwork for supporting horizontal scrolling in Markdown code blocks. Release Notes: - N/A --- crates/markdown/src/markdown.rs | 63 ++++++++++++++++++++++++++++----- 1 file changed, 55 insertions(+), 8 deletions(-) diff --git a/crates/markdown/src/markdown.rs b/crates/markdown/src/markdown.rs index 8f4ee45d25..bef07b9336 100644 --- a/crates/markdown/src/markdown.rs +++ b/crates/markdown/src/markdown.rs @@ -6,8 +6,8 @@ use gpui::{ actions, point, quad, AnyElement, AppContext, Bounds, ClipboardItem, CursorStyle, DispatchPhase, Edges, FocusHandle, FocusableView, FontStyle, FontWeight, GlobalElementId, Hitbox, Hsla, KeyContext, Length, MouseDownEvent, MouseEvent, MouseMoveEvent, MouseUpEvent, - Point, Render, StrikethroughStyle, StyleRefinement, StyledText, Task, TextLayout, TextRun, - TextStyle, TextStyleRefinement, View, + Point, Render, Stateful, StrikethroughStyle, StyleRefinement, StyledText, Task, TextLayout, + TextRun, TextStyle, TextStyleRefinement, View, }; use language::{Language, LanguageRegistry, Rope}; use parser::{parse_links_only, parse_markdown, MarkdownEvent, MarkdownTag, MarkdownTagEnd}; @@ -785,8 +785,52 @@ impl IntoElement for MarkdownElement { } } +enum AnyDiv { + Div(Div), + Stateful(Stateful
), +} + +impl AnyDiv { + fn into_any_element(self) -> AnyElement { + match self { + Self::Div(div) => div.into_any_element(), + Self::Stateful(div) => div.into_any_element(), + } + } +} + +impl From
for AnyDiv { + fn from(value: Div) -> Self { + Self::Div(value) + } +} + +impl From> for AnyDiv { + fn from(value: Stateful
) -> Self { + Self::Stateful(value) + } +} + +impl Styled for AnyDiv { + fn style(&mut self) -> &mut StyleRefinement { + match self { + Self::Div(div) => div.style(), + Self::Stateful(div) => div.style(), + } + } +} + +impl ParentElement for AnyDiv { + fn extend(&mut self, elements: impl IntoIterator) { + match self { + Self::Div(div) => div.extend(elements), + Self::Stateful(div) => div.extend(elements), + } + } +} + struct MarkdownElementBuilder { - div_stack: Vec
, + div_stack: Vec, rendered_lines: Vec, pending_line: PendingLine, rendered_links: Vec, @@ -812,7 +856,7 @@ struct ListStackEntry { impl MarkdownElementBuilder { fn new(base_text_style: TextStyle, syntax_theme: Arc) -> Self { Self { - div_stack: vec![div().debug_selector(|| "inner".into())], + div_stack: vec![div().debug_selector(|| "inner".into()).into()], rendered_lines: Vec::new(), pending_line: PendingLine::default(), rendered_links: Vec::new(), @@ -841,11 +885,12 @@ impl MarkdownElementBuilder { self.text_style_stack.pop(); } - fn push_div(&mut self, mut div: Div, range: &Range, markdown_end: usize) { + fn push_div(&mut self, div: impl Into, range: &Range, markdown_end: usize) { + let mut div = div.into(); self.flush_text(); if range.start == 0 { - //first element, remove top margin + // Remove the top margin on the first element. div.style().refine(&StyleRefinement { margin: gpui::EdgesRefinement { top: Some(Length::Definite(px(0.).into())), @@ -856,6 +901,7 @@ impl MarkdownElementBuilder { ..Default::default() }); } + if range.end == markdown_end { div.style().refine(&StyleRefinement { margin: gpui::EdgesRefinement { @@ -867,12 +913,13 @@ impl MarkdownElementBuilder { ..Default::default() }); } + self.div_stack.push(div); } fn pop_div(&mut self) { self.flush_text(); - let div = self.div_stack.pop().unwrap().into_any(); + let div = self.div_stack.pop().unwrap().into_any_element(); self.div_stack.last_mut().unwrap().extend(iter::once(div)); } @@ -973,7 +1020,7 @@ impl MarkdownElementBuilder { debug_assert_eq!(self.div_stack.len(), 1); self.flush_text(); RenderedMarkdown { - element: self.div_stack.pop().unwrap().into_any(), + element: self.div_stack.pop().unwrap().into_any_element(), text: RenderedText { lines: self.rendered_lines.into(), links: self.rendered_links.into(),