A simple CPU rendered GUI IDE experience.
Diffstat (limited to 'src/hov.rs')
-rw-r--r--src/hov.rs181
1 files changed, 101 insertions, 80 deletions
diff --git a/src/hov.rs b/src/hov.rs
index 8b006c1..48ab1cd 100644
--- a/src/hov.rs
+++ b/src/hov.rs
@@ -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()),
+ ))
+}