A simple CPU rendered GUI IDE experience.
hover wip
bendn 5 months ago
parent bc57f22 · commit 861504f
-rw-r--r--Cargo.toml3
-rw-r--r--src/hov.rs403
-rw-r--r--src/lsp.rs12
-rw-r--r--src/main.rs59
-rw-r--r--src/text.rs356
-rw-r--r--src/winit_app.rs10
6 files changed, 685 insertions, 158 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 23fc1dd..ae21f93 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -49,6 +49,9 @@ arc-swap = "1.7.1"
tokio = { version = "1.47.1", features = ["rt-multi-thread"] }
regex-cursor = "0.1.5"
papaya = "0.2.3"
+minimad = { git = "https://github.com/Canop/minimad", branch = "keep-code-fence", version = "0.13.1" }
+markdown = "1.0.0"
+itertools = "0.14.0"
[build-dependencies]
cc = "*"
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");
+}
diff --git a/src/lsp.rs b/src/lsp.rs
index 07ff21c..e5c8ae4 100644
--- a/src/lsp.rs
+++ b/src/lsp.rs
@@ -198,6 +198,13 @@ pub fn run(
..default()
}),
text_document: Some(TextDocumentClientCapabilities {
+ hover: Some(HoverClientCapabilities {
+ dynamic_registration: None,
+ content_format: Some(vec![
+ MarkupKind::PlainText,
+ MarkupKind::Markdown,
+ ]),
+ }),
semantic_tokens: Some(SemanticTokensClientCapabilities {
dynamic_registration: Some(false),
requests: SemanticTokensClientCapabilitiesRequests {
@@ -303,7 +310,7 @@ pub fn run(
recv(req_rx) -> x => match x {
Ok((x, y)) => {
debug!("received request {x}");
- assert!(map.insert(x, y).is_none());
+ assert!(map.insert(x, (y, Instant::now())).is_none());
}
Err(RecvError) => return,
},
@@ -326,7 +333,8 @@ pub fn run(
}
}
Ok(Message::Response(x)) => {
- if let Some(s) = map.remove(&x.id.i32()) {
+ if let Some((s, took)) = map.remove(&x.id.i32()) {
+ debug!("request {} took {:?}", x.id, took.elapsed());
match s.send(x) {
Ok(()) => {}
Err(e) => {
diff --git a/src/main.rs b/src/main.rs
index 35e9109..e0f5289 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,9 +1,13 @@
// this looks pretty good though
#![feature(tuple_trait, unboxed_closures, fn_traits)]
#![feature(
+ stmt_expr_attributes,
mpmc_channel,
const_cmp,
+ // generator_trait,
+ gen_blocks,
const_default,
+ coroutines,iter_from_coroutine,coroutine_trait,
cell_get_cloned,
import_trait_associated_functions,
if_let_guard,
@@ -16,6 +20,7 @@
#![allow(incomplete_features, redundant_semicolons)]
use std::convert::identity;
use std::io::BufReader;
+use std::mem::forget;
use std::num::NonZeroU32;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
@@ -30,11 +35,11 @@ use diff_match_patch_rs::PatchInput;
use dsb::cell::Style;
use dsb::{Cell, F};
use fimg::Image;
+use lsp_types::request::HoverRequest;
use lsp_types::{
- SemanticTokensOptions, SemanticTokensServerCapabilities,
- ServerCapabilities, TextDocumentIdentifier,
- TextDocumentPositionParams, WorkspaceFolder,
+ Hover, HoverParams, Position, SemanticTokensOptions, SemanticTokensServerCapabilities, ServerCapabilities, TextDocumentIdentifier, TextDocumentPositionParams, WorkspaceFolder
};
+use minimad::{Composite, CompositeStyle};
use parking_lot::RwLock;
use regex::Regex;
use ropey::Rope;
@@ -55,6 +60,7 @@ mod bar;
mod lsp;
mod text;
mod winit_app;
+mod hov;
fn main() {
env_logger::init();
// lsp::x();
@@ -503,6 +509,36 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
text.cursor = x;
*state.sel() = x..x;
}
+ Some(Do::Hover) => {
+ let hover = text.index_at(cursor_position);
+ let (x, y) =text.xy(hover);
+ let s = lsp.as_ref().map(|(c, o)| {
+ let (rx, id) = c.request::<HoverRequest>(&HoverParams {
+ text_document_position_params: TextDocumentPositionParams { text_document: TextDocumentIdentifier::new(Url::from_file_path(o).unwrap()), position: Position {
+ line: y as _, character: x as _,
+ }},
+ work_done_progress_params:default() }).unwrap();
+ c.runtime.spawn(async {
+ let x = rx.await?.load::<Hover>()?;
+ // dbg!(&x);
+ match x.contents {
+ lsp_types::HoverContents::Scalar(marked_string) => {
+ println!("{marked_string:?}");
+ },
+ lsp_types::HoverContents::Array(marked_strings) => {
+ println!("{marked_strings:?}");
+
+ },
+ lsp_types::HoverContents::Markup(markup_content) => {
+ println!("{}", markup_content.value);
+ // dbg!(minimad::Text::from(&*markup_content.value));
+ },
+ }
+ anyhow::Ok(())
+ })
+ });
+
+ }
None => {}
x => unreachable!("{x:?}"),
}
@@ -516,7 +552,7 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
if button == MouseButton::Left {
unsafe { CLICKING = true };
}
- match dbg!(state.consume(Action::M(button)).unwrap() ){
+ match state.consume(Action::M(button)).unwrap() {
Some(Do::MoveCursor) => {
text.cursor = text.index_at(cursor_position);
text.setc();
@@ -703,7 +739,7 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
};
}
Some(
- Do::MoveCursor | Do::ExtendSelectionToMouse,
+ Do::MoveCursor | Do::ExtendSelectionToMouse | Do::Hover,
) => {
unreachable!()
}
@@ -860,17 +896,18 @@ Dead => K(Key => _) => Dead,
Default => {
K(Key::Character(x) if x == "s" && ctrl()) => Save [Save],
K(Key::Character(x) if x == "q" && ctrl()) => Dead [Quit],
- K(Key::Character(x) if x == "v" && ctrl()) => Default [Paste],
- K(Key::Character(x) if x == "z" && ctrl()) => Default [Undo],
- K(Key::Character(x) if x == "y" && ctrl()) => Default [Redo],
+ K(Key::Character(x) if x == "v" && ctrl()) => _ [Paste],
+ K(Key::Character(x) if x == "z" && ctrl()) => _ [Undo],
+ K(Key::Character(x) if x == "y" && ctrl()) => _ [Redo],
K(Key::Character(x) if x == "f" && ctrl()) => Procure((default(), InputRequest::Search)),
K(Key::Character(x) if x == "o" && ctrl()) => Procure((default(), InputRequest::OpenFile)),
- K(Key::Character(x) if x == "c" && ctrl()) => Default,
+ K(Key::Character(x) if x == "c" && ctrl()) => _,
K(Key::Named(ArrowUp | ArrowLeft | ArrowDown | ArrowRight | Home | End) if shift()) => Selection(Range<usize> => 0..0) [StartSelection],
M(MouseButton => MouseButton::Left if shift()) => Selection(Range<usize> => 0..0) [StartSelection],
- M(MouseButton => MouseButton::Left) => Default [MoveCursor],
+ M(MouseButton => MouseButton::Left) => _ [MoveCursor],
C(((usize, usize)) => .. if unsafe { CLICKING }) => Selection(0..0) [StartSelection],
Changed => RequestBoolean(BoolRequest => BoolRequest::ReloadFile),
+ C(_ if false) => _ [Hover],
C(_) => _,
K(_) => _ [Edit],
M(_) => _,
@@ -880,7 +917,7 @@ Selection(x if shift()) => {
M(MouseButton => MouseButton::Left) => Selection(x) [ExtendSelectionToMouse],
}, // note: it does in fact fall through. this syntax is not an arm, merely shorthand.
Selection(x) => {
- C(_ if unsafe { CLICKING }) => Selection(x) [ExtendSelectionToMouse],
+ C(_ if unsafe { CLICKING }) => _ [ExtendSelectionToMouse],
C(_) => Selection(x),
M(MouseButton => MouseButton::Left) => Default [MoveCursor],
K(Key::Named(Backspace)) => Default [Delete(Range<usize> => x)],
diff --git a/src/text.rs b/src/text.rs
index 7b18be5..f35539f 100644
--- a/src/text.rs
+++ b/src/text.rs
@@ -1,22 +1,24 @@
use std::cmp::min;
use std::fmt::{Debug, Display};
-use std::ops::{Deref, Not as _, Range};
+use std::ops::{Deref, Not as _, Range, RangeBounds};
use std::path::Path;
+use std::pin::{Pin, pin};
use std::sync::{Arc, LazyLock};
+use std::vec::Vec;
use atools::prelude::*;
use diff_match_patch_rs::{DiffMatchPatch, Patches};
use dsb::Cell;
use dsb::cell::Style;
use helix_core::Syntax;
-use helix_core::syntax::{HighlightEvent, Loader};
+use helix_core::syntax::{HighlightEvent, Loader, reconfigure_highlights};
use implicit_fn::implicit_fn;
use log::error;
use lsp_types::{
SemanticToken, SemanticTokensLegend, SemanticTokensServerCapabilities,
};
use ropey::{Rope, RopeSlice};
-use tree_house::fixtures;
+use tree_house::{Language, fixtures};
use winit::keyboard::{NamedKey, SmolStr};
use crate::MODIFIERS;
@@ -32,11 +34,12 @@ macro_rules! theme {
),+];
};
}
-theme! { 15
+theme! { 16
"attribute" b"#ffd173",
"comment" b"#5c6773" Style::ITALIC,
"constant" b"#DFBFFF",
"function" b"#FFD173" Style::ITALIC,
+ "function.macro" b"#fbc351",
"variable.builtin" b"#FFAD66",
"keyword" b"#FFAD66" Style::ITALIC | Style::BOLD,
"number" b"#dfbfff",
@@ -82,7 +85,7 @@ mod semantic {
"enum" b"#73b9ff" Style::ITALIC | Style::BOLD,
"builtinType" b"#73d0ff" Style::ITALIC,
// "type" b"#73d0ff" Style::ITALIC | Style::BOLD,
- "typeAlias" b"#5ce6d8" Style::ITALIC | Style::BOLD,
+ "typeAlias" b"#69caed" Style::ITALIC | Style::BOLD,
"struct" b"#73d0ff" Style::ITALIC | Style::BOLD,
// "variable" b"#cccac2",
// "angle" b"#cccac2",
@@ -201,7 +204,6 @@ pub struct TextArea {
}
impl Debug for TextArea {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- String::new();
f.debug_struct("TextArea")
.field("rope", &self.rope)
.field("cursor", &self.cursor)
@@ -272,8 +274,12 @@ impl TextArea {
}
pub fn cursor(&self) -> (usize, usize) {
- let y = self.rope.char_to_line(self.cursor);
- let x = self.cursor - self.rope.line_to_char(y);
+ self.xy(self.cursor)
+ }
+
+ pub fn xy(&self, c: usize) -> (usize, usize) {
+ let y = self.rope.char_to_line(c);
+ let x = c - self.rope.line_to_char(y);
(x, y)
}
@@ -506,68 +512,56 @@ impl TextArea {
let language = path
.and_then(|x| LOADER.language_for_filename(x))
.unwrap_or_else(|| LOADER.language_for_name("rust").unwrap());
- let syntax =
- Syntax::new(self.rope.slice(..), language, &LOADER).unwrap();
-
- // println!(
- // "{}",
- // tree_house::fixtures::highlighter_fixture(
- // "hmm",
- // &*LOADER,
- // |y| NAMES[y.idx()].to_string(),
- // &syntax.inner,
- // self.rope.slice(..),
- // ..,
- // )
- // );
+
let s = self.rope.line_to_char(self.vo);
let e = self
.rope
- .try_line_to_char(self.vo + self.r + 20)
+ .try_line_to_char(self.vo + self.r * self.c)
.unwrap_or(self.rope.len_chars());
- let mut h = syntax.highlighter(
- self.rope.slice(..),
- &LOADER,
- s as u32..e as u32,
- );
- let mut at = 0;
- let (c, r) = (self.c, self.r);
+ for ((x1, y1), (x2, y2), s, _) in std::iter::from_coroutine(pin!(
+ hl(language, &self.rope, s as u32..e as u32, self.c)
+ )) {
+ cell.get_mut(y1 * self.c + x1..y2 * self.c + x2)
+ .map(|x| x.iter_mut().for_each(|x| x.style |= s));
+ }
- let mut highlight_stack = Vec::with_capacity(8);
- loop {
- let (e, new_highlights) = h.advance();
- if e == HighlightEvent::Refresh {
- highlight_stack.clear();
- }
- highlight_stack.extend(new_highlights);
+ // let mut highlight_stack = Vec::with_capacity(8);
+ // loop {
+ // let (e, new_highlights) = h.advance();
+ // if e == HighlightEvent::Refresh {
+ // highlight_stack.clear();
+ // }
+ // highlight_stack.extend(new_highlights);
- let end = h.next_event_offset() as _;
- if end == 4294967295 {
- break;
- }
- for &h in &highlight_stack {
- let y1 = self.rope.byte_to_line(at);
- let y2 = self.rope.byte_to_line(end);
- let x1 = min(
- self.rope.byte_to_char(at)
- - self.rope.line_to_char(y1),
- c,
- );
- let x2 = min(
- self.rope.byte_to_char(end)
- - self.rope.line_to_char(y2),
- c,
- );
-
- cell.get_mut(y1 * c + x1..y2 * c + x2).map(|x| {
- x.iter_mut().for_each(|x| {
- x.style.flags |= STYLES[h.idx()];
- x.style.color = COLORS[h.idx()];
- })
- });
- }
- at = end;
- }
+ // let end = h.next_event_offset() as _;
+ // if end == 4294967295 {
+ // break;
+ // }
+ // for &h in &highlight_stack {
+ // let y1 = self.rope.byte_to_line(at);
+ // let y2 = self.rope.byte_to_line(end);
+ // let x1 = min(
+ // self.rope.byte_to_char(at)
+ // - self.rope.line_to_char(y1),
+ // self.c,
+ // );
+ // let x2 = min(
+ // self.rope.byte_to_char(end)
+ // - self.rope.line_to_char(y2),
+ // self.c,
+ // );
+
+ // cell.get_mut(y1 * self.c + x1..y2 * self.c + x2).map(
+ // |x| {
+ // x.iter_mut().for_each(|x| {
+ // x.style.flags |= STYLES[h.idx()];
+ // x.style.color = COLORS[h.idx()];
+ // })
+ // },
+ // );
+ // }
+ // at = end;
+ // }
}
pub fn slice<'c>(
@@ -611,7 +605,10 @@ impl TextArea {
}
}
}
-
+ // let tokens = None::<(
+ // arc_swap::Guard<Arc<Box<[SemanticToken]>>>,
+ // &SemanticTokensLegend,
+ // )>;
if let Some((t, leg)) = tokens
&& t.len() > 0
{
@@ -862,75 +859,89 @@ impl TextArea {
fn is_word(r: char) -> bool {
matches!(r, 'a'..='z' | 'A'..='Z' | '0'..='9' | '_')
}
-static LOADER: LazyLock<Loader> = LazyLock::new(|| {
+pub static LOADER: LazyLock<Loader> = LazyLock::new(|| {
let x = helix_core::config::default_lang_loader();
x.set_scopes(NAMES.map(|x| x.to_string()).to_vec());
+
+ // x.languages().for_each(|(_, x)| {
+ // x.syntax_config(&LOADER).map(|x| {
+ // x.configure(|x| {
+ // // let x = set.entry(x.to_string()).or_insert_with(|| {
+ // // n += 1;
+ // // n
+ // // });
+ // // dbg!(x);
+ // NAMES
+ // .iter()
+ // .position(|&y| y == x)
+ // .map(|x| x as u32)
+ // .map(helix_core::syntax::Highlight::new)
+ // // Some(helix_core::syntax::Highlight::new(*x))
+ // })
+ // });
+ // });
x
});
-#[test]
+// #[test]
pub fn man() {
let query_str = r#"
(line_comment)+ @quantified_nodes
((line_comment)+) @quantified_nodes_grouped
((line_comment) (line_comment)) @multiple_nodes_grouped
"#;
- let source = Rope::from_str(
- r#"
-
- pub fn extend_selection_to(
- &mut self,
- to: usize,
- r: std::ops::Range<usize>,
- ) -> std::ops::Range<usize> {
- if [r.start, r.end].contains(&to) {
- return r;
- }
- let r = if self.cursor == r.start {
- if to < r.start {
- to..r.end
- } else if to > r.end {
- r.end..to
- } else {
- to..r.end
- }
- } else if self.cursor == r.end {
- if to > r.end {
- r.start..to
- } else if to < r.start {
- to..r.start
- } else {
- r.start..to
- }
- } else {
- panic!()
- };
- assert!(r.start < r.end);
- self.cursor = to;
- self.setc();
- r
- }
-"#,
- );
- let language = LOADER.language_for_name("rust").unwrap();
+ let source = Rope::from_str(r#"assert_eq!(0, Some(0));"#);
+ // dbg!(source.slice(70..));
+ // let mut set = std::collections::HashMap::new();
let mut n = 0;
- let mut set = std::collections::HashMap::new();
- LOADER.languages().for_each(|(_, x)| {
- x.syntax_config(&LOADER).map(|x| {
- x.configure(|x| {
- let x = set.entry(x.to_string()).or_insert_with(|| {
- n += 1;
- n
- });
- // dbg!(x);
- // NAMES
- // .iter()
- // .position(|&y| y == x)
- // .map(|x| x as u32)
- // .map(helix_core::syntax::Highlight::new)
- Some(helix_core::syntax::Highlight::new(*x))
- })
- });
- });
+ let loader = &*LOADER;
+ // loader.set_scopes(nam.map(|x| x.to_string()).to_vec());
+ let language = loader.language_for_name("rust").unwrap();
+ // for lang in [
+ // "rust-format-args",
+ // "rust-format-args-macro",
+ // "rust",
+ // "markdown-rustdoc",
+ // "comment",
+ // "regex",
+ // ] {
+ // let c = LOADER
+ // .language(LOADER.language_for_name(lang).unwrap())
+ // .syntax_config(&LOADER)
+ // .unwrap();
+ // reconfigure_highlights(c, &NAMES.map(|x| x.to_string()));
+ // // c.configure(|x| {
+ // // // NAMES
+ // // // .iter()
+ // // // .position(|&y| y == x)
+ // // // .map(|x| x as u32)
+ // // // .map(helix_core::syntax::Highlight::new)
+ // // let x = set.entry(x.to_string()).or_insert_with(|| {
+ // // n += 1;
+ // // n
+
+ // // });
+ // // dbg!(*x);
+ // // Some(helix_core::syntax::Highlight::new(*x))
+ // // })
+ // }
+ // let mut set = std::collections::HashMap::new();
+ // LOADER.languages().for_each(|(_, x)| {
+ // x.syntax_config(&LOADER).map(|x| {
+ // x.configure(|x| {
+ // // let x = set.entry(x.to_string()).or_insert_with(|| {
+ // // n += 1;
+ // // n
+ // // });
+ // // dbg!(x);
+ // NAMES
+ // .iter()
+ // .position(|&y| y == x)
+ // .map(|x| x as u32)
+ // .map(helix_core::syntax::Highlight::new)
+ // // Some(helix_core::syntax::Highlight::new(*x))
+ // })
+ // });
+ // });
// let c = LOADER.languages().next().unwrap().1;
// let grammar = LOADER.get_config(language).unwrap().grammar;
// let query = Query::new(grammar, query_str, |_, _| Ok(())).unwrap();
@@ -940,24 +951,24 @@ pub fn man() {
// &NAMES.map(|x| x.to_string()),
// );
- let syntax = Syntax::new(source.slice(..), language, &LOADER).unwrap();
+ let syntax = Syntax::new(source.slice(..), language, &loader).unwrap();
let mut h = syntax.highlighter(
source.slice(..),
- &LOADER,
+ &loader,
0..source.len_chars() as u32,
);
println!(
"{}",
tree_house::fixtures::highlighter_fixture(
"hmm",
- &*LOADER,
- |y| set
- .iter()
- .find(|x| x.1 == &y.get())
- .unwrap()
- .0
- .to_string(),
- // |y| NAMES[y.idx()].to_string(),
+ &loader,
+ // |y| set
+ // .iter()
+ // .find(|x| x.1 == &y.get())
+ // .unwrap()
+ // .0
+ // .to_string(),
+ |y| NAMES[y.idx()].to_string(),
&syntax.inner,
source.slice(..),
..,
@@ -970,13 +981,13 @@ pub fn man() {
// dbg!(hl.map(|x| NAMES[x.idx()]).collect::<Vec<_>>(), e);
dbg!(
h.active_highlights()
- .map(|y| set
- .iter()
- .find(|x| x.1 == &y.get())
- .unwrap()
- .0
- .to_string())
- // .map(|x| NAMES[x.idx()])
+ // .map(|y| set
+ // .iter()
+ // .find(|x| x.1 == &y.get())
+ // .unwrap()
+ // .0
+ // .to_string())
+ .map(|x| NAMES[x.idx()])
.collect::<Vec<_>>()
);
// panic!()
@@ -1002,3 +1013,68 @@ pub fn man() {
// test("quantified_nodes", 1..37);
panic!()
}
+
+pub fn hl(
+ lang: Language,
+ text: &'_ Rope,
+ r: impl RangeBounds<u32>,
+ c: usize,
+) -> impl std::ops::Coroutine<
+ Yield = ((usize, usize), (usize, usize), (u8, [u8; 3]), RopeSlice<'_>),
+ Return = (),
+> {
+ // println!(
+ // "{}",
+ // tree_house::fixtures::highlighter_fixture(
+ // "hmm",
+ // &*LOADER,
+ // |y| NAMES[y.idx()].to_string(),
+ // &syntax.inner,
+ // self.rope.slice(..),
+ // ..,
+ // )
+ // );
+ #[coroutine]
+ static move || {
+ println!("`\n{text}\n`");
+ let syntax = Syntax::new(text.slice(..), lang, &LOADER).unwrap();
+ let mut h = syntax.highlighter(text.slice(..), &LOADER, r);
+ let mut at = 0;
+
+ let mut highlight_stack = Vec::with_capacity(8);
+ loop {
+ let (e, new_highlights) = h.advance();
+ if e == HighlightEvent::Refresh {
+ highlight_stack.clear();
+ }
+ highlight_stack.extend(new_highlights);
+
+ let end = h.next_event_offset() as _;
+ if end == 4294967295 {
+ break;
+ }
+ for &h in &highlight_stack {
+ let y1 = text.byte_to_line(at);
+ let y2 = text.byte_to_line(end);
+ let x1 =
+ min(text.byte_to_char(at) - text.line_to_char(y1), c);
+ let x2 =
+ min(text.byte_to_char(end) - text.line_to_char(y2), c);
+
+ yield (
+ (x1, y1),
+ (x2, y2),
+ (STYLES[h.idx()], COLORS[h.idx()]),
+ (text.byte_slice(at..end)),
+ )
+ }
+ at = end;
+ }
+ }
+ // };
+ // std::iter::from_fn(move || {
+ // //
+ // use std::ops::Coroutine;
+ // Some(Pin::new(&mut x).resume(()))
+ // })
+}
diff --git a/src/winit_app.rs b/src/winit_app.rs
index 2d8c528..18f7258 100644
--- a/src/winit_app.rs
+++ b/src/winit_app.rs
@@ -39,19 +39,19 @@ pub(crate) fn make_window(
/// Easily constructable winit application.
pub(crate) struct WinitApp<T, S, Init, InitSurface, Handler> {
/// Closure to initialize `state`.
- init: Init,
+ pub init: Init,
/// Closure to initialize `surface_state`.
- init_surface: InitSurface,
+ pub init_surface: InitSurface,
/// Closure to run on window events.
- event: Handler,
+ pub event: Handler,
/// Contained state.
- state: Option<T>,
+ pub state: Option<T>,
/// Contained surface state.
- surface_state: Option<S>,
+ pub surface_state: Option<S>,
}
/// Builder that makes it so we don't have to name `T`.