gpui_component/highlighter/
languages.rs

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    /// Return the language info for the language.
176    ///
177    /// (language, query, injection, locals)
178    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}