Skip to content

Commit 3494c4d

Browse files
committed
add standard
1 parent 1eb3fa4 commit 3494c4d

14 files changed

Lines changed: 5283 additions & 890 deletions

bench/bench.js

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
import expand from '..';
2-
import fs from 'fs';
1+
/* global bench */
32

4-
const resfile = new URL('../test/cases.txt', import.meta.url);
5-
const cases = fs.readFileSync(resfile, 'utf8').split('\n');
3+
import expand from '..'
4+
import fs from 'fs'
65

7-
bench('Average', function() {
8-
cases.forEach(function(testcase) {
9-
expand(testcase);
10-
});
11-
});
6+
const resfile = new URL('../test/cases.txt', import.meta.url)
7+
const cases = fs.readFileSync(resfile, 'utf8').split('\n')
8+
9+
bench('Average', function () {
10+
cases.forEach(function (testcase) {
11+
expand(testcase)
12+
})
13+
})

example.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import expand from './index.js'
22

3-
console.log(expand('http://any.org/archive{1996..1999}/vol{1..4}/part{a,b,c}.html'));
4-
console.log(expand('http://www.numericals.com/file{1..100..10}.txt'));
5-
console.log(expand('http://www.letters.com/file{a..z..2}.txt'));
6-
console.log(expand('mkdir /usr/local/src/bash/{old,new,dist,bugs}'));
7-
console.log(expand('chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}}'));
8-
3+
console.log(expand('http://any.org/archive{1996..1999}/vol{1..4}/part{a,b,c}.html'))
4+
console.log(expand('http://www.numericals.com/file{1..100..10}.txt'))
5+
console.log(expand('http://www.letters.com/file{a..z..2}.txt'))
6+
console.log(expand('mkdir /usr/local/src/bash/{old,new,dist,bugs}'))
7+
console.log(expand('chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}}'))

index.js

Lines changed: 90 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,40 @@
1-
import balanced from 'balanced-match';
1+
import balanced from 'balanced-match'
22

3-
const escSlash = '\0SLASH'+Math.random()+'\0';
4-
const escOpen = '\0OPEN'+Math.random()+'\0';
5-
const escClose = '\0CLOSE'+Math.random()+'\0';
6-
const escComma = '\0COMMA'+Math.random()+'\0';
7-
const escPeriod = '\0PERIOD'+Math.random()+'\0';
3+
const escSlash = '\0SLASH' + Math.random() + '\0'
4+
const escOpen = '\0OPEN' + Math.random() + '\0'
5+
const escClose = '\0CLOSE' + Math.random() + '\0'
6+
const escComma = '\0COMMA' + Math.random() + '\0'
7+
const escPeriod = '\0PERIOD' + Math.random() + '\0'
88

