use std::path::Path;
use std::str::FromStr;
use crate::Error;
use crate::grammar::{Grammar, PLAIN_TEXT_NAME};
use crate::theme::Theme;
#[derive(Debug, Default)]
pub struct Registry {
pub grammars: Vec<Grammar>,
pub themes: Vec<Theme>,
}
#[derive(Clone, Copy, Debug, Default)]
pub struct GrammarQuery<'a> {
pub syntax: Option<&'a str>,
pub path: Option<&'a Path>,
pub first_line: Option<&'a str>,
}
impl Registry {
pub fn new() -> Self {
Self::default()
}
pub fn with_plain_text() -> Self {
let mut registry = Self::new();
registry.add_grammar(Grammar::plain_text());
registry
}
pub fn with_builtin_syntaxes() -> Self {
let mut registry = Self::with_plain_text();
registry.add_grammar(Grammar::json());
registry
}
pub fn add_grammar(&mut self, grammar: Grammar) {
self.grammars.push(grammar);
}
pub fn add_json(&mut self) {
self.add_grammar(Grammar::json());
}
pub fn add_grammar_json(&mut self, input: &str) -> Result<(), Error> {
let grammar = Grammar::from_str(input)?;
self.add_grammar(grammar);
Ok(())
}
pub fn add_theme(&mut self, theme: Theme) {
self.themes.push(theme);
}
pub fn add_theme_json(&mut self, input: &str) -> Result<(), Error> {
let theme = Theme::from_str(input)?;
self.add_theme(theme);
Ok(())
}
pub fn grammar_by_name(&self, name: &str) -> Result<&Grammar, Error> {
self.grammars
.iter()
.find(|grammar| grammar.matches_name(name))
.ok_or_else(|| Error::UnknownSyntax(name.to_owned()))
}
pub fn theme_by_name(&self, name: &str) -> Result<&Theme, Error> {
self.themes
.iter()
.find(|theme| theme.name.eq_ignore_ascii_case(name))
.ok_or_else(|| Error::UnknownTheme(name.to_owned()))
}
pub fn query(&self, query: GrammarQuery<'_>) -> Result<&Grammar, Error> {
if let Some(syntax) = query.syntax {
return self.grammar_by_name(syntax);
}
if let Some(path) = query.path
&& let Some(grammar) = self
.grammars
.iter()
.find(|grammar| grammar.matches_path(path))
{
return Ok(grammar);
}
if let Some(first_line) = query.first_line
&& let Some(grammar) = self
.grammars
.iter()
.find(|grammar| grammar.matches_first_line(first_line))
{
return Ok(grammar);
}
self.grammar_by_name(PLAIN_TEXT_NAME)
}
}