aboutsummaryrefslogtreecommitdiffstats
path: root/src/parse
diff options
context:
space:
mode:
authorJonas Maier <jonas@x77.dev>2026-05-23 14:48:51 +0200
committerJonas Maier <jonas@x77.dev>2026-05-23 14:48:51 +0200
commite4c0fc7beab2a6dd53210263a857f2b3ec29b604 (patch)
tree47137f101e5caaa93273cb03eeea92e0616537ca /src/parse
parentba9414b17a107bdb30fe462aa2d42f6e91b3ad74 (diff)
downloadpish-e4c0fc7beab2a6dd53210263a857f2b3ec29b604.tar.gz
customizable syntax highlighting
Diffstat (limited to 'src/parse')
-rw-r--r--src/parse/mod.rs99
1 files changed, 94 insertions, 5 deletions
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<Item = HighlightKind> {
+ 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<HighlightKind> {
+ 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<BString> {
+ 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<BString> = 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<PreExpansion> {