1use std::{ops::Range, sync::Arc};
5use theme::HighlightKind;
6use tree_sitter::Language;
7use tree_sitter_highlight::HighlightConfiguration;
8use tree_sitter_language::LanguageFn;
9
10pub enum Grammar {
15 Native(LanguageFn),
17 Wasm(Arc<[u8]>),
20}
21
22impl Grammar {
23 pub fn language(&self) -> Option<Language> {
26 match self {
27 Self::Native(grammar) => Some((*grammar).into()),
28 Self::Wasm(_) => None,
29 }
30 }
31}
32
33pub struct Lang {
34 pub name: &'static str,
35 pub aliases: &'static [&'static str],
36 pub grammar: Grammar,
37 pub query: &'static str,
38 pub injections: &'static str,
41}
42
43pub const NAMES: &[&str] = &[
50 "comment",
51 "comment.documentation",
52 "keyword",
53 "keyword.function",
54 "keyword.return",
55 "keyword.operator",
56 "keyword.conditional",
57 "keyword.conditional.ternary",
58 "keyword.coroutine",
59 "keyword.directive",
60 "keyword.exception",
61 "keyword.import",
62 "keyword.modifier",
63 "keyword.repeat",
64 "keyword.type",
65 "string",
66 "string.special",
67 "string.special.key",
68 "string.special.url",
69 "string.regexp",
70 "character.special",
71 "escape",
72 "string.escape",
73 "number",
74 "boolean",
75 "type",
76 "type.interface",
77 "type.builtin",
78 "constructor",
79 "function",
80 "function.method",
81 "function.method.call",
82 "function.call",
83 "function.builtin",
84 "macro",
85 "function.macro",
86 "property",
87 "property.definition",
88 "variable.member",
89 "constant",
90 "constant.builtin",
91 "module",
92 "module.builtin",
93 "variable",
94 "variable.builtin",
95 "variable.special",
96 "self",
97 "variable.parameter",
98 "parameter",
99 "operator",
100 "punctuation",
101 "punctuation.bracket",
102 "punctuation.delimiter",
103 "punctuation.special",
104 "tag",
105 "tag.builtin",
106 "tag.delimiter",
107 "attribute",
108 "tag.attribute",
109 "label",
110 "invalid",
111];
112
113pub struct Compiled {
116 pub config: HighlightConfiguration,
117 pub injected: Vec<String>,
120}
121
122impl Lang {
123 pub const fn new(
127 name: &'static str,
128 aliases: &'static [&'static str],
129 grammar: Grammar,
130 query: &'static str,
131 ) -> Self {
132 Self {
133 name,
134 aliases,
135 grammar,
136 query,
137 injections: "",
138 }
139 }
140
141 pub const fn with_injections(mut self, injections: &'static str) -> Self {
146 self.injections = injections;
147 self
148 }
149
150 pub fn highlight(&'static self, source: &str) -> Option<Vec<(Range<usize>, HighlightKind)>> {
153 crate::session::with(|session| session.highlight(self, source))
154 }
155
156 pub(crate) fn compile_with(&self, grammar: Language) -> Option<Compiled> {
160 let mut config =
161 HighlightConfiguration::new(grammar, self.name, self.query, self.injections, "")
162 .ok()?;
163 config.configure(NAMES);
164 let injected = (0..config.query.pattern_count())
165 .flat_map(|pattern| config.query.property_settings(pattern))
166 .filter(|property| property.key.as_ref() == "injection.language")
167 .filter_map(|property| property.value.as_ref().map(|value| value.to_string()))
168 .collect();
169 Some(Compiled { config, injected })
170 }
171}
172
173pub fn resolve(tag: &str) -> Option<&'static Lang> {
176 crate::registry::of_tag(tag)?.lang()
177}
178
179pub fn kind_of(name: &str) -> HighlightKind {
184 match name {
185 "comment" | "comment.documentation" => HighlightKind::Comment,
186 "keyword"
187 | "keyword.function"
188 | "keyword.return"
189 | "keyword.operator"
190 | "keyword.conditional"
191 | "keyword.conditional.ternary"
192 | "keyword.coroutine"
193 | "keyword.directive"
194 | "keyword.exception"
195 | "keyword.import"
196 | "keyword.modifier"
197 | "keyword.repeat"
198 | "keyword.type" => HighlightKind::Keyword,
199 "string" => HighlightKind::String,
200 "string.special" | "string.special.key" | "string.special.url" | "string.regexp"
201 | "character.special" => HighlightKind::StringSpecial,
202 "escape" | "string.escape" => HighlightKind::Escape,
203 "number" => HighlightKind::Number,
204 "boolean" => HighlightKind::Boolean,
205 "type" | "type.interface" => HighlightKind::TypeName,
206 "type.builtin" => HighlightKind::TypeBuiltin,
207 "constructor" => HighlightKind::Constructor,
208 "function" | "function.method" | "function.method.call" | "function.call" => {
209 HighlightKind::Function
210 }
211 "function.builtin" => HighlightKind::FunctionBuiltin,
212 "macro" | "function.macro" => HighlightKind::MacroName,
213 "property" | "property.definition" | "variable.member" => HighlightKind::Property,
214 "constant" | "constant.builtin" | "module" | "module.builtin" => HighlightKind::Constant,
215 "variable" | "variable.builtin" => HighlightKind::Variable,
216 "variable.special" | "self" => HighlightKind::VariableSpecial,
217 "variable.parameter" | "parameter" => HighlightKind::Parameter,
218 "operator" => HighlightKind::Operator,
219 "punctuation" | "punctuation.bracket" | "punctuation.delimiter" | "punctuation.special" => {
220 HighlightKind::Punctuation
221 }
222 "tag" | "tag.builtin" => HighlightKind::Tag,
223 "tag.delimiter" => HighlightKind::Punctuation,
224 "attribute" | "tag.attribute" => HighlightKind::Attribute,
225 "label" => HighlightKind::Label,
226 "invalid" => HighlightKind::Invalid,
227 _ => HighlightKind::Variable,
228 }
229}