Path: blob/master/node_modules/brace-expansion/index.js
2522 views
var concatMap = require('concat-map');1var balanced = require('balanced-match');23module.exports = expandTop;45var escSlash = '\0SLASH'+Math.random()+'\0';6var escOpen = '\0OPEN'+Math.random()+'\0';7var escClose = '\0CLOSE'+Math.random()+'\0';8var escComma = '\0COMMA'+Math.random()+'\0';9var escPeriod = '\0PERIOD'+Math.random()+'\0';1011function numeric(str) {12return parseInt(str, 10) == str13? parseInt(str, 10)14: str.charCodeAt(0);15}1617function escapeBraces(str) {18return str.split('\\\\').join(escSlash)19.split('\\{').join(escOpen)20.split('\\}').join(escClose)21.split('\\,').join(escComma)22.split('\\.').join(escPeriod);23}2425function unescapeBraces(str) {26return str.split(escSlash).join('\\')27.split(escOpen).join('{')28.split(escClose).join('}')29.split(escComma).join(',')30.split(escPeriod).join('.');31}323334// Basically just str.split(","), but handling cases35// where we have nested braced sections, which should be36// treated as individual members, like {a,{b,c},d}37function parseCommaParts(str) {38if (!str)39return [''];4041var parts = [];42var m = balanced('{', '}', str);4344if (!m)45return str.split(',');4647var pre = m.pre;48var body = m.body;49var post = m.post;50var p = pre.split(',');5152p[p.length-1] += '{' + body + '}';53var postParts = parseCommaParts(post);54if (post.length) {55p[p.length-1] += postParts.shift();56p.push.apply(p, postParts);57}5859parts.push.apply(parts, p);6061return parts;62}6364function expandTop(str) {65if (!str)66return [];6768// I don't know why Bash 4.3 does this, but it does.69// Anything starting with {} will have the first two bytes preserved70// but *only* at the top level, so {},a}b will not expand to anything,71// but a{},b}c will be expanded to [a}c,abc].72// One could argue that this is a bug in Bash, but since the goal of73// this module is to match Bash's rules, we escape a leading {}74if (str.substr(0, 2) === '{}') {75str = '\\{\\}' + str.substr(2);76}7778return expand(escapeBraces(str), true).map(unescapeBraces);79}8081function identity(e) {82return e;83}8485function embrace(str) {86return '{' + str + '}';87}88function isPadded(el) {89return /^-?0\d/.test(el);90}9192function lte(i, y) {93return i <= y;94}95function gte(i, y) {96return i >= y;97}9899function expand(str, isTop) {100var expansions = [];101102var m = balanced('{', '}', str);103if (!m || /\$$/.test(m.pre)) return [str];104105var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);106var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);107var isSequence = isNumericSequence || isAlphaSequence;108var isOptions = m.body.indexOf(',') >= 0;109if (!isSequence && !isOptions) {110// {a},b}111if (m.post.match(/,.*\}/)) {112str = m.pre + '{' + m.body + escClose + m.post;113return expand(str);114}115return [str];116}117118var n;119if (isSequence) {120n = m.body.split(/\.\./);121} else {122n = parseCommaParts(m.body);123if (n.length === 1) {124// x{{a,b}}y ==> x{a}y x{b}y125n = expand(n[0], false).map(embrace);126if (n.length === 1) {127var post = m.post.length128? expand(m.post, false)129: [''];130return post.map(function(p) {131return m.pre + n[0] + p;132});133}134}135}136137// at this point, n is the parts, and we know it's not a comma set138// with a single entry.139140// no need to expand pre, since it is guaranteed to be free of brace-sets141var pre = m.pre;142var post = m.post.length143? expand(m.post, false)144: [''];145146var N;147148if (isSequence) {149var x = numeric(n[0]);150var y = numeric(n[1]);151var width = Math.max(n[0].length, n[1].length)152var incr = n.length == 3153? Math.abs(numeric(n[2]))154: 1;155var test = lte;156var reverse = y < x;157if (reverse) {158incr *= -1;159test = gte;160}161var pad = n.some(isPadded);162163N = [];164165for (var i = x; test(i, y); i += incr) {166var c;167if (isAlphaSequence) {168c = String.fromCharCode(i);169if (c === '\\')170c = '';171} else {172c = String(i);173if (pad) {174var need = width - c.length;175if (need > 0) {176var z = new Array(need + 1).join('0');177if (i < 0)178c = '-' + z + c.slice(1);179else180c = z + c;181}182}183}184N.push(c);185}186} else {187N = concatMap(n, function(el) { return expand(el, false) });188}189190for (var j = 0; j < N.length; j++) {191for (var k = 0; k < post.length; k++) {192var expansion = pre + N[j] + post[k];193if (!isTop || isSequence || expansion)194expansions.push(expansion);195}196}197198return expansions;199}200201202203