1use gpui::SharedString;
2
3use crate::highlighter::LanguageConfig;
4
5#[cfg(not(feature = "tree-sitter-languages"))]
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, enum_iterator::Sequence)]
7pub enum Language {
8 Json,
9}
10
11#[cfg(feature = "tree-sitter-languages")]
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, enum_iterator::Sequence)]
13pub enum Language {
14 Json,
15 Plain,
16 Bash,
17 C,
18 CMake,
19 CSharp,
20 Cpp,
21 Css,
22 Diff,
23 Ejs,
24 Elixir,
25 Erb,
26 Go,
27 GraphQL,
28 Html,
29 Java,
30 JavaScript,
31 JsDoc,
32 Make,
33 Markdown,
34 MarkdownInline,
35 Proto,
36 Python,
37 Ruby,
38 Rust,
39 Scala,
40 Sql,
41 Swift,
42 Toml,
43 Tsx,
44 TypeScript,
45 Yaml,
46 Zig,
47}
48
49impl From<Language> for SharedString {
50 fn from(language: Language) -> Self {
51 language.name().into()
52 }
53}
54
55impl Language {
56 pub fn all() -> impl Iterator<Item = Self> {
57 enum_iterator::all::<Language>()
58 }
59
60 pub fn name(&self) -> &'static str {
61 #[cfg(not(feature = "tree-sitter-languages"))]
62 return "json";
63
64 #[cfg(feature = "tree-sitter-languages")]
65 match self {
66 Self::Plain => "text",
67 Self::Bash => "bash",
68 Self::C => "c",
69 Self::CMake => "cmake",
70 Self::CSharp => "csharp",
71 Self::Cpp => "cpp",
72 Self::Css => "css",
73 Self::Diff => "diff",
74 Self::Ejs => "ejs",
75 Self::Elixir => "elixir",
76 Self::Erb => "erb",
77 Self::Go => "go",
78 Self::GraphQL => "graphql",
79 Self::Html => "html",
80 Self::Java => "java",
81 Self::JavaScript => "javascript",
82 Self::JsDoc => "jsdoc",
83 Self::Json => "json",
84 Self::Make => "make",
85 Self::Markdown => "markdown",
86 Self::MarkdownInline => "markdown_inline",
87 Self::Proto => "proto",
88 Self::Python => "python",
89 Self::Ruby => "ruby",
90 Self::Rust => "rust",
91 Self::Scala => "scala",
92 Self::Sql => "sql",
93 Self::Swift => "swift",
94 Self::Toml => "toml",
95 Self::Tsx => "tsx",
96 Self::TypeScript => "typescript",
97 Self::Yaml => "yaml",
98 Self::Zig => "zig",
99 }
100 }
101
102 #[allow(unused)]
103 pub fn from_str(s: &str) -> Self {
104 #[cfg(not(feature = "tree-sitter-languages"))]
105 return Self::Json;
106
107 #[cfg(feature = "tree-sitter-languages")]
108 match s {
109 "bash" | "sh" => Self::Bash,
110 "c" => Self::C,
111 "cmake" => Self::CMake,
112 "cpp" | "c++" => Self::Cpp,
113 "csharp" | "cs" => Self::CSharp,
114 "css" | "scss" => Self::Css,
115 "diff" => Self::Diff,
116 "ejs" => Self::Ejs,
117 "elixir" | "ex" => Self::Elixir,
118 "erb" => Self::Erb,
119 "go" => Self::Go,
120 "graphql" => Self::GraphQL,
121 "html" => Self::Html,
122 "java" => Self::Java,
123 "javascript" | "js" => Self::JavaScript,
124 "jsdoc" => Self::JsDoc,
125 "json" | "jsonc" => Self::Json,
126 "make" | "makefile" => Self::Make,
127 "markdown" | "md" | "mdx" => Self::Markdown,
128 "markdown_inline" | "markdown-inline" => Self::MarkdownInline,
129 "proto" | "protobuf" => Self::Proto,
130 "python" | "py" => Self::Python,
131 "ruby" | "rb" => Self::Ruby,
132 "rust" | "rs" => Self::Rust,
133 "scala" => Self::Scala,
134 "sql" => Self::Sql,
135 "swift" => Self::Swift,
136 "toml" => Self::Toml,
137 "tsx" => Self::Tsx,
138 "typescript" | "ts" => Self::TypeScript,
139 "yaml" | "yml" => Self::Yaml,
140 "zig" => Self::Zig,
141 _ => Self::Plain,
142 }
143 }
144
145 #[allow(unused)]
146 pub(super) fn injection_languages(&self) -> Vec<SharedString> {
147 #[cfg(not(feature = "tree-sitter-languages"))]
148 return vec![];
149
150 #[cfg(feature = "tree-sitter-languages")]
151 match self {
152 Self::Markdown => vec!["markdown-inline", "html", "toml", "yaml"],
153 Self::MarkdownInline => vec![],
154 Self::Html => vec!["javascript", "css"],
155 Self::Rust => vec!["rust"],
156 Self::JavaScript | Self::TypeScript => vec![
157 "jsdoc",
158 "json",
159 "css",
160 "html",
161 "sql",
162 "typescript",
163 "javascript",
164 "tsx",
165 "yaml",
166 "graphql",
167 ],
168 _ => vec![],
169 }
170 .into_iter()
171 .map(|s| s.into())
172 .collect()
173 }
174
175 pub(super) fn config(&self) -> LanguageConfig {
179 #[cfg(not(feature = "tree-sitter-languages"))]
180 let (language, query, injection, locals) = match self {
181 Self::Json => (
182 tree_sitter_json::LANGUAGE,
183 include_str!("languages/json/highlights.scm"),
184 "",
185 "",
186 ),
187 };
188
189 #[cfg(feature = "tree-sitter-languages")]
190 let (language, query, injection, locals) = match self {
191 Self::Plain => (tree_sitter_json::LANGUAGE, "", "", ""),
192 Self::Json => (
193 tree_sitter_json::LANGUAGE,
194 include_str!("languages/json/highlights.scm"),
195 "",
196 "",
197 ),
198 Self::Markdown => (
199 tree_sitter_md::LANGUAGE,
200 include_str!("languages/markdown/highlights.scm"),
201 include_str!("languages/markdown/injections.scm"),
202 "",
203 ),
204 Self::MarkdownInline => (
205 tree_sitter_md::INLINE_LANGUAGE,
206 include_str!("languages/markdown_inline/highlights.scm"),
207 "",
208 "",
209 ),
210 Self::Toml => (
211 tree_sitter_toml_ng::LANGUAGE,
212 tree_sitter_toml_ng::HIGHLIGHTS_QUERY,
213 "",
214 "",
215 ),
216 Self::Yaml => (
217 tree_sitter_yaml::LANGUAGE,
218 tree_sitter_yaml::HIGHLIGHTS_QUERY,
219 "",
220 "",
221 ),
222 Self::Rust => (
223 tree_sitter_rust::LANGUAGE,
224 include_str!("languages/rust/highlights.scm"),
225 include_str!("languages/rust/injections.scm"),
226 "",
227 ),
228 Self::Go => (
229 tree_sitter_go::LANGUAGE,
230 include_str!("languages/go/highlights.scm"),
231 "",
232 "",
233 ),
234 Self::C => (
235 tree_sitter_c::LANGUAGE,
236 tree_sitter_c::HIGHLIGHT_QUERY,
237 "",
238 "",
239 ),
240 Self::Cpp => (
241 tree_sitter_cpp::LANGUAGE,
242 tree_sitter_cpp::HIGHLIGHT_QUERY,
243 "",
244 "",
245 ),
246 Self::JavaScript => (
247 tree_sitter_javascript::LANGUAGE,
248 include_str!("languages/javascript/highlights.scm"),
249 include_str!("languages/javascript/injections.scm"),
250 tree_sitter_javascript::LOCALS_QUERY,
251 ),
252 Self::JsDoc => (
253 tree_sitter_jsdoc::LANGUAGE,
254 tree_sitter_jsdoc::HIGHLIGHTS_QUERY,
255 "",
256 "",
257 ),
258 Self::Zig => (
259 tree_sitter_zig::LANGUAGE,
260 include_str!("languages/zig/highlights.scm"),
261 include_str!("languages/zig/injections.scm"),
262 "",
263 ),
264 Self::Java => (
265 tree_sitter_java::LANGUAGE,
266 tree_sitter_java::HIGHLIGHTS_QUERY,
267 "",
268 "",
269 ),
270 Self::Python => (
271 tree_sitter_python::LANGUAGE,
272 tree_sitter_python::HIGHLIGHTS_QUERY,
273 "",
274 "",
275 ),
276 Self::Ruby => (
277 tree_sitter_ruby::LANGUAGE,
278 tree_sitter_ruby::HIGHLIGHTS_QUERY,
279 "",
280 tree_sitter_ruby::LOCALS_QUERY,
281 ),
282 Self::Bash => (
283 tree_sitter_bash::LANGUAGE,
284 tree_sitter_bash::HIGHLIGHT_QUERY,
285 "",
286 "",
287 ),
288 Self::Html => (
289 tree_sitter_html::LANGUAGE,
290 include_str!("languages/html/highlights.scm"),
291 include_str!("languages/html/injections.scm"),
292 "",
293 ),
294 Self::Css => (
295 tree_sitter_css::LANGUAGE,
296 tree_sitter_css::HIGHLIGHTS_QUERY,
297 "",
298 "",
299 ),
300 Self::Swift => (tree_sitter_swift::LANGUAGE, "", "", ""),
301 Self::Scala => (
302 tree_sitter_scala::LANGUAGE,
303 tree_sitter_scala::HIGHLIGHTS_QUERY,
304 "",
305 tree_sitter_scala::LOCALS_QUERY,
306 ),
307 Self::Sql => (
308 tree_sitter_sequel::LANGUAGE,
309 tree_sitter_sequel::HIGHLIGHTS_QUERY,
310 "",
311 "",
312 ),
313 Self::CSharp => (tree_sitter_c_sharp::LANGUAGE, "", "", ""),
314 Self::GraphQL => (tree_sitter_graphql::LANGUAGE, "", "", ""),
315 Self::Proto => (tree_sitter_proto::LANGUAGE, "", "", ""),
316 Self::Make => (
317 tree_sitter_make::LANGUAGE,
318 tree_sitter_make::HIGHLIGHTS_QUERY,
319 "",
320 "",
321 ),
322 Self::CMake => (tree_sitter_cmake::LANGUAGE, "", "", ""),
323 Self::TypeScript => (
324 tree_sitter_typescript::LANGUAGE_TYPESCRIPT,
325 include_str!("languages/typescript/highlights.scm"),
326 include_str!("languages/javascript/injections.scm"),
327 tree_sitter_typescript::LOCALS_QUERY,
328 ),
329 Self::Tsx => (
330 tree_sitter_typescript::LANGUAGE_TSX,
331 tree_sitter_typescript::HIGHLIGHTS_QUERY,
332 "",
333 tree_sitter_typescript::LOCALS_QUERY,
334 ),
335 Self::Diff => (
336 tree_sitter_diff::LANGUAGE,
337 tree_sitter_diff::HIGHLIGHTS_QUERY,
338 "",
339 "",
340 ),
341 Self::Elixir => (
342 tree_sitter_elixir::LANGUAGE,
343 tree_sitter_elixir::HIGHLIGHTS_QUERY,
344 tree_sitter_elixir::INJECTIONS_QUERY,
345 "",
346 ),
347 Self::Erb => (
348 tree_sitter_embedded_template::LANGUAGE,
349 tree_sitter_embedded_template::HIGHLIGHTS_QUERY,
350 tree_sitter_embedded_template::INJECTIONS_EJS_QUERY,
351 "",
352 ),
353 Self::Ejs => (
354 tree_sitter_embedded_template::LANGUAGE,
355 tree_sitter_embedded_template::HIGHLIGHTS_QUERY,
356 tree_sitter_embedded_template::INJECTIONS_EJS_QUERY,
357 "",
358 ),
359 };
360
361 let language = tree_sitter::Language::new(language);
362
363 LanguageConfig::new(
364 self.name(),
365 language,
366 self.injection_languages(),
367 query,
368 injection,
369 locals,
370 )
371 }
372}
373
374#[cfg(test)]
375mod tests {
376 #[test]
377 #[cfg(feature = "tree-sitter-languages")]
378 fn test_language_name() {
379 use super::*;
380
381 assert_eq!(Language::MarkdownInline.name(), "markdown_inline");
382 assert_eq!(Language::Markdown.name(), "markdown");
383 assert_eq!(Language::Json.name(), "json");
384 assert_eq!(Language::Yaml.name(), "yaml");
385 assert_eq!(Language::Rust.name(), "rust");
386 assert_eq!(Language::Go.name(), "go");
387 assert_eq!(Language::C.name(), "c");
388 assert_eq!(Language::Cpp.name(), "cpp");
389 assert_eq!(Language::Sql.name(), "sql");
390 assert_eq!(Language::JavaScript.name(), "javascript");
391 assert_eq!(Language::Zig.name(), "zig");
392 assert_eq!(Language::CSharp.name(), "csharp");
393 assert_eq!(Language::TypeScript.name(), "typescript");
394 assert_eq!(Language::Tsx.name(), "tsx");
395 assert_eq!(Language::Diff.name(), "diff");
396 assert_eq!(Language::Elixir.name(), "elixir");
397 assert_eq!(Language::Erb.name(), "erb");
398 assert_eq!(Language::Ejs.name(), "ejs");
399 }
400}