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