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>;