zee_grammar/
lib.rs

1pub mod builder;
2pub mod config;
3
4mod git;
5
6use anyhow::Result;
7use once_cell::sync::Lazy;
8use std::path::Path;
9use tree_sitter::{Language, Query};
10
11use self::config::{CommentConfig, FilenamePattern, IndentationConfig, ModeConfig};
12
13#[derive(Debug)]
14pub struct Mode {
15    pub name: String,
16    pub scope: String,
17    pub injection_regex: String,
18    pub patterns: Vec<FilenamePattern>,
19    pub comment: Option<CommentConfig>,
20    pub indentation: IndentationConfig,
21    grammar: LazyGrammar,
22}
23
24impl Mode {
25    pub fn new(config: ModeConfig) -> Self {
26        let ModeConfig {
27            name,
28            scope,
29            injection_regex,
30            patterns,
31            comment,
32            indentation,
33            grammar: grammar_config,
34        } = config;
35        Self {
36            name,
37            scope,
38            injection_regex,
39            patterns,
40            comment,
41            indentation,
42            grammar: Lazy::new(Box::new(move || {
43                grammar_config
44                    .map(|grammar_config| grammar_config.grammar_id)
45                    .map(builder::load_grammar)
46            })),
47        }
48    }
49
50    pub fn matches_by_filename(&self, filename: impl AsRef<Path>) -> bool {
51        self.patterns
52            .iter()
53            .any(|pattern| pattern.matches(filename.as_ref()))
54    }
55
56    pub fn language(&self) -> Option<Result<Language, &anyhow::Error>> {
57        Some(self.grammar()?.map(|parser| parser.language))
58    }
59
60    pub fn grammar(&self) -> Option<std::result::Result<&Grammar, &anyhow::Error>> {
61        Lazy::force(&self.grammar)
62            .as_ref()
63            .map(|result| result.as_ref())
64    }
65}
66
67impl Default for Mode {
68    fn default() -> Self {
69        Self {
70            name: "Plain".into(),
71            scope: "plaintext".into(),
72            injection_regex: "".into(),
73            patterns: vec![],
74            comment: None,
75            indentation: Default::default(),
76            grammar: Lazy::new(Box::new(|| None)),
77        }
78    }
79}
80
81#[derive(Debug)]
82pub struct Grammar {
83    pub id: String,
84    pub language: Language,
85    pub highlights: Option<Query>,
86    pub indents: Option<Query>,
87    pub injections: Option<Query>,
88    pub locals: Option<Query>,
89}
90
91impl PartialEq for Mode {
92    fn eq(&self, other: &Self) -> bool {
93        self.name == other.name
94    }
95}
96
97type LazyGrammar = Lazy<
98    Option<Result<Grammar>>,
99    Box<dyn FnOnce() -> Option<Result<Grammar>> + Send + Sync + 'static>,
100>;