A simple CPU rendered GUI IDE experience.
Diffstat (limited to 'src/hov.rs')
-rw-r--r--src/hov.rs403
1 files changed, 403 insertions, 0 deletions
diff --git a/src/hov.rs b/src/hov.rs
new file mode 100644
index 0000000..869ff75
--- /dev/null
+++ b/src/hov.rs
@@ -0,0 +1,403 @@
+use std::iter::{once, repeat};
+use std::pin::pin;
+use std::time::Instant;
+use std::vec::Vec;
+
+use dsb::cell::Style;
+use dsb::{Cell, F};
+use fimg::Image;
+use itertools::Itertools;
+use minimad::*;
+use ropey::Rope;
+
+use crate::{BG, FG, M, text};
+fn f(x: &Compound) -> u8 {
+ let mut s = 0;
+ if x.bold {
+ s |= Style::BOLD;
+ }
+ if x.italic {
+ s |= Style::ITALIC;
+ }
+ if x.strikeout {
+ s |= Style::STRIKETHROUGH
+ }
+ s
+}
+fn markdown(c: usize, x: &str) -> Vec<Cell> {
+ let mut cells = vec![];
+ // println!(
+ // "{:#?}",
+ // markdown::to_mdast(
+ // include_str!("../vec.md"),
+ // &markdown::ParseOptions::default()
+ // )
+ // .unwrap()
+ // );
+ use Default::default;
+ // std::fs::write(
+ // "vec.ast",
+ // format!(
+ // "{:#?}",
+ // minimad::parse_text(
+ // include_str!("../vec.md"),
+ // Options { keep_code_fences: true, ..default() },
+ // )
+ // .lines
+ // ),
+ // )
+ // .unwrap();
+ const D: Cell = Cell {
+ letter: None,
+ style: Style { bg: BG, color: FG, flags: 0 },
+ };
+ let mut l = minimad::parse_text(
+ x,
+ Options { keep_code_fences: true, ..default() },
+ )
+ .lines
+ .into_iter()
+ .peekable();
+ 'l: while let Some(line) = l.next() {
+ match line {
+ minimad::Line::Normal(Composite { style, compounds }) => {
+ let mut compounded = l
+ .by_ref()
+ .peeking_take_while(|x| matches!(x, Line::Normal(Composite{style, compounds}) if !matches!(style, CompositeStyle::Header(_))))
+ .flat_map(|x| match x {
+ Line::Normal(Composite { style, compounds }) =>
+ compounds.into_iter().flat_map(move |x| {
+ x.as_str().chars().zip(repeat(f(&x)).map(
+ move |flags| match style {
+ CompositeStyle::Paragraph =>
+ Style {
+ color: FG,
+ bg: BG,
+ flags,
+ },
+ CompositeStyle::Header(x) =>
+ Style {
+ color: [255; 3],
+ bg: BG,
+ flags: flags | Style::BOLD,
+ },
+ CompositeStyle::ListItem(x) =>
+ Style {
+ color: FG,
+ bg: BG,
+ flags,
+ },
+ CompositeStyle::Code => Style {
+ color: [244,244,244],
+ bg: [5,5,5],
+ flags,
+ },
+ CompositeStyle::Quote => Style {
+ color: [128; 3],
+ bg: [0; 3],
+ flags,
+ },
+ },
+ ))
+ }).chain(once((' ', Style { color: FG, bg: BG, flags : 0 }))),
+ _ => panic!(),
+ })
+ .chunk_by(|x| x.0.is_whitespace());
+ let mut compounded = compounded.into_iter();
+ let mut out = vec![];
+
+ // let mut compounds = compounds.iter();
+ while let Some((x, word)) = compounded.next() {
+ if x {
+ continue;
+ }
+ if out.len() > c {
+ panic!()
+ }
+ let word = word.collect::<Vec<_>>();
+ if word.len() > c {
+ let mut w = word.iter().map(|&(x, style)| Cell {
+ letter: Some(x),
+ style,
+ });
+ out.extend(w);
+ cells.extend(
+ out.drain(..out.len() - out.len() % c),
+ );
+ // 'out: loop {
+ // while out.len() != c {
+ // let Some(x) = w.next() else {
+ // break 'out;
+ // };
+ // out.push(x);
+ // }
+ // cells.extend(&out);
+ // out.clear();
+ // }
+ continue;
+ // cells.extend(&out);
+ // out.clear();
+ // cells.extend(
+ // w.by_ref()
+ // .take(c.saturating_sub(out.len() + 1)),
+ // );
+ // cells.push(Cell::basic('-'));
+ // cells.extend(w);
+ }
+
+ if out.len() + word.len() > c {
+ assert_eq!(cells.len() % c, 0);
+ cells.extend(&out);
+ cells.extend(std::iter::repeat_n(
+ D,
+ c.saturating_sub(out.len()),
+ ));
+ dbg!(out.len(), c);
+ out.clear();
+ assert_eq!(cells.len() % c, 0);
+ }
+
+ out.extend(word.iter().map(|&(x, style)| Cell {
+ letter: Some(x),
+ style,
+ }));
+ if out.len() != c {
+ out.push(D);
+ } else {
+ cells.extend(&out);
+ out.clear();
+ }
+ dbg!(out.len());
+
+ // }
+ }
+ // if out.len() > c {
+ // panic!();
+ // }
+ // if out.len() + next.char_length() > c {
+ // cells.extend(&out);
+ // cells.extend(std::iter::repeat_n(
+ // Cell::default(),
+ // c.saturating_sub(out.len()),
+ // ));
+ // out.clear();
+ // assert_eq!(cells.len() % c, 0);
+ // }
+ // out.extend(
+ // next.as_str()
+ // .chars()
+ // .map(|x| Cell { letter: Some(x), style }),
+ // );
+ // }
+ if !out.is_empty() {
+ assert!(out.len() <= c, "{} < c", out.len());
+ cells.extend(&out);
+ cells.extend(std::iter::repeat_n(
+ D,
+ c.saturating_sub(out.len()),
+ ));
+ assert_eq!(cells.len() % c, 0);
+ }
+ continue 'l;
+ }
+ minimad::Line::TableRow(table_row) => todo!(),
+ minimad::Line::TableRule(table_rule) => todo!(),
+ minimad::Line::HorizontalRule => vec![Cell::basic('-')],
+ minimad::Line::CodeFence(Composite {
+ compounds: [Compound { src: lang, .. }],
+ ..
+ }) => {
+ let mut r = Rope::new();
+ while let Some(x) = l.next() {
+ match x {
+ Line::CodeFence(Composite {
+ compounds: [],
+ ..
+ }) => {
+ break;
+ }
+ Line::Normal(Composite {
+ compounds: [Compound { src, .. }],
+ ..
+ }) => {
+ r.insert(r.len_chars(), src);
+ r.insert_char(r.len_chars(), '\n');
+ }
+ _ => {}
+ }
+ }
+ let mut cell = vec![D; c * r.len_lines()];
+
+ for (l, y) in r.lines().zip(0..) {
+ for (e, x) in l.chars().take(c).zip(0..) {
+ if e != '\n' {
+ cell[y * c + x].letter = Some(e);
+ }
+ }
+ }
+ for ((x1, y1), (x2, y2), s, txt) in
+ std::iter::from_coroutine(pin!(text::hl(
+ text::LOADER.language_for_name(lang).unwrap_or(
+ text::LOADER
+ .language_for_name("rust")
+ .unwrap()
+ ),
+ &r,
+ ..,
+ c,
+ )))
+ {
+ cell.get_mut(y1 * c + x1..y2 * c + x2).map(|x| {
+ x.iter_mut().zip(txt.chars()).for_each(|(x, c)| {
+ x.style |= s;
+ x.letter = Some(c);
+ })
+ });
+ }
+ cells.extend(cell);
+ assert_eq!(cells.len() % c, 0);
+ continue 'l;
+ }
+ _ => panic!(),
+ };
+ // if out.len() > c {
+ // out.drain(c - 1..);
+ // out.push(Cell::basic('…'));
+ // } else {
+ // out.extend(std::iter::repeat_n(
+ // Cell::default(),
+ // c.saturating_sub(out.len()),
+ // ));
+ // }
+ // assert_eq!(out.len(), c);
+ // cells.extend(out);
+ }
+ assert_eq!(cells.len() % c, 0);
+ cells
+}
+
+#[test]
+fn t() {
+ let ppem = 18.0;
+ let lh = 10.0;
+ let (w, h) = (800, 8000);
+ let (c, r) = dsb::fit(&crate::FONT, ppem, lh, (w, h));
+ std::fs::write(
+ "mdast2",
+ format!(
+ "{:#?}",
+ markdown::to_mdast(
+ include_str!("../vec.md"),
+ &markdown::ParseOptions::gfm()
+ )
+ .unwrap()
+ ),
+ );
+ let mut cells = markdown(c, include_str!("../vec.md"));
+ // use Default::default;
+ // for line in dbg!(minimad::parse_text(
+ // include_str!("../vec.md"),
+ // Options { keep_code_fences: true, ..default() },
+ // ))
+ // .lines
+ // {
+ // fn f(x: &Compound) -> u8 {
+ // let mut s = 0;
+ // if x.bold {
+ // s |= Style::BOLD;
+ // }
+ // if x.italic {
+ // s |= Style::ITALIC;
+ // }
+ // if x.strikeout {
+ // s |= Style::STRIKETHROUGH
+ // }
+ // s
+ // }
+ // let mut out = match line {
+ // minimad::Line::Normal(Composite { style, compounds }) =>
+ // compounds
+ // .iter()
+ // .flat_map(|c| {
+ // c.as_str().chars().map(move |x| {
+ // let flags = f(&c);
+ // let style = match style {
+ // CompositeStyle::Paragraph => Style {
+ // color: [128; 3],
+ // bg: [0; 3],
+ // flags,
+ // },
+ // CompositeStyle::Header(x) => Style {
+ // color: [255; 3],
+ // bg: [0; 3],
+ // flags: flags | Style::BOLD,
+ // },
+ // CompositeStyle::ListItem(x) => Style {
+ // color: [128; 3],
+ // bg: [0; 3],
+ // flags,
+ // },
+ // CompositeStyle::Code => Style {
+ // color: [100; 3],
+ // bg: [0; 3],
+ // flags,
+ // },
+ // CompositeStyle::Quote => Style {
+ // color: [128; 3],
+ // bg: [0; 3],
+ // flags,
+ // },
+ // };
+ // Cell { letter: Some(x), style }
+ // })
+ // })
+ // .collect::<Vec<_>>(),
+ // minimad::Line::TableRow(table_row) => todo!(),
+ // minimad::Line::TableRule(table_rule) => todo!(),
+ // minimad::Line::HorizontalRule => vec![Cell::basic('-')],
+ // minimad::Line::CodeFence(composite) => {
+ // vec![]
+ // }
+ // };
+ // if out.len() > c {
+ // out.drain(c - 1..);
+ // out.push(Cell::basic('…'));
+ // } else {
+ // out.extend(std::iter::repeat_n(
+ // Cell::default(),
+ // c - out.len(),
+ // ));
+ // }
+ // assert_eq!(out.len(), c);
+ // cells.extend(out);
+ // }
+ dbg!(cells.len() / c);
+ // let (fw, fh) = dsb::dims(&FONT, ppem);
+ dbg!(w, h);
+ dbg!(c, r);
+ // panic!();
+
+ let mut fonts = dsb::Fonts::new(
+ F::FontRef(*crate::FONT, &[(2003265652, 550.0)]),
+ F::instance(*crate::FONT, *crate::BFONT),
+ F::FontRef(*crate::IFONT, &[(2003265652, 550.0)]),
+ F::instance(*crate::IFONT, *crate::BIFONT),
+ );
+
+ let now = Instant::now();
+ let mut x = Image::build(w as _, h as _).fill(BG);
+ unsafe {
+ dsb::render(
+ &cells,
+ (c, r),
+ ppem,
+ BG,
+ &mut fonts,
+ lh,
+ true,
+ x.as_mut(),
+ )
+ };
+ println!("{:?}", now.elapsed());
+ x.as_ref().save("x");
+}