summaryrefslogtreecommitdiff
path: root/src/syntax
diff options
context:
space:
mode:
authorMartin Haug <mhaug@live.de>2021-12-14 14:24:02 +0100
committerMartin Haug <mhaug@live.de>2022-01-27 22:04:45 +0100
commit4f66907d08a8ed18b41e70188b112d7c915aa0bc (patch)
treefee27c337c8d60754e1e459b48084a7ab2f9af00 /src/syntax
parent3739ab77207e0e54edb55a110a16a1eb925b84f4 (diff)
Add Code Block syntax highlighting
Diffstat (limited to 'src/syntax')
-rw-r--r--src/syntax/highlight.rs69
1 files changed, 69 insertions, 0 deletions
diff --git a/src/syntax/highlight.rs b/src/syntax/highlight.rs
index 9f7365a8..001b28b3 100644
--- a/src/syntax/highlight.rs
+++ b/src/syntax/highlight.rs
@@ -1,5 +1,8 @@
use std::ops::Range;
+use syntect::highlighting::{Highlighter, Style};
+use syntect::parsing::Scope;
+
use super::{NodeKind, RedRef};
/// Provide highlighting categories for the children of a node that fall into a
@@ -19,6 +22,45 @@ where
}
}
+/// Provide syntect highlighting styles for the children of a node.
+pub fn highlight_syntect<F>(
+ node: RedRef,
+ text: &str,
+ highlighter: &Highlighter,
+ f: &mut F,
+) where
+ F: FnMut(Style, &str),
+{
+ highlight_syntect_impl(node, text, vec![], highlighter, f)
+}
+
+/// Recursive implementation for returning syntect styles.
+fn highlight_syntect_impl<F>(
+ node: RedRef,
+ text: &str,
+ scopes: Vec<Scope>,
+ highlighter: &Highlighter,
+ f: &mut F,
+) where
+ F: FnMut(Style, &str),
+{
+ if node.children().size_hint().0 == 0 {
+ f(
+ highlighter.style_for_stack(&scopes),
+ &text[node.span().to_range()],
+ );
+ return;
+ }
+
+ for child in node.children() {
+ let mut scopes = scopes.clone();
+ if let Some(category) = Category::determine(child, node) {
+ scopes.push(Scope::new(category.tm_scope()).unwrap())
+ }
+ highlight_syntect_impl(child, text, scopes, highlighter, f);
+ }
+}
+
/// The syntax highlighting category of a node.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Category {
@@ -186,6 +228,33 @@ impl Category {
NodeKind::IncludeExpr => None,
}
}
+
+ /// Return the TextMate grammar scope for the given highlighting category.
+ pub const fn tm_scope(&self) -> &'static str {
+ match self {
+ Self::Bracket => "punctuation.definition.typst",
+ Self::Punctuation => "punctuation.typst",
+ Self::Comment => "comment.typst",
+ Self::Strong => "markup.bold.typst",
+ Self::Emph => "markup.italic.typst",
+ Self::Raw => "markup.raw.typst",
+ Self::Math => "string.other.math.typst",
+ Self::Heading => "markup.heading.typst",
+ Self::List => "markup.list.typst",
+ Self::Shortcut => "punctuation.shortcut.typst",
+ Self::Escape => "constant.character.escape.content.typst",
+ Self::Keyword => "keyword.typst",
+ Self::Operator => "keyword.operator.typst",
+ Self::None => "constant.language.none.typst",
+ Self::Auto => "constant.language.auto.typst",
+ Self::Bool => "constant.language.boolean.typst",
+ Self::Number => "constant.numeric.typst",
+ Self::String => "string.quoted.double.typst",
+ Self::Function => "entity.name.function.typst",
+ Self::Variable => "variable.parameter.typst",
+ Self::Invalid => "invalid.typst",
+ }
+ }
}
#[cfg(test)]