A simple CPU rendered GUI IDE experience.
Diffstat (limited to 'src/text.rs')
| -rw-r--r-- | src/text.rs | 138 |
1 files changed, 92 insertions, 46 deletions
diff --git a/src/text.rs b/src/text.rs index 3245f82..35b87a3 100644 --- a/src/text.rs +++ b/src/text.rs @@ -1,6 +1,3 @@ -use std::iter::{repeat, repeat_n}; -use std::os::fd::AsRawFd; - use atools::Chunked; use dsb::Cell; use dsb::cell::Style; @@ -27,24 +24,83 @@ const fn color(x: &[u8; 6]) -> [u8; 3] { |[a, b]| a * 16 + b ) } -#[test] -fn x() { - dbg!(color(b"ffd173")); -} +#[derive(Default)] pub struct TextArea { rope: Rope, cursor: usize, - // parser: Parser, highlighter: Highlighter, - tree: Option<Tree>, + column: usize, } impl TextArea { pub fn insert(&mut self, c: &str) { - dbg!(c); self.rope.insert(self.cursor, c); self.cursor += c.chars().count(); + self.setc(); + } + + 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); + (x, y) + } + + fn setc(&mut self) { + self.column = self.cursor + - self.rope.line_to_char(self.rope.char_to_line(self.cursor)); + } + + #[lower::apply(saturating)] + pub fn left(&mut self) { + self.cursor -= 1; + self.setc(); + } + + #[lower::apply(saturating)] + pub fn right(&mut self) { + self.cursor += 1; + self.cursor = self.cursor.min(self.rope.len_chars()); + self.setc(); + } + + pub fn down(&mut self) { + let l = self.rope.try_char_to_line(self.cursor).unwrap_or(0); + + // next line size + let Some(s) = self.rope.get_line(l + 1) else { + return; + }; + if s.len_chars() == 0 { + return self.cursor += 1; + } + // position of start of next line + let b = self.rope.line_to_char(l.wrapping_add(1)); + self.cursor = b + if s.len_chars() > self.column { + // if next line is long enough to position the cursor at column, do so + self.column + } else { + // otherwise, put it at the end of the next line, as it is too short. + s.len_chars() + - self + .rope + .get_line(l.wrapping_add(2)) + .map(|_| 1) + .unwrap_or(0) + }; + } + + pub fn up(&mut self) { + let l = self.rope.try_char_to_line(self.cursor).unwrap_or(0); + let Some(s) = self.rope.get_line(l.wrapping_sub(1)) else { + return; + }; + let b = self.rope.line_to_char(l - 1); + self.cursor = b + if s.len_chars() > self.column { + self.column + } else { + s.len_chars() - 1 + }; } pub fn backspace(&mut self) { @@ -61,7 +117,7 @@ impl TextArea { let mut x = HighlightConfiguration::new( tree_sitter_rust::LANGUAGE.into(), "rust", - tree_sitter_rust::HIGHLIGHTS_QUERY, + include_str!("queries.scm"), tree_sitter_rust::INJECTIONS_QUERY, "", ) @@ -99,26 +155,31 @@ impl TextArea { .map(Result::unwrap) { match hl { - HighlightEvent::Source { start, end } => { - // for elem in start..end { - // styles[elem] = s; - // } - let y1 = self.rope.char_to_line(start); - let y2 = self.rope.char_to_line(start); - let x1 = start - self.rope.line_to_char(y1); - let x2 = end - self.rope.line_to_char(y2); - // dbg!((x1, y1), (x2, y2)); - cells.get_mut(y1 * c + x1..y2 * c + x2).map(|x| { - x.iter_mut() - .for_each(|x| x.style.color = COLORS[s]) - }); - // println!( - // "highlight {} {s} {}: {:?}", - // self.rope.byte_slice(start..end), - // NAMES[s], - // COLORS[s], - // ) - } + HighlightEvent::Source { start, end } => drop::< + ropey::Result<()>, + >( + try { + // for elem in start..end { + // styles[elem] = s; + // } + let y1 = self.rope.try_char_to_line(start)?; + let y2 = self.rope.try_char_to_line(start)?; + let x1 = start - self.rope.try_line_to_char(y1)?; + let x2 = end - self.rope.try_line_to_char(y2)?; + // dbg!((x1, y1), (x2, y2)); + cells.get_mut(y1 * c + x1..y2 * c + x2).map(|x| { + x.iter_mut() + .for_each(|x| x.style.color = COLORS[s]) + }); + // println!( + // "highlight {} {s} {}: {:?}", + // self.rope.byte_slice(start..end), + // NAMES[s], + // COLORS[s], + // ) + () + }, + ), HighlightEvent::HighlightStart(s_) => s = s_.0, HighlightEvent::HighlightEnd => s = 0, } @@ -155,21 +216,6 @@ impl TextArea { } } -impl Default for TextArea { - fn default() -> Self { - // let mut parser = Highlighter::new(); - - let mut x = Self { - rope: Default::default(), - cursor: 0, - tree: None, - highlighter: Highlighter::new(), - }; - - x - } -} - pub trait TakeLine<'b> { fn take_line<'a>(&'a mut self) -> Option<&'b [u8]>; fn take_backline<'a>(&'a mut self) -> Option<&'b [u8]>; |