A simple CPU rendered GUI IDE experience.
Diffstat (limited to 'src/text.rs')
| -rw-r--r-- | src/text.rs | 356 |
1 files changed, 216 insertions, 140 deletions
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(())) + // }) +} |