rustik_highlight/
registry.rs1use std::path::Path;
9use std::str::FromStr;
10
11use crate::Error;
12use crate::grammar::{Grammar, PLAIN_TEXT_NAME};
13use crate::theme::Theme;
14
15#[derive(Debug, Default)]
17pub struct Registry {
18 pub grammars: Vec<Grammar>,
20 pub themes: Vec<Theme>,
22}
23
24#[derive(Clone, Copy, Debug, Default)]
26pub struct GrammarQuery<'a> {
27 pub syntax: Option<&'a str>,
29 pub path: Option<&'a Path>,
31 pub first_line: Option<&'a str>,
33}
34
35impl Registry {
36 pub fn new() -> Self {
38 Self::default()
39 }
40
41 pub fn with_plain_text() -> Self {
43 let mut registry = Self::new();
44 registry.add_grammar(Grammar::plain_text());
45 registry
46 }
47
48 pub fn with_builtin_syntaxes() -> Self {
50 let mut registry = Self::with_plain_text();
51 registry.add_grammar(Grammar::json());
52 registry
53 }
54
55 pub fn add_grammar(&mut self, grammar: Grammar) {
57 self.grammars.push(grammar);
58 }
59
60 pub fn add_json(&mut self) {
62 self.add_grammar(Grammar::json());
63 }
64
65 pub fn add_grammar_json(&mut self, input: &str) -> Result<(), Error> {
67 let grammar = Grammar::from_str(input)?;
68 self.add_grammar(grammar);
69 Ok(())
70 }
71
72 pub fn add_theme(&mut self, theme: Theme) {
74 self.themes.push(theme);
75 }
76
77 pub fn add_theme_json(&mut self, input: &str) -> Result<(), Error> {
79 let theme = Theme::from_str(input)?;
80 self.add_theme(theme);
81 Ok(())
82 }
83
84 pub fn grammar_by_name(&self, name: &str) -> Result<&Grammar, Error> {
86 self.grammars
87 .iter()
88 .find(|grammar| grammar.matches_name(name))
89 .ok_or_else(|| Error::UnknownSyntax(name.to_owned()))
90 }
91
92 pub fn theme_by_name(&self, name: &str) -> Result<&Theme, Error> {
94 self.themes
95 .iter()
96 .find(|theme| theme.name.eq_ignore_ascii_case(name))
97 .ok_or_else(|| Error::UnknownTheme(name.to_owned()))
98 }
99
100 pub fn query(&self, query: GrammarQuery<'_>) -> Result<&Grammar, Error> {
102 if let Some(syntax) = query.syntax {
103 return self.grammar_by_name(syntax);
104 }
105 if let Some(path) = query.path
106 && let Some(grammar) = self
107 .grammars
108 .iter()
109 .find(|grammar| grammar.matches_path(path))
110 {
111 return Ok(grammar);
112 }
113 if let Some(first_line) = query.first_line
114 && let Some(grammar) = self
115 .grammars
116 .iter()
117 .find(|grammar| grammar.matches_first_line(first_line))
118 {
119 return Ok(grammar);
120 }
121 self.grammar_by_name(PLAIN_TEXT_NAME)
122 }
123}