summaryrefslogtreecommitdiff
path: root/src/syntax/highlight.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/syntax/highlight.rs')
-rw-r--r--src/syntax/highlight.rs61
1 files changed, 61 insertions, 0 deletions
diff --git a/src/syntax/highlight.rs b/src/syntax/highlight.rs
index 9f7365a8..0f1ee89d 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,37 @@ where
}
}
+/// Provide syntect highlighting styles for the children of a node.
+pub fn highlight_syntect<F>(node: RedRef, highlighter: &Highlighter, f: &mut F)
+where
+ F: FnMut(Range<usize>, Style),
+{
+ highlight_syntect_impl(node, vec![], highlighter, f)
+}
+
+/// Recursive implementation for returning syntect styles.
+fn highlight_syntect_impl<F>(
+ node: RedRef,
+ scopes: Vec<Scope>,
+ highlighter: &Highlighter,
+ f: &mut F,
+) where
+ F: FnMut(Range<usize>, Style),
+{
+ if node.children().size_hint().0 == 0 {
+ f(node.span().to_range(), highlighter.style_for_stack(&scopes));
+ 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, scopes, highlighter, f);
+ }
+}
+
/// The syntax highlighting category of a node.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Category {
@@ -186,6 +220,33 @@ impl Category {
NodeKind::IncludeExpr => None,
}
}
+
+ /// Return the TextMate grammar scope for the given highlighting category.
+ pub 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)]