use std::borrow::Cow;
use std::collections::HashMap;
use std::sync::{Arc, RwLock};
#[allow(unused_imports)]
use arborium_highlight::tree_sitter::{CompiledGrammar, GrammarConfig};
pub struct GrammarStore {
grammars: RwLock<HashMap<String, Arc<CompiledGrammar>>>,
}
impl Default for GrammarStore {
fn default() -> Self {
Self::new()
}
}
impl GrammarStore {
pub fn new() -> Self {
Self {
grammars: RwLock::new(HashMap::new()),
}
}
pub fn insert(
&self,
language: impl Into<String>,
grammar: Arc<CompiledGrammar>,
) -> Option<Arc<CompiledGrammar>> {
let language = language.into();
let normalized = Self::normalize_language(&language).into_owned();
self.grammars.write().unwrap().insert(normalized, grammar)
}
pub fn get(&self, language: &str) -> Option<Arc<CompiledGrammar>> {
let normalized = Self::normalize_language(language);
{
let grammars = self.grammars.read().unwrap();
if let Some(grammar) = grammars.get(&*normalized) {
return Some(grammar.clone());
}
}
let grammar = Self::compile_grammar(&normalized)?;
let grammar = Arc::new(grammar);
{
let mut grammars = self.grammars.write().unwrap();
if let Some(existing) = grammars.get(&*normalized) {
return Some(existing.clone());
}
grammars.insert(normalized.into_owned(), grammar.clone());
}
Some(grammar)
}
fn normalize_language(language: &str) -> Cow<'_, str> {
match language {
"adoc" => Cow::Borrowed("asciidoc"),
"assembly" => Cow::Borrowed("asm"),
"bat" => Cow::Borrowed("batch"),
"bazel" => Cow::Borrowed("starlark"),
"bzl" => Cow::Borrowed("starlark"),
"c++" => Cow::Borrowed("cpp"),
"cbl" => Cow::Borrowed("cobol"),
"cfg" => Cow::Borrowed("ini"),
"cjs" => Cow::Borrowed("javascript"),
"cl" => Cow::Borrowed("commonlisp"),
"clj" => Cow::Borrowed("clojure"),
"cmd" => Cow::Borrowed("batch"),
"cob" => Cow::Borrowed("cobol"),
"conf" => Cow::Borrowed("ini"),
"cpy" => Cow::Borrowed("cobol"),
"cs" => Cow::Borrowed("c-sharp"),
"csharp" => Cow::Borrowed("c-sharp"),
"cts" => Cow::Borrowed("typescript"),
"cxx" => Cow::Borrowed("cpp"),
"dlang" => Cow::Borrowed("d"),
"docker" => Cow::Borrowed("dockerfile"),
"el" => Cow::Borrowed("elisp"),
"emacs-lisp" => Cow::Borrowed("elisp"),
"erl" => Cow::Borrowed("erlang"),
"ex" => Cow::Borrowed("elixir"),
"exs" => Cow::Borrowed("elixir"),
"f#" => Cow::Borrowed("fsharp"),
"frag" => Cow::Borrowed("glsl"),
"fs" => Cow::Borrowed("fsharp"),
"golang" => Cow::Borrowed("go"),
"gql" => Cow::Borrowed("graphql"),
"gsh" => Cow::Borrowed("groovy"),
"gvy" => Cow::Borrowed("groovy"),
"gy" => Cow::Borrowed("groovy"),
"h" => Cow::Borrowed("c"),
"hpp" => Cow::Borrowed("cpp"),
"hs" => Cow::Borrowed("haskell"),
"htm" => Cow::Borrowed("html"),
"idr" => Cow::Borrowed("idris"),
"j2" => Cow::Borrowed("jinja2"),
"jinja" => Cow::Borrowed("jinja2"),
"jl" => Cow::Borrowed("julia"),
"js" => Cow::Borrowed("javascript"),
"jsonc" => Cow::Borrowed("json"),
"jsx" => Cow::Borrowed("javascript"),
"kt" => Cow::Borrowed("kotlin"),
"kts" => Cow::Borrowed("kotlin"),
"lisp" => Cow::Borrowed("commonlisp"),
"m" => Cow::Borrowed("matlab"),
"md" => Cow::Borrowed("markdown"),
"mdx" => Cow::Borrowed("markdown"),
"mjs" => Cow::Borrowed("javascript"),
"ml" => Cow::Borrowed("ocaml"),
"mm" => Cow::Borrowed("objc"),
"mts" => Cow::Borrowed("typescript"),
"mysql" => Cow::Borrowed("sql"),
"nasm" => Cow::Borrowed("x86asm"),
"objective-c" => Cow::Borrowed("objc"),
"opa" => Cow::Borrowed("rego"),
"patch" => Cow::Borrowed("diff"),
"pbtxt" => Cow::Borrowed("textproto"),
"pl" => Cow::Borrowed("perl"),
"pm" => Cow::Borrowed("perl"),
"postgres" => Cow::Borrowed("sql"),
"postgresql" => Cow::Borrowed("sql"),
"pro" => Cow::Borrowed("prolog"),
"ps" => Cow::Borrowed("postscript"),
"ps1" => Cow::Borrowed("powershell"),
"pwsh" => Cow::Borrowed("powershell"),
"py" => Cow::Borrowed("python"),
"py3" => Cow::Borrowed("python"),
"python3" => Cow::Borrowed("python"),
"rb" => Cow::Borrowed("ruby"),
"res" => Cow::Borrowed("rescript"),
"rkt" => Cow::Borrowed("scheme"),
"rlang" => Cow::Borrowed("r"),
"rq" => Cow::Borrowed("sparql"),
"rs" => Cow::Borrowed("rust"),
"sass" => Cow::Borrowed("scss"),
"scm" => Cow::Borrowed("query"),
"sh" => Cow::Borrowed("bash"),
"shell" => Cow::Borrowed("bash"),
"sol" => Cow::Borrowed("solidity"),
"sqlite" => Cow::Borrowed("sql"),
"ss" => Cow::Borrowed("scheme"),
"sv" => Cow::Borrowed("verilog"),
"svg" => Cow::Borrowed("xml"),
"systemverilog" => Cow::Borrowed("verilog"),
"terraform" => Cow::Borrowed("hcl"),
"textpb" => Cow::Borrowed("textproto"),
"tf" => Cow::Borrowed("hcl"),
"tla" => Cow::Borrowed("tlaplus"),
"ts" => Cow::Borrowed("typescript"),
"typ" => Cow::Borrowed("typst"),
"ua" => Cow::Borrowed("uiua"),
"v" => Cow::Borrowed("verilog"),
"vbnet" => Cow::Borrowed("vb"),
"vert" => Cow::Borrowed("glsl"),
"vhd" => Cow::Borrowed("vhdl"),
"viml" => Cow::Borrowed("vim"),
"vimscript" => Cow::Borrowed("vim"),
"visualbasic" => Cow::Borrowed("vb"),
"wasm-interface" => Cow::Borrowed("wit"),
"x86" => Cow::Borrowed("x86asm"),
"xsl" => Cow::Borrowed("xml"),
"xslt" => Cow::Borrowed("xml"),
"yml" => Cow::Borrowed("yaml"),
_ => Cow::Borrowed(language),
}
}
#[allow(unused_variables)]
fn compile_grammar(language: &str) -> Option<CompiledGrammar> {
macro_rules! try_lang {
($feature:literal, $module:ident, $primary:literal) => {
#[cfg(feature = $feature)]
if language == $primary {
let config = GrammarConfig {
language: crate::$module::language().into(),
highlights_query: &crate::$module::HIGHLIGHTS_QUERY,
injections_query: crate::$module::INJECTIONS_QUERY,
locals_query: crate::$module::LOCALS_QUERY,
};
return CompiledGrammar::new(config).ok();
}
};
}
try_lang!("lang-ada", lang_ada, "ada");
try_lang!("lang-agda", lang_agda, "agda");
try_lang!("lang-asciidoc", lang_asciidoc, "asciidoc");
try_lang!("lang-asm", lang_asm, "asm");
try_lang!("lang-awk", lang_awk, "awk");
try_lang!("lang-bash", lang_bash, "bash");
try_lang!("lang-batch", lang_batch, "batch");
try_lang!("lang-c", lang_c, "c");
try_lang!("lang-c-sharp", lang_c_sharp, "c-sharp");
try_lang!("lang-caddy", lang_caddy, "caddy");
try_lang!("lang-capnp", lang_capnp, "capnp");
try_lang!("lang-cedar", lang_cedar, "cedar");
try_lang!("lang-cedarschema", lang_cedarschema, "cedarschema");
try_lang!("lang-clojure", lang_clojure, "clojure");
try_lang!("lang-cmake", lang_cmake, "cmake");
try_lang!("lang-cobol", lang_cobol, "cobol");
try_lang!("lang-commonlisp", lang_commonlisp, "commonlisp");
try_lang!("lang-cpp", lang_cpp, "cpp");
try_lang!("lang-css", lang_css, "css");
try_lang!("lang-d", lang_d, "d");
try_lang!("lang-dart", lang_dart, "dart");
try_lang!("lang-devicetree", lang_devicetree, "devicetree");
try_lang!("lang-diff", lang_diff, "diff");
try_lang!("lang-dockerfile", lang_dockerfile, "dockerfile");
try_lang!("lang-dot", lang_dot, "dot");
try_lang!("lang-elisp", lang_elisp, "elisp");
try_lang!("lang-elixir", lang_elixir, "elixir");
try_lang!("lang-elm", lang_elm, "elm");
try_lang!("lang-erlang", lang_erlang, "erlang");
try_lang!("lang-fish", lang_fish, "fish");
try_lang!("lang-fsharp", lang_fsharp, "fsharp");
try_lang!("lang-gleam", lang_gleam, "gleam");
try_lang!("lang-glsl", lang_glsl, "glsl");
try_lang!("lang-go", lang_go, "go");
try_lang!("lang-graphql", lang_graphql, "graphql");
try_lang!("lang-groovy", lang_groovy, "groovy");
try_lang!("lang-haskell", lang_haskell, "haskell");
try_lang!("lang-hcl", lang_hcl, "hcl");
try_lang!("lang-hlsl", lang_hlsl, "hlsl");
try_lang!("lang-html", lang_html, "html");
try_lang!("lang-idris", lang_idris, "idris");
try_lang!("lang-ini", lang_ini, "ini");
try_lang!("lang-java", lang_java, "java");
try_lang!("lang-javascript", lang_javascript, "javascript");
try_lang!("lang-jinja2", lang_jinja2, "jinja2");
try_lang!("lang-jq", lang_jq, "jq");
try_lang!("lang-json", lang_json, "json");
try_lang!("lang-julia", lang_julia, "julia");
try_lang!("lang-kotlin", lang_kotlin, "kotlin");
try_lang!("lang-lean", lang_lean, "lean");
try_lang!("lang-lua", lang_lua, "lua");
try_lang!("lang-markdown", lang_markdown, "markdown");
try_lang!("lang-matlab", lang_matlab, "matlab");
try_lang!("lang-meson", lang_meson, "meson");
try_lang!("lang-nginx", lang_nginx, "nginx");
try_lang!("lang-ninja", lang_ninja, "ninja");
try_lang!("lang-nix", lang_nix, "nix");
try_lang!("lang-objc", lang_objc, "objc");
try_lang!("lang-ocaml", lang_ocaml, "ocaml");
try_lang!("lang-perl", lang_perl, "perl");
try_lang!("lang-php", lang_php, "php");
try_lang!("lang-postscript", lang_postscript, "postscript");
try_lang!("lang-powershell", lang_powershell, "powershell");
try_lang!("lang-prolog", lang_prolog, "prolog");
try_lang!("lang-python", lang_python, "python");
try_lang!("lang-query", lang_query, "query");
try_lang!("lang-r", lang_r, "r");
try_lang!("lang-rego", lang_rego, "rego");
try_lang!("lang-rescript", lang_rescript, "rescript");
try_lang!("lang-ron", lang_ron, "ron");
try_lang!("lang-ruby", lang_ruby, "ruby");
try_lang!("lang-rust", lang_rust, "rust");
try_lang!("lang-scala", lang_scala, "scala");
try_lang!("lang-scheme", lang_scheme, "scheme");
try_lang!("lang-scss", lang_scss, "scss");
try_lang!("lang-solidity", lang_solidity, "solidity");
try_lang!("lang-sparql", lang_sparql, "sparql");
try_lang!("lang-sql", lang_sql, "sql");
try_lang!("lang-ssh-config", lang_ssh_config, "ssh-config");
try_lang!("lang-starlark", lang_starlark, "starlark");
try_lang!("lang-styx", lang_styx, "styx");
try_lang!("lang-svelte", lang_svelte, "svelte");
try_lang!("lang-swift", lang_swift, "swift");
try_lang!("lang-textproto", lang_textproto, "textproto");
try_lang!("lang-thrift", lang_thrift, "thrift");
try_lang!("lang-tlaplus", lang_tlaplus, "tlaplus");
try_lang!("lang-toml", lang_toml, "toml");
try_lang!("lang-tsx", lang_tsx, "tsx");
try_lang!("lang-typescript", lang_typescript, "typescript");
try_lang!("lang-typst", lang_typst, "typst");
try_lang!("lang-uiua", lang_uiua, "uiua");
try_lang!("lang-vb", lang_vb, "vb");
try_lang!("lang-verilog", lang_verilog, "verilog");
try_lang!("lang-vhdl", lang_vhdl, "vhdl");
try_lang!("lang-vim", lang_vim, "vim");
try_lang!("lang-vue", lang_vue, "vue");
try_lang!("lang-wit", lang_wit, "wit");
try_lang!("lang-x86asm", lang_x86asm, "x86asm");
try_lang!("lang-xml", lang_xml, "xml");
try_lang!("lang-yaml", lang_yaml, "yaml");
try_lang!("lang-yuri", lang_yuri, "yuri");
try_lang!("lang-zig", lang_zig, "zig");
try_lang!("lang-zsh", lang_zsh, "zsh");
None
}
}