A simple CPU rendered GUI IDE experience.
Diffstat (limited to 'src/hov.rs')
| -rw-r--r-- | src/hov.rs | 403 |
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"); +} |