Detailed changes
@@ -22,7 +22,7 @@ use gpui::{
};
use language::{Buffer, LanguageRegistry};
use language_model::{ConfiguredModel, LanguageModelRegistry, LanguageModelToolUseId, Role};
-use markdown::{Markdown, MarkdownStyle};
+use markdown::{Markdown, MarkdownElement, MarkdownStyle};
use project::ProjectItem as _;
use settings::{Settings as _, update_settings_file};
use std::rc::Rc;
@@ -77,7 +77,6 @@ impl RenderedMessage {
segments: &[MessageSegment],
language_registry: Arc<LanguageRegistry>,
workspace: WeakEntity<Workspace>,
- window: &Window,
cx: &mut App,
) -> Self {
let mut this = Self {
@@ -85,18 +84,12 @@ impl RenderedMessage {
segments: Vec::with_capacity(segments.len()),
};
for segment in segments {
- this.push_segment(segment, workspace.clone(), window, cx);
+ this.push_segment(segment, workspace.clone(), cx);
}
this
}
- fn append_thinking(
- &mut self,
- text: &String,
- workspace: WeakEntity<Workspace>,
- window: &Window,
- cx: &mut App,
- ) {
+ fn append_thinking(&mut self, text: &String, workspace: WeakEntity<Workspace>, cx: &mut App) {
if let Some(RenderedMessageSegment::Thinking {
content,
scroll_handle,
@@ -112,7 +105,6 @@ impl RenderedMessage {
text.into(),
self.language_registry.clone(),
workspace,
- window,
cx,
),
scroll_handle: ScrollHandle::default(),
@@ -120,13 +112,7 @@ impl RenderedMessage {
}
}
- fn append_text(
- &mut self,
- text: &String,
- workspace: WeakEntity<Workspace>,
- window: &Window,
- cx: &mut App,
- ) {
+ fn append_text(&mut self, text: &String, workspace: WeakEntity<Workspace>, cx: &mut App) {
if let Some(RenderedMessageSegment::Text(markdown)) = self.segments.last_mut() {
markdown.update(cx, |markdown, cx| markdown.append(text, cx));
} else {
@@ -135,7 +121,6 @@ impl RenderedMessage {
SharedString::from(text),
self.language_registry.clone(),
workspace,
- window,
cx,
)));
}
@@ -145,7 +130,6 @@ impl RenderedMessage {
&mut self,
segment: &MessageSegment,
workspace: WeakEntity<Workspace>,
- window: &Window,
cx: &mut App,
) {
let rendered_segment = match segment {
@@ -154,7 +138,6 @@ impl RenderedMessage {
text.into(),
self.language_registry.clone(),
workspace,
- window,
cx,
),
scroll_handle: ScrollHandle::default(),
@@ -163,7 +146,6 @@ impl RenderedMessage {
text.into(),
self.language_registry.clone(),
workspace,
- window,
cx,
)),
};
@@ -183,9 +165,16 @@ fn render_markdown(
text: SharedString,
language_registry: Arc<LanguageRegistry>,
workspace: WeakEntity<Workspace>,
- window: &Window,
cx: &mut App,
) -> Entity<Markdown> {
+ cx.new(|cx| {
+ Markdown::new(text, Some(language_registry), None, cx).open_url(move |text, window, cx| {
+ open_markdown_link(text, workspace.clone(), window, cx);
+ })
+ })
+}
+
+fn default_markdown_style(window: &Window, cx: &App) -> MarkdownStyle {
let theme_settings = ThemeSettings::get_global(cx);
let colors = cx.theme().colors();
let ui_font_size = TextSize::Default.rems(cx);
@@ -201,7 +190,7 @@ fn render_markdown(
..Default::default()
});
- let markdown_style = MarkdownStyle {
+ MarkdownStyle {
base_text_style: text_style,
syntax: cx.theme().syntax().clone(),
selection_background_color: cx.theme().players().local().selection,
@@ -266,24 +255,23 @@ fn render_markdown(
}
})),
..Default::default()
- };
-
- cx.new(|cx| {
- Markdown::new(text, markdown_style, Some(language_registry), None, cx).open_url(
- move |text, window, cx| {
- open_markdown_link(text, workspace.clone(), window, cx);
- },
- )
- })
+ }
}
fn render_tool_use_markdown(
text: SharedString,
language_registry: Arc<LanguageRegistry>,
workspace: WeakEntity<Workspace>,
- window: &Window,
cx: &mut App,
) -> Entity<Markdown> {
+ cx.new(|cx| {
+ Markdown::new(text, Some(language_registry), None, cx).open_url(move |text, window, cx| {
+ open_markdown_link(text, workspace.clone(), window, cx);
+ })
+ })
+}
+
+fn tool_use_markdown_style(window: &Window, cx: &mut App) -> MarkdownStyle {
let theme_settings = ThemeSettings::get_global(cx);
let colors = cx.theme().colors();
let ui_font_size = TextSize::Default.rems(cx);
@@ -299,7 +287,7 @@ fn render_tool_use_markdown(
..Default::default()
});
- let markdown_style = MarkdownStyle {
+ MarkdownStyle {
base_text_style: text_style,
syntax: cx.theme().syntax().clone(),
selection_background_color: cx.theme().players().local().selection,
@@ -334,15 +322,7 @@ fn render_tool_use_markdown(
..Default::default()
},
..Default::default()
- };
-
- cx.new(|cx| {
- Markdown::new(text, markdown_style, Some(language_registry), None, cx).open_url(
- move |text, window, cx| {
- open_markdown_link(text, workspace.clone(), window, cx);
- },
- )
- })
+ }
}
fn open_markdown_link(
@@ -473,7 +453,6 @@ impl ActiveThread {
tool_use.ui_text.clone(),
&tool_use.input,
tool_use.status.text(),
- window,
cx,
);
}
@@ -516,7 +495,7 @@ impl ActiveThread {
&mut self,
id: &MessageId,
segments: &[MessageSegment],
- window: &mut Window,
+ _window: &mut Window,
cx: &mut Context<Self>,
) {
let old_len = self.messages.len();
@@ -527,7 +506,6 @@ impl ActiveThread {
segments,
self.language_registry.clone(),
self.workspace.clone(),
- window,
cx,
);
self.rendered_messages_by_id.insert(*id, rendered_message);
@@ -537,7 +515,7 @@ impl ActiveThread {
&mut self,
id: &MessageId,
segments: &[MessageSegment],
- window: &mut Window,
+ _window: &mut Window,
cx: &mut Context<Self>,
) {
let Some(index) = self.messages.iter().position(|message_id| message_id == id) else {
@@ -548,7 +526,6 @@ impl ActiveThread {
segments,
self.language_registry.clone(),
self.workspace.clone(),
- window,
cx,
);
self.rendered_messages_by_id.insert(*id, rendered_message);
@@ -569,7 +546,6 @@ impl ActiveThread {
tool_label: impl Into<SharedString>,
tool_input: &serde_json::Value,
tool_output: SharedString,
- window: &mut Window,
cx: &mut Context<Self>,
) {
let rendered = RenderedToolUse {
@@ -577,7 +553,6 @@ impl ActiveThread {
tool_label.into(),
self.language_registry.clone(),
self.workspace.clone(),
- window,
cx,
),
input: render_tool_use_markdown(
@@ -588,14 +563,12 @@ impl ActiveThread {
.into(),
self.language_registry.clone(),
self.workspace.clone(),
- window,
cx,
),
output: render_tool_use_markdown(
tool_output,
self.language_registry.clone(),
self.workspace.clone(),
- window,
cx,
),
};
@@ -640,12 +613,12 @@ impl ActiveThread {
}
ThreadEvent::StreamedAssistantText(message_id, text) => {
if let Some(rendered_message) = self.rendered_messages_by_id.get_mut(&message_id) {
- rendered_message.append_text(text, self.workspace.clone(), window, cx);
+ rendered_message.append_text(text, self.workspace.clone(), cx);
}
}
ThreadEvent::StreamedAssistantThinking(message_id, text) => {
if let Some(rendered_message) = self.rendered_messages_by_id.get_mut(&message_id) {
- rendered_message.append_thinking(text, self.workspace.clone(), window, cx);
+ rendered_message.append_thinking(text, self.workspace.clone(), cx);
}
}
ThreadEvent::MessageAdded(message_id) => {
@@ -690,7 +663,6 @@ impl ActiveThread {
tool_use.ui_text.clone(),
&tool_use.input,
"".into(),
- window,
cx,
);
}
@@ -711,7 +683,6 @@ impl ActiveThread {
.tool_result(&tool_use.id)
.map(|result| result.content.clone().into())
.unwrap_or("".into()),
- window,
cx,
);
}
@@ -1204,6 +1175,7 @@ impl ActiveThread {
message_id,
rendered_message,
has_tool_uses,
+ window,
cx,
))
.into_any()
@@ -1370,7 +1342,7 @@ impl ActiveThread {
div().children(
tool_uses
.into_iter()
- .map(|tool_use| self.render_tool_use(tool_use, cx)),
+ .map(|tool_use| self.render_tool_use(tool_use, window, cx)),
),
)
}),
@@ -1540,6 +1512,7 @@ impl ActiveThread {
message_id: MessageId,
rendered_message: &RenderedMessage,
has_tool_uses: bool,
+ window: &Window,
cx: &Context<Self>,
) -> impl IntoElement {
let is_last_message = self.messages.last() == Some(&message_id);
@@ -1572,12 +1545,16 @@ impl ActiveThread {
content.clone(),
&scroll_handle,
Some(index) == pending_thinking_segment_index,
+ window,
cx,
)
.into_any_element(),
- RenderedMessageSegment::Text(markdown) => {
- div().child(markdown.clone()).into_any_element()
- }
+ RenderedMessageSegment::Text(markdown) => div()
+ .child(MarkdownElement::new(
+ markdown.clone(),
+ default_markdown_style(window, cx),
+ ))
+ .into_any_element(),
},
),
)
@@ -1601,6 +1578,7 @@ impl ActiveThread {
markdown: Entity<Markdown>,
scroll_handle: &ScrollHandle,
pending: bool,
+ window: &Window,
cx: &Context<Self>,
) -> impl IntoElement {
let is_open = self
@@ -1734,7 +1712,10 @@ impl ActiveThread {
.h_20()
.track_scroll(scroll_handle)
.text_ui_sm(cx)
- .child(markdown.clone())
+ .child(MarkdownElement::new(
+ markdown.clone(),
+ default_markdown_style(window, cx),
+ ))
.overflow_hidden(),
)
.child(gradient_overlay),
@@ -1749,7 +1730,10 @@ impl ActiveThread {
.rounded_b_lg()
.bg(editor_bg)
.text_ui_sm(cx)
- .child(markdown.clone()),
+ .child(MarkdownElement::new(
+ markdown.clone(),
+ default_markdown_style(window, cx),
+ )),
)
}),
)
@@ -1758,6 +1742,7 @@ impl ActiveThread {
fn render_tool_use(
&self,
tool_use: ToolUse,
+ window: &mut Window,
cx: &mut Context<Self>,
) -> impl IntoElement + use<> {
let is_open = self
@@ -1804,103 +1789,109 @@ impl ActiveThread {
let rendered_tool_use = self.rendered_tool_uses.get(&tool_use.id).cloned();
let results_content_container = || v_flex().p_2().gap_0p5();
- let results_content = v_flex()
- .gap_1()
- .child(
- results_content_container()
- .child(
- Label::new("Input")
- .size(LabelSize::XSmall)
- .color(Color::Muted)
- .buffer_font(cx),
- )
- .child(
- div().w_full().text_ui_sm(cx).children(
- rendered_tool_use
- .as_ref()
- .map(|rendered| rendered.input.clone()),
- ),
- ),
- )
- .map(|container| match tool_use.status {
- ToolUseStatus::Finished(_) => container.child(
+ let results_content =
+ v_flex()
+ .gap_1()
+ .child(
results_content_container()
- .border_t_1()
- .border_color(self.tool_card_border_color(cx))
.child(
- Label::new("Result")
+ Label::new("Input")
.size(LabelSize::XSmall)
.color(Color::Muted)
.buffer_font(cx),
)
- .child(
- div().w_full().text_ui_sm(cx).children(
- rendered_tool_use
- .as_ref()
- .map(|rendered| rendered.output.clone()),
- ),
- ),
- ),
- ToolUseStatus::Running => container.child(
- results_content_container().child(
- h_flex()
- .gap_1()
- .pb_1()
+ .child(div().w_full().text_ui_sm(cx).children(
+ rendered_tool_use.as_ref().map(|rendered| {
+ MarkdownElement::new(
+ rendered.input.clone(),
+ tool_use_markdown_style(window, cx),
+ )
+ }),
+ )),
+ )
+ .map(|container| match tool_use.status {
+ ToolUseStatus::Finished(_) => container.child(
+ results_content_container()
.border_t_1()
.border_color(self.tool_card_border_color(cx))
.child(
- Icon::new(IconName::ArrowCircle)
- .size(IconSize::Small)
- .color(Color::Accent)
- .with_animation(
- "arrow-circle",
- Animation::new(Duration::from_secs(2)).repeat(),
- |icon, delta| {
- icon.transform(Transformation::rotate(percentage(
- delta,
- )))
- },
- ),
- )
- .child(
- Label::new("Runningβ¦")
+ Label::new("Result")
.size(LabelSize::XSmall)
.color(Color::Muted)
.buffer_font(cx),
- ),
+ )
+ .child(div().w_full().text_ui_sm(cx).children(
+ rendered_tool_use.as_ref().map(|rendered| {
+ MarkdownElement::new(
+ rendered.output.clone(),
+ tool_use_markdown_style(window, cx),
+ )
+ }),
+ )),
),
- ),
- ToolUseStatus::Error(_) => container.child(
- results_content_container()
- .border_t_1()
- .border_color(self.tool_card_border_color(cx))
- .child(
- Label::new("Error")
- .size(LabelSize::XSmall)
- .color(Color::Muted)
- .buffer_font(cx),
+ ToolUseStatus::Running => container.child(
+ results_content_container().child(
+ h_flex()
+ .gap_1()
+ .pb_1()
+ .border_t_1()
+ .border_color(self.tool_card_border_color(cx))
+ .child(
+ Icon::new(IconName::ArrowCircle)
+ .size(IconSize::Small)
+ .color(Color::Accent)
+ .with_animation(
+ "arrow-circle",
+ Animation::new(Duration::from_secs(2)).repeat(),
+ |icon, delta| {
+ icon.transform(Transformation::rotate(percentage(
+ delta,
+ )))
+ },
+ ),
+ )
+ .child(
+ Label::new("Runningβ¦")
+ .size(LabelSize::XSmall)
+ .color(Color::Muted)
+ .buffer_font(cx),
+ ),
+ ),
+ ),
+ ToolUseStatus::Error(_) => {
+ container.child(
+ results_content_container()
+ .border_t_1()
+ .border_color(self.tool_card_border_color(cx))
+ .child(
+ Label::new("Error")
+ .size(LabelSize::XSmall)
+ .color(Color::Muted)
+ .buffer_font(cx),
+ )
+ .child(div().text_ui_sm(cx).children(
+ rendered_tool_use.as_ref().map(|rendered| {
+ MarkdownElement::new(
+ rendered.output.clone(),
+ tool_use_markdown_style(window, cx),
+ )
+ }),
+ )),
)
- .child(
- div().text_ui_sm(cx).children(
- rendered_tool_use
- .as_ref()
- .map(|rendered| rendered.output.clone()),
+ }
+ ToolUseStatus::Pending => container,
+ ToolUseStatus::NeedsConfirmation => container.child(
+ results_content_container()
+ .border_t_1()
+ .border_color(self.tool_card_border_color(cx))
+ .child(
+ Label::new("Asking Permission")
+ .size(LabelSize::Small)
+ .color(Color::Muted)
+ .buffer_font(cx),
),
- ),
- ),
- ToolUseStatus::Pending => container,
- ToolUseStatus::NeedsConfirmation => container.child(
- results_content_container()
- .border_t_1()
- .border_color(self.tool_card_border_color(cx))
- .child(
- Label::new("Asking Permission")
- .size(LabelSize::Small)
- .color(Color::Muted)
- .buffer_font(cx),
- ),
- ),
- });
+ ),
+ });
let gradient_overlay = |color: Hsla| {
div()
@@ -1948,7 +1939,7 @@ impl ActiveThread {
)
.child(
h_flex().pr_8().text_ui_sm(cx).children(
- rendered_tool_use.map(|rendered| rendered.label)
+ rendered_tool_use.map(|rendered| MarkdownElement::new(rendered.label, tool_use_markdown_style(window, cx)))
),
),
)
@@ -2036,7 +2027,7 @@ impl ActiveThread {
)
.child(
h_flex().pr_8().text_ui_sm(cx).children(
- rendered_tool_use.map(|rendered| rendered.label)
+ rendered_tool_use.map(|rendered| MarkdownElement::new(rendered.label, tool_use_markdown_style(window, cx)))
),
),
)
@@ -7,7 +7,7 @@ use gpui::{
};
use language::Buffer;
use language::CodeLabel;
-use markdown::Markdown;
+use markdown::{Markdown, MarkdownElement};
use multi_buffer::{Anchor, ExcerptId};
use ordered_float::OrderedFloat;
use project::CompletionSource;
@@ -622,21 +622,18 @@ impl CompletionsMenu {
let language = editor
.language_at(self.initial_position, cx)
.map(|l| l.name().to_proto());
- Markdown::new(
- SharedString::default(),
- hover_markdown_style(window, cx),
- languages,
- language,
- cx,
- )
- .copy_code_block_buttons(false)
- .open_url(open_markdown_url)
+ Markdown::new(SharedString::default(), languages, language, cx)
+ .copy_code_block_buttons(false)
+ .open_url(open_markdown_url)
})
});
markdown.update(cx, |markdown, cx| {
markdown.reset(parsed.clone(), cx);
});
- div().child(markdown.clone())
+ div().child(MarkdownElement::new(
+ markdown.clone(),
+ hover_markdown_style(window, cx),
+ ))
}
CompletionDocumentation::MultiLineMarkdown(_) => return None,
CompletionDocumentation::SingleLine(_) => return None,
@@ -3912,9 +3912,13 @@ impl EditorElement {
);
let hover_popovers = self.editor.update(cx, |editor, cx| {
- editor
- .hover_state
- .render(snapshot, visible_display_row_range.clone(), max_size, cx)
+ editor.hover_state.render(
+ snapshot,
+ visible_display_row_range.clone(),
+ max_size,
+ window,
+ cx,
+ )
});
let Some((position, hover_popovers)) = hover_popovers else {
return;
@@ -14,7 +14,7 @@ use gpui::{
use itertools::Itertools;
use language::{DiagnosticEntry, Language, LanguageRegistry};
use lsp::DiagnosticSeverity;
-use markdown::{Markdown, MarkdownStyle};
+use markdown::{Markdown, MarkdownElement, MarkdownStyle};
use multi_buffer::{MultiOrSingleBufferOffsetRange, ToOffset};
use project::{HoverBlock, HoverBlockKind, InlayHintLabelPart};
use settings::Settings;
@@ -310,7 +310,7 @@ fn show_hover(
let mut background_color: Option<Hsla> = None;
let parsed_content = cx
- .new_window_entity(|window, cx| {
+ .new_window_entity(|_window, cx| {
let status_colors = cx.theme().status();
match local_diagnostic.diagnostic.severity {
@@ -335,32 +335,8 @@ fn show_hover(
border_color = Some(status_colors.ignored_border);
}
};
- let settings = ThemeSettings::get_global(cx);
- let mut base_text_style = window.text_style();
- base_text_style.refine(&TextStyleRefinement {
- font_family: Some(settings.ui_font.family.clone()),
- font_fallbacks: settings.ui_font.fallbacks.clone(),
- font_size: Some(settings.ui_font_size(cx).into()),
- color: Some(cx.theme().colors().editor_foreground),
- background_color: Some(gpui::transparent_black()),
- ..Default::default()
- });
- let markdown_style = MarkdownStyle {
- base_text_style,
- selection_background_color: { cx.theme().players().local().selection },
- link: TextStyleRefinement {
- underline: Some(gpui::UnderlineStyle {
- thickness: px(1.),
- color: Some(cx.theme().colors().editor_foreground),
- wavy: false,
- }),
- ..Default::default()
- },
- ..Default::default()
- };
- Markdown::new_text(SharedString::new(text), markdown_style.clone(), cx)
- .open_url(open_markdown_url)
+ Markdown::new_text(SharedString::new(text), cx).open_url(open_markdown_url)
})
.ok();
@@ -563,10 +539,9 @@ async fn parse_blocks(
.join("\n\n");
let rendered_block = cx
- .new_window_entity(|window, cx| {
+ .new_window_entity(|_window, cx| {
Markdown::new(
combined_text.into(),
- hover_markdown_style(window, cx),
Some(language_registry.clone()),
fallback_language_name,
cx,
@@ -704,6 +679,7 @@ impl HoverState {
snapshot: &EditorSnapshot,
visible_rows: Range<DisplayRow>,
max_size: Size<Pixels>,
+ window: &mut Window,
cx: &mut Context<Editor>,
) -> Option<(DisplayPoint, Vec<AnyElement>)> {
// If there is a diagnostic, position the popovers based on that.
@@ -738,10 +714,10 @@ impl HoverState {
let mut elements = Vec::new();
if let Some(diagnostic_popover) = self.diagnostic_popover.as_ref() {
- elements.push(diagnostic_popover.render(max_size, cx));
+ elements.push(diagnostic_popover.render(max_size, window, cx));
}
for info_popover in &mut self.info_popovers {
- elements.push(info_popover.render(max_size, cx));
+ elements.push(info_popover.render(max_size, window, cx));
}
Some((point, elements))
@@ -781,6 +757,7 @@ impl InfoPopover {
pub(crate) fn render(
&mut self,
max_size: Size<Pixels>,
+ window: &mut Window,
cx: &mut Context<Editor>,
) -> AnyElement {
let keyboard_grace = Rc::clone(&self.keyboard_grace);
@@ -806,7 +783,10 @@ impl InfoPopover {
.max_h(max_size.height)
.p_2()
.track_scroll(&self.scroll_handle)
- .child(markdown.clone()),
+ .child(MarkdownElement::new(
+ markdown.clone(),
+ hover_markdown_style(window, cx),
+ )),
)
.child(self.render_vertical_scrollbar(cx));
}
@@ -868,11 +848,41 @@ pub struct DiagnosticPopover {
}
impl DiagnosticPopover {
- pub fn render(&self, max_size: Size<Pixels>, cx: &mut Context<Editor>) -> AnyElement {
+ pub fn render(
+ &self,
+ max_size: Size<Pixels>,
+ window: &mut Window,
+ cx: &mut Context<Editor>,
+ ) -> AnyElement {
let keyboard_grace = Rc::clone(&self.keyboard_grace);
let mut markdown_div = div().py_1().px_2();
if let Some(markdown) = &self.parsed_content {
- markdown_div = markdown_div.child(markdown.clone());
+ let settings = ThemeSettings::get_global(cx);
+ let mut base_text_style = window.text_style();
+ base_text_style.refine(&TextStyleRefinement {
+ font_family: Some(settings.ui_font.family.clone()),
+ font_fallbacks: settings.ui_font.fallbacks.clone(),
+ font_size: Some(settings.ui_font_size(cx).into()),
+ color: Some(cx.theme().colors().editor_foreground),
+ background_color: Some(gpui::transparent_black()),
+ ..Default::default()
+ });
+ let markdown_style = MarkdownStyle {
+ base_text_style,
+ selection_background_color: { cx.theme().players().local().selection },
+ link: TextStyleRefinement {
+ underline: Some(gpui::UnderlineStyle {
+ thickness: px(1.),
+ color: Some(cx.theme().colors().editor_foreground),
+ wavy: false,
+ }),
+ ..Default::default()
+ },
+ ..Default::default()
+ };
+
+ markdown_div =
+ markdown_div.child(MarkdownElement::new(markdown.clone(), markdown_style));
}
if let Some(background_color) = &self.background_color {
@@ -95,14 +95,13 @@ impl BlameRenderer for GitBlameRenderer {
)
}
})
- .hoverable_tooltip(move |window, cx| {
+ .hoverable_tooltip(move |_window, cx| {
cx.new(|cx| {
CommitTooltip::blame_entry(
&blame_entry,
details.clone(),
repository.clone(),
workspace.clone(),
- window,
cx,
)
})
@@ -145,14 +144,13 @@ impl BlameRenderer for GitBlameRenderer {
.child(Icon::new(IconName::FileGit).color(Color::Hint))
.child(text)
.gap_2()
- .hoverable_tooltip(move |window, cx| {
+ .hoverable_tooltip(move |_window, cx| {
let tooltip = cx.new(|cx| {
CommitTooltip::blame_entry(
&blame_entry,
details.clone(),
repository.clone(),
workspace.clone(),
- window,
cx,
)
});
@@ -8,7 +8,7 @@ use gpui::{
App, Asset, ClipboardItem, Element, Entity, MouseButton, ParentElement, Render, ScrollHandle,
StatefulInteractiveElement, WeakEntity, prelude::*,
};
-use markdown::Markdown;
+use markdown::{Markdown, MarkdownElement};
use project::git_store::Repository;
use settings::Settings;
use std::hash::Hash;
@@ -118,7 +118,6 @@ impl CommitTooltip {
details: Option<ParsedCommitMessage>,
repository: Entity<Repository>,
workspace: WeakEntity<Workspace>,
- window: &mut Window,
cx: &mut Context<Self>,
) -> Self {
let commit_time = blame
@@ -140,7 +139,6 @@ impl CommitTooltip {
},
repository,
workspace,
- window,
cx,
)
}
@@ -149,13 +147,8 @@ impl CommitTooltip {
commit: CommitDetails,
repository: Entity<Repository>,
workspace: WeakEntity<Workspace>,
- window: &mut Window,
cx: &mut Context<Self>,
) -> Self {
- let mut style = hover_markdown_style(window, cx);
- if let Some(code_block) = &style.code_block.text {
- style.base_text_style.refine(code_block);
- }
let markdown = cx.new(|cx| {
Markdown::new(
commit
@@ -163,7 +156,6 @@ impl CommitTooltip {
.as_ref()
.map(|message| message.message.clone())
.unwrap_or_default(),
- style,
None,
None,
cx,
@@ -199,12 +191,19 @@ impl Render for CommitTooltip {
OffsetDateTime::now_utc(),
time_format::TimestampFormat::MediumAbsolute,
);
+ let markdown_style = {
+ let mut style = hover_markdown_style(window, cx);
+ if let Some(code_block) = &style.code_block.text {
+ style.base_text_style.refine(code_block);
+ }
+ style
+ };
let message = self
.commit
.message
.as_ref()
- .map(|_| self.markdown.clone().into_any_element())
+ .map(|_| MarkdownElement::new(self.markdown.clone(), markdown_style).into_any())
.unwrap_or("<no commit message>".into_any());
let pull_request = self
@@ -3927,9 +3927,9 @@ impl GitPanelMessageTooltip {
}),
};
- this.update_in(cx, |this: &mut GitPanelMessageTooltip, window, cx| {
+ this.update(cx, |this: &mut GitPanelMessageTooltip, cx| {
this.commit_tooltip = Some(cx.new(move |cx| {
- CommitTooltip::new(commit_details, repository, workspace, window, cx)
+ CommitTooltip::new(commit_details, repository, workspace, cx)
}));
cx.notify();
})
@@ -1,7 +1,7 @@
use assets::Assets;
use gpui::{Application, Entity, KeyBinding, StyleRefinement, WindowOptions, prelude::*, rgb};
use language::{LanguageRegistry, language_settings::AllLanguageSettings};
-use markdown::{Markdown, MarkdownStyle};
+use markdown::{Markdown, MarkdownElement, MarkdownStyle};
use node_runtime::NodeRuntime;
use settings::SettingsStore;
use std::sync::Arc;
@@ -47,54 +47,7 @@ pub fn main() {
cx.activate(true);
cx.open_window(WindowOptions::default(), |_, cx| {
- cx.new(|cx| {
- let markdown_style = MarkdownStyle {
- base_text_style: gpui::TextStyle {
- font_family: "Zed Plex Sans".into(),
- color: cx.theme().colors().terminal_ansi_black,
- ..Default::default()
- },
- code_block: StyleRefinement::default()
- .font_family("Zed Plex Mono")
- .m(rems(1.))
- .bg(rgb(0xAAAAAAA)),
- inline_code: gpui::TextStyleRefinement {
- font_family: Some("Zed Mono".into()),
- color: Some(cx.theme().colors().editor_foreground),
- background_color: Some(cx.theme().colors().editor_background),
- ..Default::default()
- },
- rule_color: Color::Muted.color(cx),
- block_quote_border_color: Color::Muted.color(cx),
- block_quote: gpui::TextStyleRefinement {
- color: Some(Color::Muted.color(cx)),
- ..Default::default()
- },
- link: gpui::TextStyleRefinement {
- color: Some(Color::Accent.color(cx)),
- underline: Some(gpui::UnderlineStyle {
- thickness: px(1.),
- color: Some(Color::Accent.color(cx)),
- wavy: false,
- }),
- ..Default::default()
- },
- syntax: cx.theme().syntax().clone(),
- selection_background_color: {
- let mut selection = cx.theme().players().local().selection;
- selection.fade_out(0.7);
- selection
- },
- ..Default::default()
- };
-
- MarkdownExample::new(
- MARKDOWN_EXAMPLE.into(),
- markdown_style,
- language_registry,
- cx,
- )
- })
+ cx.new(|cx| MarkdownExample::new(MARKDOWN_EXAMPLE.into(), language_registry, cx))
})
.unwrap();
});
@@ -105,16 +58,10 @@ struct MarkdownExample {
}
impl MarkdownExample {
- pub fn new(
- text: SharedString,
- style: MarkdownStyle,
- language_registry: Arc<LanguageRegistry>,
- cx: &mut App,
- ) -> Self {
+ pub fn new(text: SharedString, language_registry: Arc<LanguageRegistry>, cx: &mut App) -> Self {
let markdown = cx.new(|cx| {
Markdown::new(
text,
- style,
Some(language_registry),
Some("TypeScript".to_string()),
cx,
@@ -125,7 +72,47 @@ impl MarkdownExample {
}
impl Render for MarkdownExample {
- fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
+ let markdown_style = MarkdownStyle {
+ base_text_style: gpui::TextStyle {
+ font_family: "Zed Plex Sans".into(),
+ color: cx.theme().colors().terminal_ansi_black,
+ ..Default::default()
+ },
+ code_block: StyleRefinement::default()
+ .font_family("Zed Plex Mono")
+ .m(rems(1.))
+ .bg(rgb(0xAAAAAAA)),
+ inline_code: gpui::TextStyleRefinement {
+ font_family: Some("Zed Mono".into()),
+ color: Some(cx.theme().colors().editor_foreground),
+ background_color: Some(cx.theme().colors().editor_background),
+ ..Default::default()
+ },
+ rule_color: Color::Muted.color(cx),
+ block_quote_border_color: Color::Muted.color(cx),
+ block_quote: gpui::TextStyleRefinement {
+ color: Some(Color::Muted.color(cx)),
+ ..Default::default()
+ },
+ link: gpui::TextStyleRefinement {
+ color: Some(Color::Accent.color(cx)),
+ underline: Some(gpui::UnderlineStyle {
+ thickness: px(1.),
+ color: Some(Color::Accent.color(cx)),
+ wavy: false,
+ }),
+ ..Default::default()
+ },
+ syntax: cx.theme().syntax().clone(),
+ selection_background_color: {
+ let mut selection = cx.theme().players().local().selection;
+ selection.fade_out(0.7);
+ selection
+ },
+ ..Default::default()
+ };
+
div()
.id("markdown-example")
.debug_selector(|| "foo".into())
@@ -134,6 +121,6 @@ impl Render for MarkdownExample {
.size_full()
.p_4()
.overflow_y_scroll()
- .child(self.markdown.clone())
+ .child(MarkdownElement::new(self.markdown.clone(), markdown_style))
}
}
@@ -1,7 +1,7 @@
use assets::Assets;
use gpui::{Application, Entity, KeyBinding, Length, StyleRefinement, WindowOptions, rgb};
use language::{LanguageRegistry, language_settings::AllLanguageSettings};
-use markdown::{Markdown, MarkdownStyle};
+use markdown::{Markdown, MarkdownElement, MarkdownStyle};
use node_runtime::NodeRuntime;
use settings::SettingsStore;
use std::sync::Arc;
@@ -37,58 +37,7 @@ pub fn main() {
cx.activate(true);
let _ = cx.open_window(WindowOptions::default(), |_, cx| {
cx.new(|cx| {
- let markdown_style = MarkdownStyle {
- base_text_style: gpui::TextStyle {
- font_family: "Zed Mono".into(),
- color: cx.theme().colors().text,
- ..Default::default()
- },
- code_block: StyleRefinement {
- text: Some(gpui::TextStyleRefinement {
- font_family: Some("Zed Mono".into()),
- background_color: Some(cx.theme().colors().editor_background),
- ..Default::default()
- }),
- margin: gpui::EdgesRefinement {
- top: Some(Length::Definite(rems(4.).into())),
- left: Some(Length::Definite(rems(4.).into())),
- right: Some(Length::Definite(rems(4.).into())),
- bottom: Some(Length::Definite(rems(4.).into())),
- },
- ..Default::default()
- },
- inline_code: gpui::TextStyleRefinement {
- font_family: Some("Zed Mono".into()),
- background_color: Some(cx.theme().colors().editor_background),
- ..Default::default()
- },
- rule_color: Color::Muted.color(cx),
- block_quote_border_color: Color::Muted.color(cx),
- block_quote: gpui::TextStyleRefinement {
- color: Some(Color::Muted.color(cx)),
- ..Default::default()
- },
- link: gpui::TextStyleRefinement {
- color: Some(Color::Accent.color(cx)),
- underline: Some(gpui::UnderlineStyle {
- thickness: px(1.),
- color: Some(Color::Accent.color(cx)),
- wavy: false,
- }),
- ..Default::default()
- },
- syntax: cx.theme().syntax().clone(),
- selection_background_color: {
- let mut selection = cx.theme().players().local().selection;
- selection.fade_out(0.7);
- selection
- },
- heading: Default::default(),
- ..Default::default()
- };
- let markdown = cx.new(|cx| {
- Markdown::new(MARKDOWN_EXAMPLE.into(), markdown_style, None, None, cx)
- });
+ let markdown = cx.new(|cx| Markdown::new(MARKDOWN_EXAMPLE.into(), None, None, cx));
HelloWorld { markdown }
})
@@ -100,7 +49,57 @@ struct HelloWorld {
}
impl Render for HelloWorld {
- fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
+ fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
+ let markdown_style = MarkdownStyle {
+ base_text_style: gpui::TextStyle {
+ font_family: "Zed Mono".into(),
+ color: cx.theme().colors().text,
+ ..Default::default()
+ },
+ code_block: StyleRefinement {
+ text: Some(gpui::TextStyleRefinement {
+ font_family: Some("Zed Mono".into()),
+ background_color: Some(cx.theme().colors().editor_background),
+ ..Default::default()
+ }),
+ margin: gpui::EdgesRefinement {
+ top: Some(Length::Definite(rems(4.).into())),
+ left: Some(Length::Definite(rems(4.).into())),
+ right: Some(Length::Definite(rems(4.).into())),
+ bottom: Some(Length::Definite(rems(4.).into())),
+ },
+ ..Default::default()
+ },
+ inline_code: gpui::TextStyleRefinement {
+ font_family: Some("Zed Mono".into()),
+ background_color: Some(cx.theme().colors().editor_background),
+ ..Default::default()
+ },
+ rule_color: Color::Muted.color(cx),
+ block_quote_border_color: Color::Muted.color(cx),
+ block_quote: gpui::TextStyleRefinement {
+ color: Some(Color::Muted.color(cx)),
+ ..Default::default()
+ },
+ link: gpui::TextStyleRefinement {
+ color: Some(Color::Accent.color(cx)),
+ underline: Some(gpui::UnderlineStyle {
+ thickness: px(1.),
+ color: Some(Color::Accent.color(cx)),
+ wavy: false,
+ }),
+ ..Default::default()
+ },
+ syntax: cx.theme().syntax().clone(),
+ selection_background_color: {
+ let mut selection = cx.theme().players().local().selection;
+ selection.fade_out(0.7);
+ selection
+ },
+ heading: Default::default(),
+ ..Default::default()
+ };
+
div()
.flex()
.bg(rgb(0x2e7d32))
@@ -112,6 +111,10 @@ impl Render for HelloWorld {
.border_color(rgb(0x0000ff))
.text_xl()
.text_color(rgb(0xffffff))
- .child(div().child(self.markdown.clone()).p_20())
+ .child(
+ div()
+ .child(MarkdownElement::new(self.markdown.clone(), markdown_style))
+ .p_20(),
+ )
}
}
@@ -14,7 +14,7 @@ use std::time::Duration;
use gpui::{
AnyElement, App, BorderStyle, Bounds, ClipboardItem, CursorStyle, DispatchPhase, Edges, Entity,
FocusHandle, Focusable, FontStyle, FontWeight, GlobalElementId, Hitbox, Hsla, KeyContext,
- Length, MouseDownEvent, MouseEvent, MouseMoveEvent, MouseUpEvent, Point, Render, Stateful,
+ Length, MouseDownEvent, MouseEvent, MouseMoveEvent, MouseUpEvent, Point, Stateful,
StrikethroughStyle, StyleRefinement, StyledText, Task, TextLayout, TextRun, TextStyle,
TextStyleRefinement, actions, point, quad,
};
@@ -74,7 +74,6 @@ pub struct Markdown {
selection: Selection,
pressed_link: Option<RenderedLink>,
autoscroll_request: Option<usize>,
- style: MarkdownStyle,
parsed_markdown: ParsedMarkdown,
should_reparse: bool,
pending_parse: Option<Task<Option<()>>>,
@@ -97,7 +96,6 @@ actions!(markdown, [Copy]);
impl Markdown {
pub fn new(
source: SharedString,
- style: MarkdownStyle,
language_registry: Option<Arc<LanguageRegistry>>,
fallback_code_block_language: Option<String>,
cx: &mut Context<Self>,
@@ -108,7 +106,6 @@ impl Markdown {
selection: Selection::default(),
pressed_link: None,
autoscroll_request: None,
- style,
should_reparse: false,
parsed_markdown: ParsedMarkdown::default(),
pending_parse: None,
@@ -136,14 +133,13 @@ impl Markdown {
}
}
- pub fn new_text(source: SharedString, style: MarkdownStyle, cx: &mut Context<Self>) -> Self {
+ pub fn new_text(source: SharedString, cx: &mut Context<Self>) -> Self {
let focus_handle = cx.focus_handle();
let mut this = Self {
source,
selection: Selection::default(),
pressed_link: None,
autoscroll_request: None,
- style,
should_reparse: false,
parsed_markdown: ParsedMarkdown::default(),
pending_parse: None,
@@ -275,12 +271,6 @@ impl Markdown {
}
}
-impl Render for Markdown {
- fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
- MarkdownElement::new(cx.entity().clone(), self.style.clone())
- }
-}
-
impl Focusable for Markdown {
fn focus_handle(&self, _cx: &App) -> FocusHandle {
self.focus_handle.clone()
@@ -341,7 +331,7 @@ pub struct MarkdownElement {
}
impl MarkdownElement {
- fn new(markdown: Entity<Markdown>, style: MarkdownStyle) -> Self {
+ pub fn new(markdown: Entity<Markdown>, style: MarkdownStyle) -> Self {
Self { markdown, style }
}
@@ -638,6 +628,10 @@ impl Element for MarkdownElement {
// If the path actually exists in the project, render a link to it.
if let Some(project_path) =
window.root::<Workspace>().flatten().and_then(|workspace| {
+ if path_range.path.is_absolute() {
+ return None;
+ }
+
workspace
.read(cx)
.project()
@@ -13,7 +13,7 @@ use gpui::{
};
use language::CursorShape;
-use markdown::{Markdown, MarkdownStyle};
+use markdown::{Markdown, MarkdownElement, MarkdownStyle};
use release_channel::ReleaseChannel;
use remote::ssh_session::{ConnectionIdentifier, SshPortForwardOption};
use remote::{SshConnectionOptions, SshPlatform, SshRemoteClient};
@@ -182,7 +182,6 @@ impl SshPrompt {
) {
let theme = ThemeSettings::get_global(cx);
- let mut text_style = window.text_style();
let refinement = TextStyleRefinement {
font_family: Some(theme.buffer_font.family.clone()),
font_features: Some(FontFeatures::disable_ligatures()),
@@ -192,7 +191,6 @@ impl SshPrompt {
..Default::default()
};
- text_style.refine(&refinement);
self.editor.update(cx, |editor, cx| {
if prompt.contains("yes/no") {
editor.set_masked(false, cx);
@@ -202,12 +200,8 @@ impl SshPrompt {
editor.set_text_style_refinement(refinement);
editor.set_cursor_shape(CursorShape::Block, cx);
});
- let markdown_style = MarkdownStyle {
- base_text_style: text_style,
- selection_background_color: cx.theme().players().local().selection,
- ..Default::default()
- };
- let markdown = cx.new(|cx| Markdown::new_text(prompt.into(), markdown_style, cx));
+
+ let markdown = cx.new(|cx| Markdown::new_text(prompt.into(), cx));
self.prompt = Some((markdown, tx));
self.status_message.take();
window.focus(&self.editor.focus_handle(cx));
@@ -231,7 +225,26 @@ impl SshPrompt {
}
impl Render for SshPrompt {
- fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
+ let theme = ThemeSettings::get_global(cx);
+
+ let mut text_style = window.text_style();
+ let refinement = TextStyleRefinement {
+ font_family: Some(theme.buffer_font.family.clone()),
+ font_features: Some(FontFeatures::disable_ligatures()),
+ font_size: Some(theme.buffer_font_size(cx).into()),
+ color: Some(cx.theme().colors().editor_foreground),
+ background_color: Some(gpui::transparent_black()),
+ ..Default::default()
+ };
+
+ text_style.refine(&refinement);
+ let markdown_style = MarkdownStyle {
+ base_text_style: text_style,
+ selection_background_color: cx.theme().players().local().selection,
+ ..Default::default()
+ };
+
v_flex()
.key_context("PasswordPrompt")
.py_2()
@@ -266,7 +279,7 @@ impl Render for SshPrompt {
div()
.size_full()
.overflow_hidden()
- .child(prompt.0.clone())
+ .child(MarkdownElement::new(prompt.0.clone(), markdown_style))
.child(self.editor.clone()),
)
})
@@ -4,7 +4,7 @@ use gpui::{
Refineable, Render, RenderablePromptHandle, SharedString, Styled, TextStyleRefinement, Window,
div,
};
-use markdown::{Markdown, MarkdownStyle};
+use markdown::{Markdown, MarkdownElement, MarkdownStyle};
use settings::{Settings, SettingsStore};
use theme::ThemeSettings;
use ui::{
@@ -47,24 +47,9 @@ fn zed_prompt_renderer(
actions: actions.iter().map(ToString::to_string).collect(),
focus: cx.focus_handle(),
active_action_id: 0,
- detail: detail.filter(|text| !text.is_empty()).map(|text| {
- cx.new(|cx| {
- let settings = ThemeSettings::get_global(cx);
- let mut base_text_style = window.text_style();
- base_text_style.refine(&TextStyleRefinement {
- font_family: Some(settings.ui_font.family.clone()),
- font_size: Some(settings.ui_font_size(cx).into()),
- color: Some(ui::Color::Muted.color(cx)),
- ..Default::default()
- });
- let markdown_style = MarkdownStyle {
- base_text_style,
- selection_background_color: { cx.theme().players().local().selection },
- ..Default::default()
- };
- Markdown::new(SharedString::new(text), markdown_style, None, None, cx)
- })
- }),
+ detail: detail
+ .filter(|text| !text.is_empty())
+ .map(|text| cx.new(|cx| Markdown::new(SharedString::new(text), None, None, cx))),
}
});
@@ -127,7 +112,7 @@ impl ZedPromptRenderer {
}
impl Render for ZedPromptRenderer {
- fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
+ fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let settings = ThemeSettings::get_global(cx);
let font_family = settings.ui_font.family.clone();
let prompt = v_flex()
@@ -153,11 +138,26 @@ impl Render for ZedPromptRenderer {
.child(self.message.clone())
.text_color(ui::Color::Default.color(cx)),
)
- .children(
- self.detail
- .clone()
- .map(|detail| div().w_full().text_xs().child(detail)),
- )
+ .children(self.detail.clone().map(|detail| {
+ div()
+ .w_full()
+ .text_xs()
+ .child(MarkdownElement::new(detail, {
+ let settings = ThemeSettings::get_global(cx);
+ let mut base_text_style = window.text_style();
+ base_text_style.refine(&TextStyleRefinement {
+ font_family: Some(settings.ui_font.family.clone()),
+ font_size: Some(settings.ui_font_size(cx).into()),
+ color: Some(ui::Color::Muted.color(cx)),
+ ..Default::default()
+ });
+ MarkdownStyle {
+ base_text_style,
+ selection_background_color: { cx.theme().players().local().selection },
+ ..Default::default()
+ }
+ }))
+ }))
.child(h_flex().justify_end().gap_2().children(
self.actions.iter().enumerate().rev().map(|(ix, action)| {
ui::Button::new(ix, action.clone())