pub fn get_language_file_name(base_name: &str, language_id: &str) -> Option<String> {
let language = language_id.to_ascii_lowercase();
let ext = match known_language_extension(&language) {
Some(ext) => ext,
None if is_fallback_extension(&language) => &language,
None => return None,
};
Some(format!("{}.{}", base_name, ext))
}
fn known_language_extension(language: &str) -> Option<&'static str> {
Some(match language {
"bash" | "sh" | "shell" | "shellscript" => "sh",
"c#" | "csharp" => "cs",
"c++" | "cpp" => "cpp",
"clojure" => "clj",
"coffeescript" => "coffee",
"elixir" => "ex",
"erlang" => "erl",
"f#" | "fsharp" => "fs",
"handlebars" => "hbs",
"haskell" => "hs",
"javascript" => "js",
"javascriptreact" => "jsx",
"julia" => "jl",
"kotlin" => "kt",
"latex" => "tex",
"markdown" => "md",
"nushell" => "nu",
"ocaml" => "ml",
"perl" => "pl",
"powershell" => "ps1",
"proto3" | "protobuf" => "proto",
"python" | "python3" => "py",
"restructuredtext" => "rst",
"ruby" => "rb",
"rust" => "rs",
"terraform" => "tf",
"typescript" => "ts",
"typescriptreact" => "tsx",
"yaml" => "yml",
_ => return None,
})
}
fn is_fallback_extension(language: &str) -> bool {
!language.is_empty()
&& language.chars().all(|c| c.is_ascii_alphanumeric())
&& language != "ipynb"
}