Initial commit
[yaffs-website] / node_modules / micromatch / lib / glob.js
1 'use strict';
2
3 var chars = require('./chars');
4 var utils = require('./utils');
5
6 /**
7  * Expose `Glob`
8  */
9
10 var Glob = module.exports = function Glob(pattern, options) {
11   if (!(this instanceof Glob)) {
12     return new Glob(pattern, options);
13   }
14   this.options = options || {};
15   this.pattern = pattern;
16   this.history = [];
17   this.tokens = {};
18   this.init(pattern);
19 };
20
21 /**
22  * Initialize defaults
23  */
24
25 Glob.prototype.init = function(pattern) {
26   this.orig = pattern;
27   this.negated = this.isNegated();
28   this.options.track = this.options.track || false;
29   this.options.makeRe = true;
30 };
31
32 /**
33  * Push a change into `glob.history`. Useful
34  * for debugging.
35  */
36
37 Glob.prototype.track = function(msg) {
38   if (this.options.track) {
39     this.history.push({msg: msg, pattern: this.pattern});
40   }
41 };
42
43 /**
44  * Return true if `glob.pattern` was negated
45  * with `!`, also remove the `!` from the pattern.
46  *
47  * @return {Boolean}
48  */
49
50 Glob.prototype.isNegated = function() {
51   if (this.pattern.charCodeAt(0) === 33 /* '!' */) {
52     this.pattern = this.pattern.slice(1);
53     return true;
54   }
55   return false;
56 };
57
58 /**
59  * Expand braces in the given glob pattern.
60  *
61  * We only need to use the [braces] lib when
62  * patterns are nested.
63  */
64
65 Glob.prototype.braces = function() {
66   if (this.options.nobraces !== true && this.options.nobrace !== true) {
67     // naive/fast check for imbalanced characters
68     var a = this.pattern.match(/[\{\(\[]/g);
69     var b = this.pattern.match(/[\}\)\]]/g);
70
71     // if imbalanced, don't optimize the pattern
72     if (a && b && (a.length !== b.length)) {
73       this.options.makeRe = false;
74     }
75
76     // expand brace patterns and join the resulting array
77     var expanded = utils.braces(this.pattern, this.options);
78     this.pattern = expanded.join('|');
79   }
80 };
81
82 /**
83  * Expand bracket expressions in `glob.pattern`
84  */
85
86 Glob.prototype.brackets = function() {
87   if (this.options.nobrackets !== true) {
88     this.pattern = utils.brackets(this.pattern);
89   }
90 };
91
92 /**
93  * Expand bracket expressions in `glob.pattern`
94  */
95
96 Glob.prototype.extglob = function() {
97   if (this.options.noextglob === true) return;
98
99   if (utils.isExtglob(this.pattern)) {
100     this.pattern = utils.extglob(this.pattern, {escape: true});
101   }
102 };
103
104 /**
105  * Parse the given pattern
106  */
107
108 Glob.prototype.parse = function(pattern) {
109   this.tokens = utils.parseGlob(pattern || this.pattern, true);
110   return this.tokens;
111 };
112
113 /**
114  * Replace `a` with `b`. Also tracks the change before and
115  * after each replacement. This is disabled by default, but
116  * can be enabled by setting `options.track` to true.
117  *
118  * Also, when the pattern is a string, `.split()` is used,
119  * because it's much faster than replace.
120  *
121  * @param  {RegExp|String} `a`
122  * @param  {String} `b`
123  * @param  {Boolean} `escape` When `true`, escapes `*` and `?` in the replacement.
124  * @return {String}
125  */
126
127 Glob.prototype._replace = function(a, b, escape) {
128   this.track('before (find): "' + a + '" (replace with): "' + b + '"');
129   if (escape) b = esc(b);
130   if (a && b && typeof a === 'string') {
131     this.pattern = this.pattern.split(a).join(b);
132   } else {
133     this.pattern = this.pattern.replace(a, b);
134   }
135   this.track('after');
136 };
137
138 /**
139  * Escape special characters in the given string.
140  *
141  * @param  {String} `str` Glob pattern
142  * @return {String}
143  */
144
145 Glob.prototype.escape = function(str) {
146   this.track('before escape: ');
147   var re = /["\\](['"]?[^"'\\]['"]?)/g;
148
149   this.pattern = str.replace(re, function($0, $1) {
150     var o = chars.ESC;
151     var ch = o && o[$1];
152     if (ch) {
153       return ch;
154     }
155     if (/[a-z]/i.test($0)) {
156       return $0.split('\\').join('');
157     }
158     return $0;
159   });
160
161   this.track('after escape: ');
162 };
163
164 /**
165  * Unescape special characters in the given string.
166  *
167  * @param  {String} `str`
168  * @return {String}
169  */
170
171 Glob.prototype.unescape = function(str) {
172   var re = /__([A-Z]+)_([A-Z]+)__/g;
173   this.pattern = str.replace(re, function($0, $1) {
174     return chars[$1][$0];
175   });
176   this.pattern = unesc(this.pattern);
177 };
178
179 /**
180  * Escape/unescape utils
181  */
182
183 function esc(str) {
184   str = str.split('?').join('%~');
185   str = str.split('*').join('%%');
186   return str;
187 }
188
189 function unesc(str) {
190   str = str.split('%~').join('?');
191   str = str.split('%%').join('*');
192   return str;
193 }