A simple CPU rendered GUI IDE experience.
Diffstat (limited to 'src/hov.rs')
| -rw-r--r-- | src/hov.rs | 181 |
1 files changed, 101 insertions, 80 deletions
@@ -7,12 +7,14 @@ use std::sync::Arc; use std::vec::Vec; use Default::default; +use annotate_snippets::Renderer; use dsb::Cell; use dsb::cell::Style; use implicit_fn::implicit_fn; use itertools::Itertools; use lsp_types::{ - Diagnostic, TextDocumentIdentifier, TextDocumentPositionParams, + Diagnostic, DiagnosticSeverity, TextDocumentIdentifier, + TextDocumentPositionParams, }; use markdown::mdast::{self, Node}; use ropey::Rope; @@ -20,6 +22,7 @@ use serde_derive::{Deserialize, Serialize}; use url::Url; const D: Cell = Cell { letter: None, style: Style::new(FG, BG) }; use crate::rnd::{CellBuffer, simplify_path}; +use crate::text::RopeExt; use crate::{FG, FONT, text}; struct Builder { @@ -99,18 +102,29 @@ impl Builder { n: &mdast::Node, i: impl IntoIterator<Item = Action>, inherit: Style, + l: Option<helix_core::Language>, ) -> Vec<Action> { n.children() .iter() .flat_map(|i| *i) - .flat_map(|x| self.run(x, inherit)) + .flat_map(|x| self.run(x, inherit, l)) .chain(i) .collect() } - fn extend(&self, n: &Node, inherit: Style) -> Vec<Action> { - self.extend_(n, empty(), inherit) + fn extend( + &self, + n: &Node, + inherit: Style, + l: Option<helix_core::Language>, + ) -> Vec<Action> { + self.extend_(n, empty(), inherit, l) } - fn run(&self, node: &mdast::Node, mut inherit: Style) -> Vec<Action> { + fn run( + &self, + node: &mdast::Node, + mut inherit: Style, + l: Option<helix_core::Language>, + ) -> Vec<Action> { match node { Node::Break(_) => vec![Action::Finish], Node::InlineCode(x) => { @@ -123,25 +137,25 @@ impl Builder { Node::Delete(_) => todo!(), Node::Emphasis(_) => { inherit.flags |= Style::ITALIC; - self.extend(node, inherit | Style::ITALIC) + self.extend(node, inherit | Style::ITALIC, l) } Node::Link(_) => { inherit.flags |= Style::UNDERLINE; inherit.fg = [244, 196, 98]; - self.extend(node, inherit) + self.extend(node, inherit, l) } Node::LinkReference(_) => { inherit.flags |= Style::UNDERLINE; inherit.fg = [244, 196, 98]; - self.extend(node, inherit) + self.extend(node, inherit, l) } Node::Heading(_) => { inherit.flags |= Style::BOLD; inherit.fg = [255, 255, 255]; - self.extend_(node, [Action::Finish], inherit) + self.extend_(node, [Action::Finish], inherit, l) } - Node::Strong(_) => self.extend(node, inherit | Style::BOLD), + Node::Strong(_) => self.extend(node, inherit | Style::BOLD, l), Node::Text(text) => vec![Action::Put( text.value .chars() @@ -161,20 +175,24 @@ impl Builder { } } for ((x1, y1), (x2, y2), s, txt) in - std::iter::from_coroutine(pin!(text::hl( - text::LOADER - .language_for_name( - code.lang.as_deref().unwrap_or("rust") - ) - .unwrap_or( - text::LOADER - .language_for_name("rust") - .unwrap() - ), - &r, - .., - self.c, - ))) + std::iter::from_coroutine(pin!( + text::hl( + code.lang + .as_deref() + .and_then( + |x| text::LOADER.language_for_name(x) + ) + .or(l) + .unwrap_or( + text::LOADER + .language_for_name("rust") + .unwrap() + ), + &r, + .., + self.c, + ) + )) { cell.get_mut(y1 * self.c + x1..y2 * self.c + x2).map( |x| { @@ -197,10 +215,10 @@ impl Builder { Node::Paragraph(paragraph) => paragraph .children .iter() - .flat_map(|c| self.run(&c, inherit)) + .flat_map(|c| self.run(&c, inherit, l)) .chain([Action::Finish, Action::Finish]) .collect(), - n => self.extend(n, inherit), + n => self.extend(n, inherit, l), } } } @@ -236,10 +254,14 @@ pub fn l(node: &Node) -> Vec<usize> { .collect::<Vec<_>>() } #[implicit_fn::implicit_fn] -pub fn markdown2(c: usize, x: &Node) -> Vec<Cell> { +pub fn markdown2( + c: usize, + x: &Node, + l: Option<helix_core::Language>, +) -> Vec<Cell> { let mut r = Builder { c, to: vec![], scratch: vec![] }; for (is_put, act) in r - .run(&x, Style::new(FG, BG)) + .run(&x, Style::new(FG, BG), l) .into_iter() .chunk_by(|x| matches!(x, Action::Put(_))) .into_iter() @@ -263,11 +285,16 @@ pub fn markdown2(c: usize, x: &Node) -> Vec<Cell> { } } } - if r.to.iter().take(c).all(_.letter.is_none()) { + if r.to.iter().take(c).all(_.letter.is_none()) + && r.to.get(..c).is_some() + { r.to.drain(..c); } - if r.to.iter().rev().take(c).all(_.letter.is_none()) { - r.to.drain(r.to.len() - c..); + if r.to.iter().rev().take(c).all(_.letter.is_none()) + && let Some(n) = r.to.len().checked_sub(c) + && r.to.get(n..).is_some() + { + r.to.drain(n..); } r.to } @@ -344,28 +371,30 @@ impl DiagnosticHovr { diag: Diagnostic, window: &Arc<dyn winit::window::Window>, r: usize, + rope: &Rope, ) -> Self { let fw_15 = { let ppem = 15.0; let (fw, _) = dsb::dims(&FONT, ppem); fw }; - let dawg = once(&diag) - .filter_map(|x| { - x.data - .as_ref() - .unwrap_or_default() - .get("rendered") - .and_then(serde_json::Value::as_str) - }) - .collect::<String>(); - let mut t = pattypan::term::Terminal::new( - ( - ((window.surface_size().width as f32 / fw_15) as u16 - 5), - r as u16 - 5, - ), - false, - ); + let w = (window.surface_size().width as f32 / fw_15) as u16 - 5; + let dawg = + diag.data + .as_ref() + .unwrap_or_default() + .get("rendered") + .and_then(serde_json::Value::as_str) + .map(String::from) + .unwrap_or_else(|| { + Renderer::styled() + .decor_style( + annotate_snippets::renderer::DecorStyle::Unicode, + ).term_width(w as _) + .render(&[to_snippet(&diag, rope)]) + }); + let mut t = + pattypan::term::Terminal::new((w, r as u16 - 5), false); for b in simplify_path(&dawg.replace('\n', "\r\n").replace("βΈ¬", ":")) .bytes() @@ -398,39 +427,6 @@ impl DiagnosticHovr { .collect(); Self { t: CellBuffer { c: x_lim, vo: 0, cells: n }, diag, span } - - // let Ok((_, left, top, w, h)) = place_around( - // { - // let (x, y) = text.map_to_visual(( - // diag.range.start.character as _, - // diag.range.start.line as usize, - // )); - // (x + text.line_number_offset() + 1, y - text.vo) - // }, - // i.copy(), - // &*n, - // x_lim, - // 15.0, - // -200., - // 0., - // 0., - // 0., - // true, - // ) else { - // break 'out; - // }; - // pass = false; - // i.r#box( - // ( - // left.saturating_sub(1) as _, - // top.saturating_sub(1) as _, - // ), - // w as _, - // h as _, - // BORDER, - // ); - // } - // }; } } impl std::fmt::Debug for DiagnosticHovr { @@ -480,3 +476,28 @@ impl Hovring { pub fn rndr() {} } pub const HOV_HEIGHT: usize = 500; + +pub fn to_snippet<'a: 'c, 'b: 'c, 'c>( + Diagnostic { + range, + severity, + // code, + // code_description, + // source, + message, + .. + }: &'a Diagnostic, + t: &'b Rope, +) -> annotate_snippets::Group<'c> { + use annotate_snippets::*; + match severity { + Some(DiagnosticSeverity::WARNING) => Level::WARNING, + Some(DiagnosticSeverity::INFORMATION) => Level::INFO, + Some(DiagnosticSeverity::HINT) => Level::HELP, + _ => Level::ERROR, + } + .primary_title(message) + .element(Snippet::source(t).annotation( + AnnotationKind::Primary.span(t.l_range(*range).unwrap()), + )) +} |