Skip to main content

_diffctx/
languages.rs

1use once_cell::sync::Lazy;
2use rustc_hash::FxHashMap;
3use std::path::Path;
4
5pub static EXTENSION_TO_LANGUAGE: Lazy<FxHashMap<&'static str, &'static str>> = Lazy::new(|| {
6    let entries: &[(&str, &str)] = &[
7        (".py", "python"),
8        (".pyw", "python"),
9        (".pyi", "python"),
10        (".js", "javascript"),
11        (".mjs", "javascript"),
12        (".cjs", "javascript"),
13        (".jsx", "jsx"),
14        (".ts", "typescript"),
15        (".tsx", "tsx"),
16        (".mts", "typescript"),
17        (".cts", "typescript"),
18        (".json", "json"),
19        (".yaml", "yaml"),
20        (".yml", "yaml"),
21        (".toml", "toml"),
22        (".md", "markdown"),
23        (".markdown", "markdown"),
24        (".html", "html"),
25        (".htm", "html"),
26        (".css", "css"),
27        (".scss", "scss"),
28        (".less", "less"),
29        (".xml", "xml"),
30        (".svg", "xml"),
31        (".sh", "bash"),
32        (".bash", "bash"),
33        (".zsh", "zsh"),
34        (".fish", "fish"),
35        (".ksh", "bash"),
36        (".ps1", "powershell"),
37        (".psm1", "powershell"),
38        (".psd1", "powershell"),
39        (".bat", "batch"),
40        (".cmd", "batch"),
41        (".c", "c"),
42        (".h", "c"),
43        (".cpp", "cpp"),
44        (".cc", "cpp"),
45        (".cxx", "cpp"),
46        (".hpp", "cpp"),
47        (".hh", "cpp"),
48        (".hxx", "cpp"),
49        (".cs", "csharp"),
50        (".fs", "fsharp"),
51        (".fsi", "fsharp"),
52        (".fsx", "fsharp"),
53        (".java", "java"),
54        (".kt", "kotlin"),
55        (".kts", "kotlin"),
56        (".scala", "scala"),
57        (".sc", "scala"),
58        (".go", "go"),
59        (".rs", "rust"),
60        (".rb", "ruby"),
61        (".rake", "ruby"),
62        (".gemspec", "ruby"),
63        (".php", "php"),
64        (".swift", "swift"),
65        (".m", "objectivec"),
66        (".mm", "objectivec"),
67        (".r", "r"),
68        (".lua", "lua"),
69        (".pl", "perl"),
70        (".pm", "perl"),
71        (".ex", "elixir"),
72        (".exs", "elixir"),
73        (".erl", "erlang"),
74        (".hrl", "erlang"),
75        (".hs", "haskell"),
76        (".lhs", "haskell"),
77        (".ml", "ocaml"),
78        (".mli", "ocaml"),
79        (".clj", "clojure"),
80        (".cljs", "clojure"),
81        (".cljc", "clojure"),
82        (".sql", "sql"),
83        (".graphql", "graphql"),
84        (".gql", "graphql"),
85        (".proto", "protobuf"),
86        (".dockerfile", "dockerfile"),
87        (".tf", "terraform"),
88        (".hcl", "hcl"),
89        (".vim", "vim"),
90        (".el", "elisp"),
91        (".lisp", "lisp"),
92        (".scm", "scheme"),
93        (".rkt", "racket"),
94        (".zig", "zig"),
95        (".nim", "nim"),
96        (".v", "v"),
97        (".sv", "systemverilog"),
98        (".vhd", "vhdl"),
99        (".vhdl", "vhdl"),
100        (".d", "d"),
101        (".dart", "dart"),
102        (".groovy", "groovy"),
103        (".gradle", "groovy"),
104        (".jl", "julia"),
105        (".ini", "ini"),
106        (".cfg", "ini"),
107        (".conf", "ini"),
108        (".properties", "properties"),
109        (".env", "dotenv"),
110        (".ada", "ada"),
111        (".pas", "pascal"),
112        (".f90", "fortran"),
113        (".f95", "fortran"),
114        (".cob", "cobol"),
115        (".asm", "asm"),
116        (".s", "asm"),
117        (".c++", "cpp"),
118        (".h++", "cpp"),
119        (".ipp", "cpp"),
120        (".tpp", "cpp"),
121        (".phtml", "php"),
122        (".php3", "php"),
123        (".php4", "php"),
124        (".php5", "php"),
125        (".php7", "php"),
126        (".phps", "php"),
127        (".adoc", "asciidoc"),
128        (".editorconfig", "editorconfig"),
129        (".tex", "latex"),
130        (".latex", "latex"),
131        (".rst", "rst"),
132        (".txt", "text"),
133        (".log", "text"),
134        (".diff", "diff"),
135        (".patch", "diff"),
136        (".vue", "vue"),
137        (".svelte", "svelte"),
138        (".sty", "latex"),
139        (".cls", "latex"),
140        (".bst", "latex"),
141        (".dtx", "latex"),
142        (".bib", "bibtex"),
143        (".nix", "nix"),
144        (".prisma", "prisma"),
145        (".bzl", "bazel"),
146        (".j2", "jinja"),
147        (".jinja", "jinja"),
148        (".jinja2", "jinja"),
149    ];
150
151    let mut map = FxHashMap::with_capacity_and_hasher(entries.len(), Default::default());
152    for &(ext, lang) in entries {
153        map.insert(ext, lang);
154    }
155    map
156});
157
158pub static FILENAME_TO_LANGUAGE: Lazy<FxHashMap<&'static str, &'static str>> = Lazy::new(|| {
159    let entries: &[(&str, &str)] = &[
160        ("makefile", "makefile"),
161        ("gnumakefile", "makefile"),
162        ("dockerfile", "dockerfile"),
163        ("containerfile", "dockerfile"),
164        ("vagrantfile", "ruby"),
165        ("gemfile", "ruby"),
166        ("rakefile", "ruby"),
167        ("guardfile", "ruby"),
168        ("brewfile", "ruby"),
169        ("podfile", "ruby"),
170        ("cmakelists.txt", "cmake"),
171        ("justfile", "just"),
172        (".bashrc", "bash"),
173        (".bash_profile", "bash"),
174        (".bash_aliases", "bash"),
175        (".zshrc", "zsh"),
176        (".zshenv", "zsh"),
177        (".zprofile", "zsh"),
178        (".profile", "bash"),
179        (".gitconfig", "gitconfig"),
180        (".gitattributes", "gitattributes"),
181        (".gitignore", "gitignore"),
182        (".dockerignore", "gitignore"),
183        (".diffctxignore", "gitignore"),
184        (".npmrc", "ini"),
185        (".yarnrc", "yaml"),
186        (".prettierrc", "json"),
187        (".eslintrc", "json"),
188        ("package.json", "json"),
189        ("tsconfig.json", "json"),
190        ("composer.json", "json"),
191        ("cargo.toml", "toml"),
192        ("pyproject.toml", "toml"),
193        ("go.mod", "gomod"),
194        ("go.sum", "gosum"),
195        ("requirements.txt", "text"),
196        ("pipfile", "toml"),
197        ("procfile", "text"),
198        ("jenkinsfile", "groovy"),
199        ("build", "bazel"),
200        ("build.bazel", "bazel"),
201        ("workspace", "bazel"),
202        ("workspace.bazel", "bazel"),
203        ("flake.lock", "json"),
204    ];
205
206    let mut map = FxHashMap::with_capacity_and_hasher(entries.len(), Default::default());
207    for &(name, lang) in entries {
208        map.insert(name, lang);
209    }
210    map
211});
212
213pub fn get_language_for_file(path: &str) -> Option<&'static str> {
214    let p = Path::new(path);
215
216    if let Some(name) = p.file_name() {
217        let name_lower = name.to_string_lossy().to_lowercase();
218        if let Some(&lang) = FILENAME_TO_LANGUAGE.get(name_lower.as_str()) {
219            return Some(lang);
220        }
221    }
222
223    if let Some(ext) = p.extension() {
224        let ext_lower = format!(".{}", ext.to_string_lossy().to_lowercase());
225        if let Some(&lang) = EXTENSION_TO_LANGUAGE.get(ext_lower.as_str()) {
226            return Some(lang);
227        }
228    }
229
230    if let Some(name) = p.file_name() {
231        let name_lower = name.to_string_lossy().to_lowercase();
232        if name_lower.starts_with("dockerfile") {
233            return Some("dockerfile");
234        }
235    }
236
237    None
238}