use std::{ops::Range, path::Path, sync::OnceLock};
use bezel::theme::HighlightKind;
use syntax::registry::Known;
mod provider;
pub use provider::{Status, available, start_install, status};
const MARKDOWN: &str = "markdown";
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Language {
Ready(&'static str),
Markdown,
Missing(&'static str),
}
fn installed() {
static ONCE: OnceLock<()> = OnceLock::new();
ONCE.get_or_init(provider::initialize);
}
pub fn of(path: &Path) -> Option<Language> {
installed();
let known = syntax::registry::of_path(path)?;
if known.name() == MARKDOWN {
return Some(Language::Markdown);
}
Some(match known {
Known::Ready(lang) => Language::Ready(lang.name),
Known::Named(name) => Language::Missing(name),
})
}
pub fn paintable() -> Vec<&'static str> {
installed();
syntax::registry::ready()
}
pub fn spans(path: &Path, text: &str) -> Option<Vec<(Range<usize>, HighlightKind)>> {
match of(path)? {
Language::Ready(language) => highlight(language, text),
Language::Markdown => Some(markdown::source::spans(text)),
Language::Missing(_) => None,
}
}
pub fn highlight(language: &str, source: &str) -> Option<Vec<(Range<usize>, HighlightKind)>> {
installed();
provider::ensure_runtime().ok()?;
syntax::highlight(source, language)
}