use std::path::Path;
use crate::cli::FormatMappings;
pub const SUPPORTED_FORMATS: &[&str] = &[
"abap",
"actionscript",
"ada",
"apacheconf",
"apl",
"applescript",
"arduino",
"arff",
"asciidoc",
"asm6502",
"aspnet",
"autohotkey",
"autoit",
"bash",
"basic",
"batch",
"bison",
"brainfuck",
"bro",
"c",
"c-header",
"clike",
"clojure",
"coffeescript",
"comments",
"cpp",
"cpp-header",
"crystal",
"csharp",
"csp",
"css-extras",
"css",
"d",
"dart",
"diff",
"django",
"docker",
"eiffel",
"elixir",
"elm",
"erb",
"erlang",
"flow",
"fortran",
"fsharp",
"gdscript",
"gedcom",
"gherkin",
"git",
"glsl",
"go",
"graphql",
"groovy",
"haml",
"handlebars",
"haskell",
"haxe",
"hpkp",
"hsts",
"http",
"ichigojam",
"icon",
"inform7",
"ini",
"io",
"j",
"java",
"javascript",
"jolie",
"json",
"jsx",
"julia",
"keymap",
"kotlin",
"latex",
"less",
"liquid",
"lisp",
"livescript",
"lolcode",
"lua",
"makefile",
"markdown",
"markup",
"matlab",
"mel",
"mizar",
"monkey",
"n4js",
"nasm",
"nginx",
"nim",
"nix",
"nsis",
"objectivec",
"ocaml",
"opencl",
"oz",
"parigp",
"pascal",
"perl",
"php",
"plsql",
"powershell",
"processing",
"prolog",
"properties",
"protobuf",
"pug",
"puppet",
"pure",
"python",
"q",
"qore",
"r",
"reason",
"renpy",
"rest",
"rip",
"roboconf",
"ruby",
"rust",
"sas",
"sass",
"scala",
"scheme",
"scss",
"svelte",
"smalltalk",
"smarty",
"soy",
"sql",
"stylus",
"swift",
"tap",
"tcl",
"textile",
"tsx",
"tt2",
"twig",
"typescript",
"txt",
"vbnet",
"velocity",
"verilog",
"vhdl",
"vim",
"visual-basic",
"astro",
"vue",
"wasm",
"wiki",
"xeora",
"xojo",
"xquery",
"yaml",
"abnf",
"agda",
"antlr4",
"apex",
"aql",
"armasm",
"awk",
"bicep",
"bnf",
"cfscript",
"cfml",
"cmake",
"cobol",
"csv",
"cypher",
"dhall",
"dns-zone-file",
"dot",
"ebnf",
"editorconfig",
"excel-formula",
"factor",
"ftl",
"gcode",
"gettext",
"gml",
"go-module",
"hcl",
"hlsl",
"idris",
"ignore",
"jq",
"json5",
"kusto",
"lilypond",
"linker-script",
"llvm",
"log",
"mermaid",
"mongodb",
"n1ql",
"odin",
"openqasm",
"plant-uml",
"powerquery",
"promql",
"purescript",
"qsharp",
"racket",
"regex",
"rego",
"rescript",
"robotframework",
"shell-session",
"smali",
"solidity",
"sparql",
"stata",
"toml",
"turtle",
"typoscript",
"unrealscript",
"uri",
"vala",
"wgsl",
"wolfram",
"zig",
];
#[cfg(test)]
const EXTENSION_FORMATS_COUNT: usize = 206;
pub fn format_for_path<'a>(
path: &Path,
formats_exts: &'a FormatMappings,
formats_names: &'a FormatMappings,
) -> Option<&'a str> {
let file_name = path.file_name()?.to_string_lossy();
if !formats_names.is_empty()
&& let Some(format) = formats_names.find_format_for_value(&file_name)
{
return Some(format);
}
let ext = path.extension()?.to_string_lossy();
if !formats_exts.is_empty() {
return formats_exts.find_format_for_value(&ext);
}
builtin_format_for_extension(&ext)
}
fn builtin_format_for_extension(extension: &str) -> Option<&'static str> {
match extension {
"as" => Some("actionscript"),
"ada" => Some("ada"),
"apl" => Some("apl"),
"asp" => Some("aspnet"),
"aspx" => Some("aspnet"),
"sh" => Some("bash"),
"ksh" => Some("bash"),
"bash" => Some("bash"),
"bas" => Some("basic"),
"b" => Some("brainfuck"),
"bf" => Some("brainfuck"),
"c" => Some("c"),
"z80" => Some("c"),
"h" => Some("c-header"),
"cljs" => Some("clojure"),
"clj" => Some("clojure"),
"cljc" => Some("clojure"),
"cljx" => Some("clojure"),
"edn" => Some("clojure"),
"coffee" => Some("coffeescript"),
"cpp" => Some("cpp"),
"c++" => Some("cpp"),
"cc" => Some("cpp"),
"cxx" => Some("cpp"),
"hpp" => Some("cpp-header"),
"h++" => Some("cpp-header"),
"hh" => Some("cpp-header"),
"hxx" => Some("cpp-header"),
"cr" => Some("crystal"),
"cs" => Some("csharp"),
"css" => Some("css"),
"gss" => Some("css"),
"d" => Some("d"),
"dart" => Some("dart"),
"diff" => Some("diff"),
"patch" => Some("diff"),
"e" => Some("eiffel"),
"elm" => Some("elm"),
"erl" => Some("erlang"),
"erlang" => Some("erlang"),
"f" => Some("fortran"),
"for" => Some("fortran"),
"f77" => Some("fortran"),
"f90" => Some("fortran"),
"fs" => Some("fsharp"),
"gd" => Some("gdscript"),
"feature" => Some("gherkin"),
"go" => Some("go"),
"graphql" => Some("graphql"),
"groovy" => Some("groovy"),
"gradle" => Some("groovy"),
"haml" => Some("haml"),
"hb" => Some("handlebars"),
"hbs" => Some("handlebars"),
"handlebars" => Some("handlebars"),
"hs" => Some("haskell"),
"lhs" => Some("haskell"),
"hx" => Some("haxe"),
"hxml" => Some("haxe"),
"ini" => Some("ini"),
"java" => Some("java"),
"js" => Some("javascript"),
"es" => Some("javascript"),
"es6" => Some("javascript"),
"mjs" => Some("javascript"),
"cjs" => Some("javascript"),
"json" => Some("json"),
"map" => Some("json"),
"jsonld" => Some("json"),
"jsx" => Some("jsx"),
"jl" => Some("julia"),
"kt" => Some("kotlin"),
"kts" => Some("kotlin"),
"tex" => Some("latex"),
"less" => Some("less"),
"cl" => Some("lisp"),
"lisp" => Some("lisp"),
"el" => Some("lisp"),
"ls" => Some("livescript"),
"lua" => Some("lua"),
"md" => Some("markdown"),
"markdown" => Some("markdown"),
"mkd" => Some("markdown"),
"html" => Some("markup"),
"htm" => Some("markup"),
"xml" => Some("markup"),
"xsl" => Some("markup"),
"xslt" => Some("markup"),
"svg" => Some("markup"),
"ejs" => Some("markup"),
"jsp" => Some("markup"),
"nsh" => Some("nsis"),
"nsi" => Some("nsis"),
"m" => Some("objectivec"),
"mm" => Some("objectivec"),
"ocaml" => Some("ocaml"),
"ml" => Some("ocaml"),
"mli" => Some("ocaml"),
"mll" => Some("ocaml"),
"mly" => Some("ocaml"),
"oz" => Some("oz"),
"pas" => Some("pascal"),
"p" => Some("pascal"),
"pl" => Some("perl"),
"pm" => Some("perl"),
"php" => Some("php"),
"phtml" => Some("php"),
"plsql" => Some("plsql"),
"ps1" => Some("powershell"),
"psd1" => Some("powershell"),
"psm1" => Some("powershell"),
"pro" => Some("prolog"),
"properties" => Some("properties"),
"proto" => Some("protobuf"),
"pug" => Some("pug"),
"jade" => Some("pug"),
"pp" => Some("puppet"),
"puppet" => Some("puppet"),
"py" => Some("python"),
"pyx" => Some("python"),
"pxd" => Some("python"),
"pxi" => Some("python"),
"q" => Some("q"),
"r" => Some("r"),
"R" => Some("r"),
"rb" => Some("ruby"),
"rs" => Some("rust"),
"sas" => Some("sas"),
"sass" => Some("sass"),
"scala" => Some("scala"),
"scm" => Some("scheme"),
"ss" => Some("scheme"),
"scss" => Some("scss"),
"svelte" => Some("svelte"),
"st" => Some("smalltalk"),
"smarty" => Some("smarty"),
"tpl" => Some("smarty"),
"soy" => Some("soy"),
"sql" => Some("sql"),
"cql" => Some("sql"),
"styl" => Some("stylus"),
"stylus" => Some("stylus"),
"swift" => Some("swift"),
"tap" => Some("tap"),
"tcl" => Some("tcl"),
"textile" => Some("textile"),
"tsx" => Some("tsx"),
"tt2" => Some("tt2"),
"twig" => Some("twig"),
"ts" => Some("typescript"),
"mts" => Some("typescript"),
"cts" => Some("typescript"),
"txt" => Some("txt"),
"vb" => Some("vbnet"),
"vtl" => Some("velocity"),
"v" => Some("verilog"),
"vhd" => Some("vhdl"),
"vhdl" => Some("vhdl"),
"astro" => Some("astro"),
"vue" => Some("vue"),
"xy" => Some("xquery"),
"xquery" => Some("xquery"),
"yaml" => Some("yaml"),
"yml" => Some("yaml"),
"g4" => Some("antlr4"),
"cls" => Some("apex"),
"trigger" => Some("apex"),
"apex" => Some("apex"),
"awk" => Some("awk"),
"bicep" => Some("bicep"),
"cfc" => Some("cfscript"),
"cfm" => Some("cfml"),
"cmake" => Some("cmake"),
"csv" => Some("csv"),
"dot" => Some("dot"),
"gv" => Some("dot"),
"xlsx" => Some("excel-formula"),
"xls" => Some("excel-formula"),
"po" => Some("gettext"),
"tf" => Some("hcl"),
"hcl" => Some("hcl"),
"idr" => Some("idris"),
"gitignore" => Some("ignore"),
"json5" => Some("json5"),
"ly" => Some("lilypond"),
"ld" => Some("linker-script"),
"ll" => Some("llvm"),
"log" => Some("log"),
"qasm" => Some("openqasm"),
"puml" => Some("plant-uml"),
"plantuml" => Some("plant-uml"),
"pq" => Some("powerquery"),
"purs" => Some("purescript"),
"qs" => Some("qsharp"),
"rkt" => Some("racket"),
"res" => Some("rescript"),
"robot" => Some("robotframework"),
"sol" => Some("solidity"),
"rq" => Some("sparql"),
"toml" => Some("toml"),
"ttl" => Some("turtle"),
"uc" => Some("unrealscript"),
"wgsl" => Some("wgsl"),
"wl" => Some("wolfram"),
"nb" => Some("wolfram"),
"zig" => Some("zig"),
_ => None,
}
}
pub fn supported_formats() -> Vec<&'static str> {
SUPPORTED_FORMATS.to_vec()
}
#[cfg(test)]
mod tests {
use std::path::Path;
use crate::cli::FormatMappings;
#[test]
fn maps_module_typescript_extensions_like_upstream() {
let formats_exts = FormatMappings::default();
let formats_names = FormatMappings::default();
assert_eq!(
super::format_for_path(Path::new("index.mts"), &formats_exts, &formats_names),
Some("typescript")
);
assert_eq!(
super::format_for_path(Path::new("index.cts"), &formats_exts, &formats_names),
Some("typescript")
);
}
#[test]
fn maps_javascript_module_extensions_like_upstream() {
let formats_exts = FormatMappings::default();
let formats_names = FormatMappings::default();
assert_eq!(
super::format_for_path(Path::new("index.es"), &formats_exts, &formats_names),
Some("javascript")
);
assert_eq!(
super::format_for_path(Path::new("index.es6"), &formats_exts, &formats_names),
Some("javascript")
);
}
#[test]
fn syncs_supported_format_surface_from_upstream() {
assert_eq!(super::SUPPORTED_FORMATS.len(), 223);
assert_eq!(super::EXTENSION_FORMATS_COUNT, 206);
assert_eq!(super::supported_formats().first(), Some(&"abap"));
assert!(super::supported_formats().contains(&"typescript"));
assert!(super::supported_formats().contains(&"excel-formula"));
}
#[test]
fn maps_long_tail_extensions_like_upstream() {
let formats_exts = FormatMappings::default();
let formats_names = FormatMappings::default();
assert_eq!(
super::format_for_path(Path::new("schema.g4"), &formats_exts, &formats_names),
Some("antlr4")
);
assert_eq!(
super::format_for_path(Path::new("component.bicep"), &formats_exts, &formats_names),
Some("bicep")
);
assert_eq!(
super::format_for_path(Path::new("formula.xlsx"), &formats_exts, &formats_names),
Some("excel-formula")
);
}
#[test]
fn maps_header_extensions_like_upstream() {
let formats_exts = FormatMappings::default();
let formats_names = FormatMappings::default();
assert_eq!(
super::format_for_path(Path::new("foo.h"), &formats_exts, &formats_names),
Some("c-header")
);
assert_eq!(
super::format_for_path(Path::new("foo.hpp"), &formats_exts, &formats_names),
Some("cpp-header")
);
}
#[test]
fn extensionless_names_require_formats_names_like_upstream() {
let formats_exts = FormatMappings::default();
let formats_names = FormatMappings::default();
assert_eq!(
super::format_for_path(Path::new("Makefile"), &formats_exts, &formats_names),
None
);
let formats_names = FormatMappings::from_pairs(vec![(
"makefile".to_string(),
vec!["Makefile".to_string(), "GNUmakefile".to_string()],
)]);
assert_eq!(
super::format_for_path(Path::new("Makefile"), &formats_exts, &formats_names),
Some("makefile")
);
}
}