diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index 55911a458705..7f407b1aac44 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -8,9 +8,10 @@ use crate::{ keymap::{KeymapResult, Keymaps}, ui::{ document::{render_document, LinePos, TextRenderer}, + markdown::StyledText, statusline, text_decorations::{self, Decoration, DecorationManager, InlineDiagnostics}, - Completion, Markdown, Popup, ProgressSpinners, + Completion, Popup, ProgressSpinners, }, }; @@ -1601,8 +1602,8 @@ impl Component for EditorView { let call: job::Callback = Callback::EditorCompositor(Box::new( move |editor: &mut Editor, compositor: &mut Compositor| { if let Some((contents, _)) = &editor.status_msg { - let contents = - Markdown::new(contents.to_string(), editor.syn_loader.clone()); + let contents = StyledText::new(contents.to_string(), style); + let popup = Popup::new("hover", contents).auto_close(true); compositor.replace_or_push("hover", popup); } diff --git a/helix-term/src/ui/markdown.rs b/helix-term/src/ui/markdown.rs index 96614443fb75..0e6d43f4bb79 100644 --- a/helix-term/src/ui/markdown.rs +++ b/helix-term/src/ui/markdown.rs @@ -5,7 +5,7 @@ use tui::{ text::{Span, Spans, Text}, }; -use std::sync::Arc; +use std::{borrow::Cow, sync::Arc}; use pulldown_cmark::{CodeBlockKind, Event, HeadingLevel, Options, Parser, Tag, TagEnd}; @@ -126,6 +126,45 @@ pub struct Markdown { config_loader: Arc>, } +pub struct StyledText { + text: tui::text::Text<'static>, +} + +impl StyledText { + pub fn new(contents: String, style: Style) -> Self { + let spans: Vec> = contents + .lines() + .map(|line| Spans::from(vec![Span::styled(Cow::Owned(line.to_string()), style)])) + .collect(); + + let text = Text::from(spans); + + Self { text } + } +} + +impl Component for StyledText { + fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut Context) { + use tui::widgets::{Paragraph, Widget, Wrap}; + + let par = Paragraph::new(&self.text) + .wrap(Wrap { trim: false }) + .scroll((cx.scroll.unwrap_or_default() as u16, 0)); + + let margin = Margin::all(1); + par.render(area.inner(margin), surface); + } + + fn required_size(&mut self, viewport: (u16, u16)) -> Option<(u16, u16)> { + let padding = 2; + + let max_text_width = (viewport.0.saturating_sub(padding)).min(120); + let (width, height) = crate::ui::text::required_size(&self.text, max_text_width); + + Some((width + padding, height + padding)) + } +} + // TODO: pre-render and self reference via Pin // better yet, just use Tendril + subtendril for references