99
/**
1010
* @return {number}
1111
*/
12-
function numeric(str) {
13-
return parseInt(str, 10) == str
12+
function numeric (str) {
13+
return !isNaN(str)
1414
? parseInt(str, 10)
15-
: str.charCodeAt(0);
15+
: str.charCodeAt(0)
1616
}
1717

1818
/**
1919
* @param {string} str
2020
*/
21-
function escapeBraces(str) {
21+
function escapeBraces (str) {
2222
return str.split('\\\\').join(escSlash)
23-
.split('\\{').join(escOpen)
24-
.split('\\}').join(escClose)
25-
.split('\\,').join(escComma)
26-
.split('\\.').join(escPeriod);
23+
.split('\\{').join(escOpen)
24+
.split('\\}').join(escClose)
25+
.split('\\,').join(escComma)
26+
.split('\\.').join(escPeriod)
2727
}
2828

2929
/**
3030
* @param {string} str
3131
*/
32-
function unescapeBraces(str) {
32+
function unescapeBraces (str) {
3333
return str.split(escSlash).join('\\')
34-
.split(escOpen).join('{')
35-
.split(escClose).join('}')
36-
.split(escComma).join(',')
37-
.split(escPeriod).join('.');
34+
.split(escOpen).join('{')
35+
.split(escClose).join('}')
36+
.split(escComma).join(',')
37+
.split(escPeriod).join('.')
3838
}
3939

4040
/**
@@ -43,37 +43,34 @@ function unescapeBraces(str) {
4343
* treated as individual members, like {a,{b,c},d}
4444
* @param {string} str
4545
*/
46-
function parseCommaParts(str) {
47-
if (!str)
48-
return [''];
46+
function parseCommaParts (str) {
47+
if (!str) { return [''] }
4948

50-
const parts = [];
51-
const m = balanced('{', '}', str);
49+
const parts = []
50+
const m = balanced('{', '}', str)
5251

53-
if (!m)
54-
return str.split(',');
52+
if (!m) { return str.split(',') }
5553

56-
const {pre, body, post} = m;
57-
const p = pre.split(',');
54+
const { pre, body, post } = m
55+
const p = pre.split(',')
5856

59-
p[p.length-1] += '{' + body + '}';
60-
const postParts = parseCommaParts(post);
57+
p[p.length - 1] += '{' + body + '}'
58+
const postParts = parseCommaParts(post)
6159
if (post.length) {
62-
p[p.length-1] += postParts.shift();
63-
p.push.apply(p, postParts);
60+
p[p.length - 1] += postParts.shift()
61+
p.push.apply(p, postParts)
6462
}
6563

66-
parts.push.apply(parts, p);
64+
parts.push.apply(parts, p)
6765

68-
return parts;
66+
return parts
6967
}
7068

7169
/**
7270
* @param {string} str
7371
*/
74-
export default function expandTop(str) {
75-
if (!str)
76-
return [];
72+
export default function expandTop (str) {
73+
if (!str) { return [] }
7774

7875
// I don't know why Bash 4.3 does this, but it does.
7976
// Anything starting with {} will have the first two bytes preserved
@@ -82,152 +79,147 @@ export default function expandTop(str) {
8279
// One could argue that this is a bug in Bash, but since the goal of
8380
// this module is to match Bash's rules, we escape a leading {}
8481
if (str.slice(0, 2) === '{}') {
85-
str = '\\{\\}' + str.slice(2);
82+
str = '\\{\\}' + str.slice(2)
8683
}
8784

88-
return expand(escapeBraces(str), true).map(unescapeBraces);
85+
return expand(escapeBraces(str), true).map(unescapeBraces)
8986
}
9087

9188
/**
9289
* @param {string} str
9390
*/
94-
function embrace(str) {
95-
return '{' + str + '}';
91+
function embrace (str) {
92+
return '{' + str + '}'
9693
}
9794

9895
/**
9996
* @param {string} el
10097
*/
101-
function isPadded(el) {
102-
return /^-?0\d/.test(el);
98+
function isPadded (el) {
99+
return /^-?0\d/.test(el)
103100
}
104101

105102
/**
106103
* @param {number} i
107104
* @param {number} y
108105
*/
109-
function lte(i, y) {
110-
return i <= y;
106+
function lte (i, y) {
107+
return i <= y
111108
}
112109

113110
/**
114111
* @param {number} i
115112
* @param {number} y
116113
*/
117-
function gte(i, y) {
118-
return i >= y;
114+
function gte (i, y) {
115+
return i >= y
119116
}
120117

121118
/**
122119
* @param {string} str
123120
* @param {boolean} [isTop]
124121
*/
125-
function expand(str, isTop) {
122+
function expand (str, isTop) {
126123
/** @type {string[]} */
127-
const expansions = [];
124+
const expansions = []
128125

129-
const m = balanced('{', '}', str);
130-
if (!m) return [str];
126+
const m = balanced('{', '}', str)
127+
if (!m) return [str]
131128

132129
// no need to expand pre, since it is guaranteed to be free of brace-sets
133-
const pre = m.pre;
130+
const pre = m.pre
134131
const post = m.post.length
135132
? expand(m.post, false)
136-
: [''];
133+
: ['']
137134

138135
if (/\$$/.test(m.pre)) {
139136
for (let k = 0; k < post.length; k++) {
140-
const expansion = pre+ '{' + m.body + '}' + post[k];
141-
expansions.push(expansion);
137+
const expansion = pre + '{' + m.body + '}' + post[k]
138+
expansions.push(expansion)
142139
}
143140
} else {
144-
const isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
145-
const isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
146-
const isSequence = isNumericSequence || isAlphaSequence;
147-
const isOptions = m.body.indexOf(',') >= 0;
141+
const isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body)
142+
const isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body)
143+
const isSequence = isNumericSequence || isAlphaSequence
144+
const isOptions = m.body.indexOf(',') >= 0
148145
if (!isSequence && !isOptions) {
149146
// {a},b}
150147
if (m.post.match(/,.*\}/)) {
151-
str = m.pre + '{' + m.body + escClose + m.post;
152-
return expand(str);
148+
str = m.pre + '{' + m.body + escClose + m.post
149+
return expand(str)
153150
}
154-
return [str];
151+
return [str]
155152
}
156153

157-
let n;
154+
let n
158155
if (isSequence) {
159-
n = m.body.split(/\.\./);
156+
n = m.body.split(/\.\./)
160157
} else {
161-
n = parseCommaParts(m.body);
158+
n = parseCommaParts(m.body)
162159
if (n.length === 1) {
163160
// x{{a,b}}y ==> x{a}y x{b}y
164-
n = expand(n[0], false).map(embrace);
161+
n = expand(n[0], false).map(embrace)
165162
if (n.length === 1) {
166-
return post.map(function(p) {
167-
return m.pre + n[0] + p;
168-
});
163+
return post.map(function (p) {
164+
return m.pre + n[0] + p
165+
})
169166
}
170167
}
171168
}
172169

173170
// at this point, n is the parts, and we know it's not a comma set
174171
// with a single entry.
175-
let N;
172+
let N
176173

177174
if (isSequence) {
178-
const x = numeric(n[0]);
179-
const y = numeric(n[1]);
175+
const x = numeric(n[0])
176+
const y = numeric(n[1])
180177
const width = Math.max(n[0].length, n[1].length)
181-
let incr = n.length == 3
178+
let incr = n.length === 3
182179
? Math.abs(numeric(n[2]))
183-
: 1;
184-
let test = lte;
185-
const reverse = y < x;
180+
: 1
181+
let test = lte
182+
const reverse = y < x
186183
if (reverse) {
187-
incr *= -1;
188-
test = gte;
184+
incr *= -1
185+
test = gte
189186
}
190-
const pad = n.some(isPadded);
187+
const pad = n.some(isPadded)
191188

192-
N = [];
189+
N = []
193190

194191
for (let i = x; test(i, y); i += incr) {
195-
let c;
192+
let c
196193
if (isAlphaSequence) {
197-
c = String.fromCharCode(i);
198-
if (c === '\\')
199-
c = '';
194+
c = String.fromCharCode(i)
195+
if (c === '\\') { c = '' }
200196
} else {
201-
c = String(i);
197+
c = String(i)
202198
if (pad) {
203-
const need = width - c.length;
199+
const need = width - c.length
204200
if (need > 0) {
205-
const z = new Array(need + 1).join('0');
206-
if (i < 0)
207-
c = '-' + z + c.slice(1);
208-
else
209-
c = z + c;
201+
const z = new Array(need + 1).join('0')
202+
if (i < 0) { c = '-' + z + c.slice(1) } else { c = z + c }
210203
}
211204
}
212205
}
213-
N.push(c);
206+
N.push(c)
214207
}
215208
} else {
216-
N = [];
209+
N = []
217210

218211
for (let j = 0; j < n.length; j++) {
219-
N.push.apply(N, expand(n[j], false));
212+
N.push.apply(N, expand(n[j], false))
220213
}
221214
}
222215

223216
for (let j = 0; j < N.length; j++) {
224217
for (let k = 0; k < post.length; k++) {
225-
const expansion = pre + N[j] + post[k];
226-
if (!isTop || isSequence || expansion)
227-
expansions.push(expansion);
218+
const expansion = pre + N[j] + post[k]
219+
if (!isTop || isSequence || expansion) { expansions.push(expansion) }
228220
}
229221
}
230222
}
231223

232-
return expansions;
224+
return expansions
233225
}

0 commit comments

Comments
 (0)