From e4c0fc7beab2a6dd53210263a857f2b3ec29b604 Mon Sep 17 00:00:00 2001 From: Jonas Maier Date: Sat, 23 May 2026 14:48:51 +0200 Subject: customizable syntax highlighting --- src/parse/mod.rs | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 94 insertions(+), 5 deletions(-) (limited to 'src/parse/mod.rs') diff --git a/src/parse/mod.rs b/src/parse/mod.rs index 10ec666..8970fc3 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -1,4 +1,6 @@ -use crate::{BString, PushAll, bstr}; +use pish_derive::Variants; + +use crate::{BString, PushAll, bstr, variants::Variants}; #[cfg(test)] mod test; @@ -1042,7 +1044,7 @@ impl Parse for ExpString { let end = b.loc_u32(); b.highlights.push(Highlight { span: begin.to(end), - kind: HighlightKind::String, + kind: HighlightKind::Other(OtherHighlights::String), }); } } @@ -1296,11 +1298,94 @@ pub enum ParseMode { Completion, } -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum HighlightKind { None, - String, Keyword(Keyword), + Other(OtherHighlights), +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Variants)] +pub enum OtherHighlights { + String, +} + +impl OtherHighlights { + pub fn identifier(&self) -> &bstr { + match self { + OtherHighlights::String => b"string", + } + } +} + +impl HighlightKind { + /// all highlight kind variants *except* None + pub fn variants() -> impl Iterator { + let a = Keyword::VARIANTS + .into_iter() + .cloned() + .map(HighlightKind::Keyword); + let b = OtherHighlights::VARIANTS + .into_iter() + .cloned() + .map(HighlightKind::Other); + a.chain(b) + } + + /// an unique identifier such that we can refer to that in the builtin `pish_theme` + pub fn identifier(&self) -> &bstr { + match self { + HighlightKind::None => b"default", + HighlightKind::Keyword(keyword) => keyword.identifier(), + HighlightKind::Other(other) => other.identifier(), + } + } + + pub fn from_identifier(ident: &bstr) -> Vec { + match ident { + b"keywords" => { + return Keyword::VARIANTS + .into_iter() + .cloned() + .map(HighlightKind::Keyword) + .collect(); + } + b"braces" => { + return vec![ + HighlightKind::Keyword(Keyword::OpenBrace), + HighlightKind::Keyword(Keyword::CloseBrace), + ]; + } + b"all" | b"everything" => return Self::variants().collect(), + _ => (), + } + + Self::variants() + .into_iter() + .filter(|x| x.identifier() == ident) + .collect() + } + + pub fn all_identifiers() -> Vec { + let kw = Keyword::VARIANTS.into_iter().map(Keyword::identifier); + let ot = OtherHighlights::VARIANTS + .into_iter() + .map(OtherHighlights::identifier); + let groups = [&b"keywords"[..], b"braces", b"all", b"everything"]; + kw.chain(ot) + .chain(groups) + .map(|ident| ident.to_vec()) + .collect() + } +} + +#[test] +fn no_two_highlight_kinds_share_an_identifier() { + use std::collections::HashSet; + let unique_identifiers: HashSet = HighlightKind::variants() + .map(|x| x.identifier().to_vec()) + .collect(); + assert_eq!(unique_identifiers.len(), HighlightKind::variants().count()); } pub struct Highlight { @@ -1504,7 +1589,7 @@ impl<'a> Cursor<'a> { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Variants)] pub enum Keyword { If, While, @@ -1536,6 +1621,10 @@ impl Keyword { Keyword::CloseBrace => false, } } + + pub fn identifier(&self) -> &bstr { + self.as_bytes() + } } impl If { -- cgit v1.2.3