mod highlight;
pub use highlight::highlighted_spans;
pub struct Language {
name: &'static str,
pub(crate) grammar: tree_sitter::Language,
pub(crate) highlight_query: tree_sitter::Query,
}
impl Language {
pub fn new(
name: &'static str,
grammar: tree_sitter::Language,
highlight_query_source: &str,
) -> Self {
let highlight_query = tree_sitter::Query::new(&grammar, highlight_query_source)
.unwrap_or_else(|error| {
panic!("bundled highlight query for {name} failed to parse: {error}")
});
Self {
name,
grammar,
highlight_query,
}
}
pub fn name(&self) -> &'static str {
self.name
}
}
pub trait LanguageRegistry {
fn language_for_extension(&self, extension: &str) -> Option<&Language>;
}
pub struct DefaultLanguageRegistry {
#[cfg(feature = "lang-rust")]
rust: Language,
#[cfg(feature = "lang-javascript")]
javascript: Language,
#[cfg(feature = "lang-typescript")]
typescript: Language,
#[cfg(feature = "lang-typescript")]
tsx: Language,
#[cfg(feature = "lang-markdown")]
markdown: Language,
#[cfg(feature = "lang-json")]
json: Language,
}
impl DefaultLanguageRegistry {
pub fn new() -> Self {
Self {
#[cfg(feature = "lang-rust")]
rust: Language::new(
"Rust",
tree_sitter_rust::LANGUAGE.into(),
tree_sitter_rust::HIGHLIGHTS_QUERY,
),
#[cfg(feature = "lang-javascript")]
javascript: Language::new(
"JavaScript",
tree_sitter_javascript::LANGUAGE.into(),
tree_sitter_javascript::HIGHLIGHT_QUERY,
),
#[cfg(feature = "lang-typescript")]
typescript: Language::new(
"TypeScript",
tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into(),
tree_sitter_typescript::HIGHLIGHTS_QUERY,
),
#[cfg(feature = "lang-typescript")]
tsx: Language::new(
"TSX",
tree_sitter_typescript::LANGUAGE_TSX.into(),
tree_sitter_typescript::HIGHLIGHTS_QUERY,
),
#[cfg(feature = "lang-markdown")]
markdown: Language::new(
"Markdown",
tree_sitter_md::LANGUAGE.into(),
tree_sitter_md::HIGHLIGHT_QUERY_BLOCK,
),
#[cfg(feature = "lang-json")]
json: Language::new(
"JSON",
tree_sitter_json::LANGUAGE.into(),
tree_sitter_json::HIGHLIGHTS_QUERY,
),
}
}
}
impl Default for DefaultLanguageRegistry {
fn default() -> Self {
Self::new()
}
}
impl LanguageRegistry for DefaultLanguageRegistry {
fn language_for_extension(&self, extension: &str) -> Option<&Language> {
match extension {
#[cfg(feature = "lang-rust")]
"rs" => Some(&self.rust),
#[cfg(feature = "lang-javascript")]
"js" | "mjs" | "cjs" | "jsx" => Some(&self.javascript),
#[cfg(feature = "lang-typescript")]
"ts" | "mts" | "cts" => Some(&self.typescript),
#[cfg(feature = "lang-typescript")]
"tsx" => Some(&self.tsx),
#[cfg(feature = "lang-markdown")]
"md" | "markdown" => Some(&self.markdown),
#[cfg(feature = "lang-json")]
"json" => Some(&self.json),
_ => None,
}
}
}