textmate_scope_selector_peg/
matchers.rs

1// Traits for matchers
2pub trait Matcher {
3    fn matches(&self, scope: &str) -> bool;
4    fn get_prefix(&self, _scopes: &str) -> Option<char> {
5        None
6    }
7}
8
9// SegmentMatcher
10pub struct SegmentMatcher {
11    segment: String,
12}
13
14impl SegmentMatcher {
15    pub fn new(segment: &str) -> Self {
16        Self { segment: segment.to_string() }
17    }
18}
19
20impl Matcher for SegmentMatcher {
21    fn matches(&self, scope: &str) -> bool {
22        scope == self.segment
23    }
24}
25
26// TrueMatcher
27pub struct TrueMatcher;
28
29impl Matcher for TrueMatcher {
30    fn matches(&self, _: &str) -> bool {
31        true
32    }
33}
34
35// ScopeMatcher
36pub struct ScopeMatcher {
37    segments: Vec<Box<dyn Matcher>>,
38}
39
40impl ScopeMatcher {
41    pub fn new(segments: Vec<Box<(dyn Matcher + 'static)>>) -> Self {
42        Self { segments }
43    }
44}
45
46impl Matcher for ScopeMatcher {
47    fn matches(&self, scope: &str) -> bool {
48        let scope_segments: Vec<&str> = scope.split('.').collect();
49        if scope_segments.len() < self.segments.len() {
50            return false;
51        }
52
53        self.segments.iter().zip(scope_segments.iter()).all(|(segment, scope)| {
54            segment.matches(scope)
55        })
56    }
57}
58
59// GroupMatcher
60pub struct GroupMatcher {
61    prefix: Option<char>,
62    selector: Box<dyn Matcher>,
63}
64
65impl GroupMatcher {
66    pub fn new(prefix: Option<&str>, selector: Box<dyn Matcher>) -> Self {
67        Self {
68            prefix: prefix.and_then(|f| f.chars().next()),
69            selector,
70        }
71    }
72}
73
74impl Matcher for GroupMatcher {
75    fn matches(&self, scopes: &str) -> bool {
76        self.selector.matches(scopes)
77    }
78
79    fn get_prefix(&self, scopes: &str) -> Option<char> {
80        if self.matches(scopes) {
81            self.prefix
82        } else {
83            None
84        }
85    }
86}
87
88// PathMatcher
89pub struct PathMatcher {
90    prefix: Option<char>,
91    matchers: Vec<Box<dyn Matcher>>,
92}
93
94impl PathMatcher {
95    pub fn new(
96        prefix: Option<&str>,
97        matchers: Vec<Box<dyn Matcher>>,
98    ) -> Self {
99        Self {
100			prefix: prefix.and_then(|f| f.chars().next()),
101			matchers
102		}
103    }
104}
105
106impl Matcher for PathMatcher {
107    fn matches(&self, scopes: &str) -> bool {
108        let scopes_iter = scopes.split(' ').peekable();
109        let mut index = 0;
110
111        if self.matchers.is_empty() {
112            return false;
113        }
114
115        let mut matcher = &self.matchers[index];
116
117        for scope in scopes_iter {
118            if matcher.matches(scope) {
119                index += 1;
120                if index >= self.matchers.len() {
121                    return true;
122                }
123                matcher = &self.matchers[index];
124            }
125        }
126
127        false
128    }
129
130    fn get_prefix(&self, scopes: &str) -> Option<char> {
131        if self.matches(scopes) {
132            self.prefix
133        } else {
134            None
135        }
136    }
137}
138
139// OrMatcher
140pub struct OrMatcher {
141    left: Box<dyn Matcher>,
142    right: Box<dyn Matcher>,
143}
144
145impl OrMatcher {
146    pub fn new(left: Box<dyn Matcher>, right: Box<dyn Matcher>) -> Self {
147        Self { left, right }
148    }
149}
150
151impl Matcher for OrMatcher {
152    fn matches(&self, scopes: &str) -> bool {
153        self.left.matches(scopes) || self.right.matches(scopes)
154    }
155
156    fn get_prefix(&self, scopes: &str) -> Option<char> {
157        self.left.get_prefix(scopes).or_else(|| self.right.get_prefix(scopes))
158    }
159}
160
161// AndMatcher
162pub struct AndMatcher {
163    left: Box<dyn Matcher>,
164    right: Box<dyn Matcher>,
165}
166
167impl AndMatcher {
168    pub fn new(left: Box<dyn Matcher>, right: Box<dyn Matcher>) -> Self {
169        Self { left, right }
170    }
171}
172
173impl Matcher for AndMatcher {
174    fn matches(&self, scopes: &str) -> bool {
175        self.left.matches(scopes) && self.right.matches(scopes)
176    }
177
178    fn get_prefix(&self, scopes: &str) -> Option<char> {
179        if self.matches(scopes) {
180            self.left.get_prefix(scopes)
181        } else {
182            None
183        }
184    }
185}
186
187// NegateMatcher
188pub struct NegateMatcher {
189    matcher: Box<dyn Matcher>,
190}
191
192impl NegateMatcher {
193    pub fn new(matcher: Box<dyn Matcher>) -> Self {
194        Self { matcher }
195    }
196}
197
198impl Matcher for NegateMatcher {
199    fn matches(&self, scopes: &str) -> bool {
200        !self.matcher.matches(scopes)
201    }
202}
203
204// CompositeMatcher
205pub struct CompositeMatcher {
206    matcher: Box<dyn Matcher>,
207}
208
209impl CompositeMatcher {
210    pub fn new(
211        left: Box<dyn Matcher>,
212        operator: char,
213        right: Box<dyn Matcher>,
214    ) -> Self {
215        let matcher: Box<dyn Matcher> = match operator {
216            '|' => Box::new(OrMatcher::new(left, right)),
217            '&' => Box::new(AndMatcher::new(left, right)),
218            '-' => Box::new(AndMatcher::new(left, Box::new(NegateMatcher::new(right)))),
219            _ => panic!("Unsupported operator"),
220        };
221        Self { matcher }
222    }
223}
224
225impl Matcher for CompositeMatcher {
226    fn matches(&self, scopes: &str) -> bool {
227        self.matcher.matches(scopes)
228    }
229
230    fn get_prefix(&self, scopes: &str) -> Option<char> {
231        self.matcher.get_prefix(scopes)
232    }
233}