textmate_scope_selector_peg/
matchers.rs1pub trait Matcher {
3 fn matches(&self, scope: &str) -> bool;
4 fn get_prefix(&self, _scopes: &str) -> Option<char> {
5 None
6 }
7}
8
9pub 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
26pub struct TrueMatcher;
28
29impl Matcher for TrueMatcher {
30 fn matches(&self, _: &str) -> bool {
31 true
32 }
33}
34
35pub 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
59pub 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
88pub 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
139pub 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
161pub 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
187pub 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
204pub 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}