.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / nanomatch / lib / compilers.js
1 'use strict';
2
3 /**
4 * Nanomatch compilers
5 */
6
7 module.exports = function(nanomatch, options) {
8   function slash() {
9     if (options && typeof options.slash === 'string') {
10       return options.slash;
11     }
12     if (options && typeof options.slash === 'function') {
13       return options.slash.call(nanomatch);
14     }
15     return '\\\\/';
16   }
17
18   function star() {
19     if (options && typeof options.star === 'string') {
20       return options.star;
21     }
22     if (options && typeof options.star === 'function') {
23       return options.star.call(nanomatch);
24     }
25     return '[^' + slash() + ']*?';
26   }
27
28   var ast = nanomatch.ast = nanomatch.parser.ast;
29   ast.state = nanomatch.parser.state;
30   nanomatch.compiler.state = ast.state;
31   nanomatch.compiler
32
33     /**
34      * Negation / escaping
35      */
36
37     .set('not', function(node) {
38       var prev = this.prev();
39       if (this.options.nonegate === true || prev.type !== 'bos') {
40         return this.emit('\\' + node.val, node);
41       }
42       return this.emit(node.val, node);
43     })
44     .set('escape', function(node) {
45       if (this.options.unescape && /^[-\w_.]/.test(node.val)) {
46         return this.emit(node.val, node);
47       }
48       return this.emit('\\' + node.val, node);
49     })
50     .set('quoted', function(node) {
51       return this.emit(node.val, node);
52     })
53
54     /**
55      * Regex
56      */
57
58     .set('dollar', function(node) {
59       if (node.parent.type === 'bracket') {
60         return this.emit(node.val, node);
61       }
62       return this.emit('\\' + node.val, node);
63     })
64
65     /**
66      * Dot: "."
67      */
68
69     .set('dot', function(node) {
70       if (node.dotfiles === true) this.dotfiles = true;
71       return this.emit('\\' + node.val, node);
72     })
73
74     /**
75      * Slashes: "/" and "\"
76      */
77
78     .set('backslash', function(node) {
79       return this.emit(node.val, node);
80     })
81     .set('slash', function(node, nodes, i) {
82       var val = '[' + slash() + ']';
83       var parent = node.parent;
84       var prev = this.prev();
85
86       // set "node.hasSlash" to true on all ancestor parens nodes
87       while (parent.type === 'paren' && !parent.hasSlash) {
88         parent.hasSlash = true;
89         parent = parent.parent;
90       }
91
92       if (prev.addQmark) {
93         val += '?';
94       }
95
96       // word boundary
97       if (node.rest.slice(0, 2) === '\\b') {
98         return this.emit(val, node);
99       }
100
101       // globstars
102       if (node.parsed === '**' || node.parsed === './**') {
103         this.output = '(?:' + this.output;
104         return this.emit(val + ')?', node);
105       }
106
107       // negation
108       if (node.parsed === '!**' && this.options.nonegate !== true) {
109         return this.emit(val + '?\\b', node);
110       }
111       return this.emit(val, node);
112     })
113
114     /**
115      * Square brackets
116      */
117
118     .set('bracket', function(node) {
119       var close = node.close;
120       var open = !node.escaped ? '[' : '\\[';
121       var negated = node.negated;
122       var inner = node.inner;
123       var val = node.val;
124
125       if (node.escaped === true) {
126         inner = inner.replace(/\\?(\W)/g, '\\$1');
127         negated = '';
128       }
129
130       if (inner === ']-') {
131         inner = '\\]\\-';
132       }
133
134       if (negated && inner.indexOf('.') === -1) {
135         inner += '.';
136       }
137       if (negated && inner.indexOf('/') === -1) {
138         inner += '/';
139       }
140
141       val = open + negated + inner + close;
142       return this.emit(val, node);
143     })
144
145     /**
146      * Square: "[.]" (only matches a single character in brackets)
147      */
148
149     .set('square', function(node) {
150       var val = (/^\W/.test(node.val) ? '\\' : '') + node.val;
151       return this.emit(val, node);
152     })
153
154     /**
155      * Question mark: "?"
156      */
157
158     .set('qmark', function(node) {
159       var prev = this.prev();
160       // don't use "slash" variable so that we always avoid
161       // matching backslashes and slashes with a qmark
162       var val = '[^.\\\\/]';
163       if (this.options.dot || (prev.type !== 'bos' && prev.type !== 'slash')) {
164         val = '[^\\\\/]';
165       }
166
167       if (node.parsed.slice(-1) === '(') {
168         var ch = node.rest.charAt(0);
169         if (ch === '!' || ch === '=' || ch === ':') {
170           return this.emit(node.val, node);
171         }
172       }
173
174       if (node.val.length > 1) {
175         val += '{' + node.val.length + '}';
176       }
177       return this.emit(val, node);
178     })
179
180     /**
181      * Plus
182      */
183
184     .set('plus', function(node) {
185       var prev = node.parsed.slice(-1);
186       if (prev === ']' || prev === ')') {
187         return this.emit(node.val, node);
188       }
189       if (!this.output || (/[?*+]/.test(ch) && node.parent.type !== 'bracket')) {
190         return this.emit('\\+', node);
191       }
192       var ch = this.output.slice(-1);
193       if (/\w/.test(ch) && !node.inside) {
194         return this.emit('+\\+?', node);
195       }
196       return this.emit('+', node);
197     })
198
199     /**
200      * globstar: '**'
201      */
202
203     .set('globstar', function(node, nodes, i) {
204       if (!this.output) {
205         this.state.leadingGlobstar = true;
206       }
207
208       var prev = this.prev();
209       var before = this.prev(2);
210       var next = this.next();
211       var after = this.next(2);
212       var type = prev.type;
213       var val = node.val;
214
215       if (prev.type === 'slash' && next.type === 'slash') {
216         if (before.type === 'text') {
217           this.output += '?';
218
219           if (after.type !== 'text') {
220             this.output += '\\b';
221           }
222         }
223       }
224
225       var parsed = node.parsed;
226       if (parsed.charAt(0) === '!') {
227         parsed = parsed.slice(1);
228       }
229
230       var isInside = node.isInside.paren || node.isInside.brace;
231       if (parsed && type !== 'slash' && type !== 'bos' && !isInside) {
232         val = star();
233       } else {
234         val = this.options.dot !== true
235           ? '(?:(?!(?:[' + slash() + ']|^)\\.).)*?'
236           : '(?:(?!(?:[' + slash() + ']|^)(?:\\.{1,2})($|[' + slash() + ']))(?!\\.{2}).)*?';
237       }
238
239       if ((type === 'slash' || type === 'bos') && this.options.dot !== true) {
240         val = '(?!\\.)' + val;
241       }
242
243       if (prev.type === 'slash' && next.type === 'slash' && before.type !== 'text') {
244         if (after.type === 'text' || after.type === 'star') {
245           node.addQmark = true;
246         }
247       }
248
249       if (this.options.capture) {
250         val = '(' + val + ')';
251       }
252
253       return this.emit(val, node);
254     })
255
256     /**
257      * Star: "*"
258      */
259
260     .set('star', function(node, nodes, i) {
261       var prior = nodes[i - 2] || {};
262       var prev = this.prev();
263       var next = this.next();
264       var type = prev.type;
265
266       function isStart(n) {
267         return n.type === 'bos' || n.type === 'slash';
268       }
269
270       if (this.output === '' && this.options.contains !== true) {
271         this.output = '(?![' + slash() + '])';
272       }
273
274       if (type === 'bracket' && this.options.bash === false) {
275         var str = next && next.type === 'bracket' ? star() : '*?';
276         if (!prev.nodes || prev.nodes[1].type !== 'posix') {
277           return this.emit(str, node);
278         }
279       }
280
281       var prefix = !this.dotfiles && type !== 'text' && type !== 'escape'
282         ? (this.options.dot ? '(?!(?:^|[' + slash() + '])\\.{1,2}(?:$|[' + slash() + ']))' : '(?!\\.)')
283         : '';
284
285       if (isStart(prev) || (isStart(prior) && type === 'not')) {
286         if (prefix !== '(?!\\.)') {
287           prefix += '(?!(\\.{2}|\\.[' + slash() + ']))(?=.)';
288         } else {
289           prefix += '(?=.)';
290         }
291       } else if (prefix === '(?!\\.)') {
292         prefix = '';
293       }
294
295       if (prev.type === 'not' && prior.type === 'bos' && this.options.dot === true) {
296         this.output = '(?!\\.)' + this.output;
297       }
298
299       var output = prefix + star();
300       if (this.options.capture) {
301         output = '(' + output + ')';
302       }
303
304       return this.emit(output, node);
305     })
306
307     /**
308      * Text
309      */
310
311     .set('text', function(node) {
312       return this.emit(node.val, node);
313     })
314
315     /**
316      * End-of-string
317      */
318
319     .set('eos', function(node) {
320       var prev = this.prev();
321       var val = node.val;
322
323       this.output = '(?:\\.[' + slash() + '](?=.))?' + this.output;
324       if (this.state.metachar && prev.type !== 'qmark' && prev.type !== 'slash') {
325         val += (this.options.contains ? '[' + slash() + ']?' : '(?:[' + slash() + ']|$)');
326       }
327
328       return this.emit(val, node);
329     });
330
331   /**
332    * Allow custom compilers to be passed on options
333    */
334
335   if (options && typeof options.compilers === 'function') {
336     options.compilers(nanomatch.compiler);
337   }
338 };
339