A simple CPU rendered GUI IDE experience.
Diffstat (limited to 'src/text/semantic_tokens.rs')
-rw-r--r--src/text/semantic_tokens.rs197
1 files changed, 197 insertions, 0 deletions
diff --git a/src/text/semantic_tokens.rs b/src/text/semantic_tokens.rs
new file mode 100644
index 0000000..196f1ff
--- /dev/null
+++ b/src/text/semantic_tokens.rs
@@ -0,0 +1,197 @@
+use dsb::cell::Style;
+use log::error;
+use lsp_types::{SemanticToken, SemanticTokensLegend};
+use serde_derive::{Deserialize, Serialize};
+
+macro_rules! modified {
+ ($count:literal $($x:literal . $mod:literal $color:literal $($style:expr)?,)+ $(,)?) => {
+ pub const MODIFIED: [(&str, &str); $count] = [
+ $(($x, $mod),)+
+ ];
+ pub const MCOLORS: [[u8;3]; MODIFIED.len()] = car::map!([$($color),+], |x| color(x));
+ pub const MSTYLE: [u8; MODIFIED.len()] = [$(($($style, )? 0, ).0 ,)+];
+ }
+}
+use super::color;
+macro_rules! theme {
+ ($($x:literal $color:literal $($style:expr)?),+ $(,)?) => {
+ #[rustfmt::skip]
+ pub const NAMES: [&str; [$($x),+].len()] = [$($x),+];
+ #[rustfmt::skip]
+ pub const COLORS: [[u8; 3]; NAMES.len()] = car::map!([$($color),+], |x| color(x));
+ pub const STYLES: [u8; NAMES.len()] = [$(
+ ($($style, )? 0, ).0
+ ),+];
+ };
+}
+pub(crate) use theme;
+theme! {
+"constructor" b"#FFAD66",
+"field" b"#cccac2",
+
+"comment" b"#5c6773" Style::ITALIC,
+// "decorator" b"#cccac2",
+"function" b"#FFD173" Style::ITALIC,
+"interface" b"#5CCFE6",
+"keyword" b"#FFAD66" Style::ITALIC | Style::BOLD,
+"macro" b"#fbc351" Style::BOLD,
+"method" b"#FFD173" Style::ITALIC,
+// "namespace" b"#cccac2",
+"number" b"#dfbfff",
+"operator" b"#F29E74",
+// "property" b"#cccac2",
+"string" b"#D5FF80",
+// "struct" b"#cccac2",
+// "typeParameter" b"#cccac2",
+"class" b"#73b9ff",
+"enumMember" 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",
+// "angle" b"#cccac2",
+// "arithmetic" b"#cccac2",
+// "attributeBracket" b"#cccac2",
+"parameter" b"#DFBFFF",
+"namespace" b"#73d0ff",
+// "attributeBracket" b"#cccac2",
+// "attribute" b"#cccac2",
+// "bitwise" b"#cccac2",
+// "boolean" b"#cccac2",
+// "brace" b"#cccac2",
+// "bracket" b"#cccac2",
+// "builtinAttribute" b"#cccac2",
+// "character" b"#cccac2",
+// "colon" b"#cccac2",
+// "comma" b"#cccac2",
+// "comparison" b"#cccac2",
+// "constParameter" b"#cccac2",
+"const" b"#DFBFFF",
+// "deriveHelper" b"#cccac2",
+// "derive" b"#cccac2",
+// "dot" b"#cccac2",
+// "escapeSequence" b"#cccac2",
+// "formatSpecifier" b"#cccac2",
+// "generic" b"#cccac2",
+// "invalidEscapeSequence" b"#cccac2",
+// "label" b"#cccac2",
+// "lifetime" b"#cccac2",
+// "logical" b"#cccac2",
+"macroBang" b"#f28f74",
+// "parenthesis" b"#cccac2",
+// "procMacro" b"#cccac2",
+// "punctuation" b"#cccac2",
+"selfKeyword" b"#FFAD66" Style::ITALIC | Style::BOLD,
+"selfTypeKeyword" b"#FFAD66" Style::ITALIC | Style::BOLD,
+// "semicolon" b"#cccac2",
+// "static" b"#cccac2",
+// "toolModule" b"#cccac2",
+// "union" b"#cccac2",
+// "unresolvedReference" b"#cccac2",
+}
+const fn of(x: &'static str) -> usize {
+ let mut i = 0;
+ while i < NAMES.len() {
+ if NAMES[i] == x {
+ return i;
+ }
+ i += 1;
+ }
+ panic!()
+}
+
+modified! { 2
+ "function" . "unsafe" b"#F28779",
+ "variable" . "mutable" b"#e6dab6",
+}
+use crate::text::TextArea;
+
+#[derive(
+ Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize,
+)]
+pub struct TokenD {
+ pub ty: u32,
+ pub modifiers: u32,
+}
+impl TokenD {
+ pub fn style(self, leg: &SemanticTokensLegend) -> Style {
+ let mut sty = Style::new(crate::FG, crate::BG);
+ let Some(tty) = leg.token_types.get(self.ty as usize) else {
+ error!(
+ "issue while loading semantic token {self:?}; couldnt \
+ find in legend"
+ );
+ return sty;
+ };
+ if let Some(f) = NAMES.iter().position(|&x| x == tty.as_str()) {
+ // cells
+ // .get_range_enumerated((x1, ln as _), (x2, ln as _))
+ // .filter(|(_, i)| {
+ // matches!(src_map.get(i.0), Some(Mapping::Char(..)))
+ // })
+ // .for_each(|(x, _)| {
+ sty.fg = COLORS[f];
+ sty.flags |= STYLES[f];
+ // });
+ }
+ // println!(
+ // "{tty:?}: {}",
+ // slice.iter().flat_map(|x| x.letter).collect::<String>()
+ // );
+ let mut modi = self.modifiers;
+ while modi != 0 {
+ let bit = modi.trailing_zeros();
+
+ leg.token_modifiers
+ .get(bit as usize)
+ .and_then(|modi| {
+ MODIFIED.iter().position(|&(x, y)| {
+ (x == tty.as_str()) & (y == modi.as_str())
+ })
+ })
+ .map(|i| {
+ sty.fg = MCOLORS[i];
+ sty.flags |= MSTYLE[i];
+ });
+
+ modi &= !(1 << bit);
+ }
+ sty
+ }
+}
+impl TextArea {
+ pub fn set_toks(&mut self, toks: &[SemanticToken]) {
+ let mut ln = 0;
+ let mut ch = 0;
+ self.tokens.clear();
+ for t in toks {
+ ln += t.delta_line;
+ ch = match t.delta_line {
+ 1.. => t.delta_start,
+ 0 => ch + t.delta_start,
+ };
+ let Ok((x1, x2)): ropey::Result<_> = (try {
+ let p1 = self.rope.try_byte_to_char(
+ self.rope.try_line_to_byte(ln as _)? + ch as usize,
+ )?;
+ let p2 = self.rope.try_byte_to_char(
+ self.rope.try_line_to_byte(ln as _)?
+ + ch as usize
+ + t.length as usize,
+ )?;
+ (p1 as u32, p2 as u32)
+ }) else {
+ continue;
+ };
+ self.tokens.insert(
+ x1..x2,
+ TokenD {
+ ty: t.token_type,
+ modifiers: t.token_modifiers_bitset,
+ },
+ );
+ }
+ }
+}