A simple CPU rendered GUI IDE experience.
Diffstat (limited to 'src/text.rs')
| -rw-r--r-- | src/text.rs | 107 |
1 files changed, 66 insertions, 41 deletions
diff --git a/src/text.rs b/src/text.rs index c66d779..55eaf0d 100644 --- a/src/text.rs +++ b/src/text.rs @@ -23,9 +23,9 @@ use winit::keyboard::{NamedKey, SmolStr}; use crate::text::semantic::{MCOLORS, MODIFIED, MSTYLE}; macro_rules! theme { - ($n:literal $($x:literal $color:literal $($style:expr)?),+ $(,)?) => { + ($($x:literal $color:literal $($style:expr)?),+ $(,)?) => { #[rustfmt::skip] - pub const NAMES: [&str; $n] = [$($x),+]; + pub const NAMES: [&str; [$($x),+].len()] = [$($x),+]; #[rustfmt::skip] pub const COLORS: [[u8; 3]; NAMES.len()] = car::map!([$($color),+], |x| color(x.tail())); pub const STYLES: [u8; NAMES.len()] = [$( @@ -33,7 +33,7 @@ macro_rules! theme { ),+]; }; } -theme! { 16 +theme! { "attribute" b"#ffd173", "comment" b"#5c6773" Style::ITALIC, "constant" b"#DFBFFF", @@ -65,7 +65,10 @@ mod semantic { }; } use super::color; - theme! { 19 + theme! { + "constructor" b"#FFAD66", + "field" b"#cccac2", + "comment" b"#5c6773" Style::ITALIC, // "decorator" b"#cccac2", // "enumMember" b"#cccac2", @@ -81,12 +84,13 @@ mod semantic { "string" b"#D5FF80", // "struct" b"#cccac2", // "typeParameter" b"#cccac2", + "class" b"#73b9ff", "enum" b"#73b9ff" Style::ITALIC | Style::BOLD, "builtinType" b"#73d0ff" Style::ITALIC, // "type" b"#73d0ff" Style::ITALIC | Style::BOLD, "typeAlias" b"#69caed" Style::ITALIC | Style::BOLD, "struct" b"#73d0ff" Style::ITALIC | Style::BOLD, - // "variable" b"#cccac2", + "variable" b"#cccac2", // "angle" b"#cccac2", // "arithmetic" b"#cccac2", // "attributeBracket" b"#cccac2", @@ -143,7 +147,7 @@ const fn of(x: &'static str) -> usize { panic!() } -pub const fn color(x: &[u8; 6]) -> [u8; 3] { +pub const fn color(x: [u8; 6]) -> [u8; 3] { car::map!( car::map!(x, |b| (b & 0xF) + 9 * (b >> 6)).chunked::<2>(), |[a, b]| a * 16 + b @@ -292,6 +296,12 @@ impl TextArea { pub fn cursor(&self) -> (usize, usize) { self.xy(self.cursor) } + pub fn x(&self, c: usize) -> usize { + self.xy(c).0 + } + pub fn y(&self, c: usize) -> usize { + self.xy(c).1 + } pub fn xy(&self, c: usize) -> (usize, usize) { let y = self.rope.char_to_line(c); @@ -383,7 +393,7 @@ impl TextArea { self.set_ho(); } - fn at(&self) -> char { + pub fn at(&self) -> char { self.rope.get_char(self.cursor).unwrap_or('\n') } #[implicit_fn] @@ -418,42 +428,51 @@ impl TextArea { self.set_ho(); } // from μ - #[lower::apply(saturating)] pub fn word_left(&mut self) { - self.left(); - while self.at().is_whitespace() { - if self.cursor == 0 { - return; + self.cursor = self.word_left_p(); + self.setc(); + self.set_ho(); + } + #[lower::apply(saturating)] + pub fn word_left_p(&self) -> usize { + let mut c = self.cursor - 1; + if self.x(self.cursor) == 0 { + return c; + } + macro_rules! at { + () => { + self.rope.get_char(c).unwrap_or('\n') + }; + } + while at!().is_whitespace() { + if self.x(c) == 0 { + return c; } - self.left(); + c -= 1 } - if is_word(self.at()).not() - && !self.at().is_whitespace() - && !is_word(self.rope.char(self.cursor - 1)) + if is_word(at!()).not() + && !at!().is_whitespace() + && !is_word(self.rope.char(c - 1)) { - while is_word(self.at()).not() - && self.at().is_whitespace().not() - { - if self.cursor == 0 { - return; + while is_word(at!()).not() && at!().is_whitespace().not() { + if self.x(c) == 0 { + return c; } - self.left(); + c -= 1; } - self.right(); + c += 1; } else { - self.left(); - self.right(); - while is_word(self.at()) { - if self.cursor == 0 { - return; + c -= 1; + while is_word(at!()) { + if self.x(c) == 0 { + return c; } - self.left(); + c -= 1; } + c += 1; } - self.setc(); - self.set_ho(); + c } - pub fn enter(&mut self) { use run::Run; let n = self.indentation(); @@ -512,6 +531,12 @@ impl TextArea { } self.set_ho(); } + pub fn backspace_word(&mut self) { + _ = self.rope.try_remove(self.word_left_p()..self.cursor); + self.cursor = self.word_left_p(); + self.setc(); + self.set_ho(); + } #[lower::apply(saturating)] pub fn backspace(&mut self) { _ = self.rope.try_remove(self.cursor - 1..self.cursor); @@ -1353,12 +1378,12 @@ fn txt() { dbg!(o.as_chunks::<4>().0); } -// pub trait CoerceOption<T> { -// fn coerce(self) -> impl Iterator<Item = T>; -// } -// impl<I: Iterator<Item = T>, T> CoerceOption<T> for Option<I> { -// #[allow(refining_impl_trait)] -// fn coerce(self) -> std::iter::Flatten<std::option::IntoIter<I>> { -// self.into_iter().flatten() -// } -// } +pub trait CoerceOption<T> { + fn coerce(self) -> impl Iterator<Item = T>; +} +impl<I: Iterator<Item = T>, T> CoerceOption<T> for Option<I> { + #[allow(refining_impl_trait)] + fn coerce(self) -> std::iter::Flatten<std::option::IntoIter<I>> { + self.into_iter().flatten() + } +} |