use once_cell::sync::Lazy;
use rustc_hash::FxHashMap;
use std::path::Path;
pub static EXTENSION_TO_LANGUAGE: Lazy<FxHashMap<&'static str, &'static str>> = Lazy::new(|| {
let entries: &[(&str, &str)] = &[
(".py", "python"),
(".pyw", "python"),
(".pyi", "python"),
(".js", "javascript"),
(".mjs", "javascript"),
(".cjs", "javascript"),
(".jsx", "jsx"),
(".ts", "typescript"),
(".tsx", "tsx"),
(".mts", "typescript"),
(".cts", "typescript"),
(".json", "json"),
(".yaml", "yaml"),
(".yml", "yaml"),
(".toml", "toml"),
(".md", "markdown"),
(".markdown", "markdown"),
(".html", "html"),
(".htm", "html"),
(".css", "css"),
(".scss", "scss"),
(".less", "less"),
(".xml", "xml"),
(".svg", "xml"),
(".sh", "bash"),
(".bash", "bash"),
(".zsh", "zsh"),
(".fish", "fish"),
(".ksh", "bash"),
(".ps1", "powershell"),
(".psm1", "powershell"),
(".psd1", "powershell"),
(".bat", "batch"),
(".cmd", "batch"),
(".c", "c"),
(".h", "c"),
(".cpp", "cpp"),
(".cc", "cpp"),
(".cxx", "cpp"),
(".hpp", "cpp"),
(".hh", "cpp"),
(".hxx", "cpp"),
(".cs", "csharp"),
(".fs", "fsharp"),
(".fsi", "fsharp"),
(".fsx", "fsharp"),
(".java", "java"),
(".kt", "kotlin"),
(".kts", "kotlin"),
(".scala", "scala"),
(".sc", "scala"),
(".go", "go"),
(".rs", "rust"),
(".rb", "ruby"),
(".rake", "ruby"),
(".gemspec", "ruby"),
(".php", "php"),
(".swift", "swift"),
(".m", "objectivec"),
(".mm", "objectivec"),
(".r", "r"),
(".lua", "lua"),
(".pl", "perl"),
(".pm", "perl"),
(".ex", "elixir"),
(".exs", "elixir"),
(".erl", "erlang"),
(".hrl", "erlang"),
(".hs", "haskell"),
(".lhs", "haskell"),
(".ml", "ocaml"),
(".mli", "ocaml"),
(".clj", "clojure"),
(".cljs", "clojure"),
(".cljc", "clojure"),
(".sql", "sql"),
(".graphql", "graphql"),
(".gql", "graphql"),
(".proto", "protobuf"),
(".dockerfile", "dockerfile"),
(".tf", "terraform"),
(".hcl", "hcl"),
(".vim", "vim"),
(".el", "elisp"),
(".lisp", "lisp"),
(".scm", "scheme"),
(".rkt", "racket"),
(".zig", "zig"),
(".nim", "nim"),
(".v", "v"),
(".sv", "systemverilog"),
(".vhd", "vhdl"),
(".vhdl", "vhdl"),
(".d", "d"),
(".dart", "dart"),
(".groovy", "groovy"),
(".gradle", "groovy"),
(".jl", "julia"),
(".ini", "ini"),
(".cfg", "ini"),
(".conf", "ini"),
(".properties", "properties"),
(".env", "dotenv"),
(".ada", "ada"),
(".pas", "pascal"),
(".f90", "fortran"),
(".f95", "fortran"),
(".cob", "cobol"),
(".asm", "asm"),
(".s", "asm"),
(".c++", "cpp"),
(".h++", "cpp"),
(".ipp", "cpp"),
(".tpp", "cpp"),
(".phtml", "php"),
(".php3", "php"),
(".php4", "php"),
(".php5", "php"),
(".php7", "php"),
(".phps", "php"),
(".adoc", "asciidoc"),
(".editorconfig", "editorconfig"),
(".tex", "latex"),
(".latex", "latex"),
(".rst", "rst"),
(".txt", "text"),
(".log", "text"),
(".diff", "diff"),
(".patch", "diff"),
(".vue", "vue"),
(".svelte", "svelte"),
(".sty", "latex"),
(".cls", "latex"),
(".bst", "latex"),
(".dtx", "latex"),
(".bib", "bibtex"),
(".nix", "nix"),
(".prisma", "prisma"),
(".bzl", "bazel"),
(".j2", "jinja"),
(".jinja", "jinja"),
(".jinja2", "jinja"),
];
let mut map = FxHashMap::with_capacity_and_hasher(entries.len(), Default::default());
for &(ext, lang) in entries {
map.insert(ext, lang);
}
map
});
pub static FILENAME_TO_LANGUAGE: Lazy<FxHashMap<&'static str, &'static str>> = Lazy::new(|| {
let entries: &[(&str, &str)] = &[
("makefile", "makefile"),
("gnumakefile", "makefile"),
("dockerfile", "dockerfile"),
("containerfile", "dockerfile"),
("vagrantfile", "ruby"),
("gemfile", "ruby"),
("rakefile", "ruby"),
("guardfile", "ruby"),
("brewfile", "ruby"),
("podfile", "ruby"),
("cmakelists.txt", "cmake"),
("justfile", "just"),
(".bashrc", "bash"),
(".bash_profile", "bash"),
(".bash_aliases", "bash"),
(".zshrc", "zsh"),
(".zshenv", "zsh"),
(".zprofile", "zsh"),
(".profile", "bash"),
(".gitconfig", "gitconfig"),
(".gitattributes", "gitattributes"),
(".gitignore", "gitignore"),
(".dockerignore", "gitignore"),
(".diffctxignore", "gitignore"),
(".npmrc", "ini"),
(".yarnrc", "yaml"),
(".prettierrc", "json"),
(".eslintrc", "json"),
("package.json", "json"),
("tsconfig.json", "json"),
("composer.json", "json"),
("cargo.toml", "toml"),
("pyproject.toml", "toml"),
("go.mod", "gomod"),
("go.sum", "gosum"),
("requirements.txt", "text"),
("pipfile", "toml"),
("procfile", "text"),
("jenkinsfile", "groovy"),
("build", "bazel"),
("build.bazel", "bazel"),
("workspace", "bazel"),
("workspace.bazel", "bazel"),
("flake.lock", "json"),
];
let mut map = FxHashMap::with_capacity_and_hasher(entries.len(), Default::default());
for &(name, lang) in entries {
map.insert(name, lang);
}
map
});
pub fn get_language_for_file(path: &str) -> Option<&'static str> {
let p = Path::new(path);
if let Some(name) = p.file_name() {
let name_lower = name.to_string_lossy().to_lowercase();
if let Some(&lang) = FILENAME_TO_LANGUAGE.get(name_lower.as_str()) {
return Some(lang);
}
}
if let Some(ext) = p.extension() {
let ext_lower = format!(".{}", ext.to_string_lossy().to_lowercase());
if let Some(&lang) = EXTENSION_TO_LANGUAGE.get(ext_lower.as_str()) {
return Some(lang);
}
}
if let Some(name) = p.file_name() {
let name_lower = name.to_string_lossy().to_lowercase();
if name_lower.starts_with("dockerfile") {
return Some("dockerfile");
}
}
None
}