Skip to content

Commit 13aa1c9

Browse files
committed
rename toPreset.. default output function.. more tests
1 parent b254deb commit 13aa1c9

File tree

5 files changed

+92
-25
lines changed

5 files changed

+92
-25
lines changed

dist/index.cjs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ function getFromIndex (arr, find) {
9292
const fromFns = arrayBack(find).map(convertToFunction);
9393

9494
if (fromFns.length === 0) {
95-
throw new Error('from required')
95+
throw new Error('from/single required') // TODO: obviously broken semantically
9696
}
9797

9898
let fromIndex;
@@ -132,6 +132,8 @@ function positional (arr, fromIndex, options = {}) {
132132
return output
133133
}
134134

135+
function defaultOutput (val) { return val }
136+
135137
/* TODO: factor out into a FromTo Extractor-derived class as relevant only to from-to. */
136138
const toPresets = {
137139
singleOptionValue (arg, index, argv, valueIndex) {
@@ -161,13 +163,11 @@ class CommandLineArgs {
161163

162164
const notPositionals = optionDefinitions.filter(d => d.extractor !== 'positional');
163165
for (const def of notPositionals) {
166+
def.output ||= defaultOutput;
164167
let extraction;
165168
if (def.extractor === 'fromTo') {
166-
extraction = fromTo(this.argv, {
167-
from: def.from,
168-
to: toPresets[def.to],
169-
remove: true
170-
});
169+
const to = def.toPreset ? toPresets[def.toPreset] : def.to;
170+
extraction = fromTo(this.argv, { from: def.from, to, remove: true });
171171
} else if (def.extractor === 'single') {
172172
extraction = single(this.argv, def.single, { remove: true });
173173
} else {
@@ -187,6 +187,7 @@ class CommandLineArgs {
187187

188188
if (positionals.length) {
189189
for (const def of positionals) {
190+
def.output ||= defaultOutput;
190191
const extraction = positional(this.argv, def.position - 1, { remove: true });
191192
if (extraction.length) {
192193
result[def.name] = def.output(extraction);

index.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { fromTo, single, positional } from './lib/from-to.js'
22

3+
function defaultOutput (val) { return val }
4+
35
/* TODO: factor out into a FromTo Extractor-derived class as relevant only to from-to. */
46
const toPresets = {
57
singleOptionValue (arg, index, argv, valueIndex) {
@@ -29,13 +31,11 @@ class CommandLineArgs {
2931

3032
const notPositionals = optionDefinitions.filter(d => d.extractor !== 'positional')
3133
for (const def of notPositionals) {
34+
def.output ||= defaultOutput
3235
let extraction
3336
if (def.extractor === 'fromTo') {
34-
extraction = fromTo(this.argv, {
35-
from: def.from,
36-
to: toPresets[def.to],
37-
remove: true
38-
})
37+
const to = def.toPreset ? toPresets[def.toPreset] : def.to
38+
extraction = fromTo(this.argv, { from: def.from, to, remove: true })
3939
} else if (def.extractor === 'single') {
4040
extraction = single(this.argv, def.single, { remove: true })
4141
} else {
@@ -55,6 +55,7 @@ class CommandLineArgs {
5555

5656
if (positionals.length) {
5757
for (const def of positionals) {
58+
def.output ||= defaultOutput
5859
const extraction = positional(this.argv, def.position - 1, { remove: true })
5960
if (extraction.length) {
6061
result[def.name] = def.output(extraction)

lib/from-to.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ function getFromIndex (arr, find) {
9090
const fromFns = arrayBack(find).map(convertToFunction)
9191

9292
if (fromFns.length === 0) {
93-
throw new Error('from required')
93+
throw new Error('from/single required') // TODO: obviously broken semantically
9494
}
9595

9696
let fromIndex

test/from-to.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,29 @@ test.set('from and to: string inputs', async function () {
1313
a.deepEqual(arr, ['one', 'here', '--', '--', '--', 'here', '--', '--', '--', 'there'])
1414
})
1515

16+
test.set('from and to: from array', async function () {
17+
const arr = ['one', '-o', 'two', '-v']
18+
const result = fromTo(arr, {
19+
from: ['--option', '-o'],
20+
to: ['--version', '-v']
21+
})
22+
a.deepEqual(result, [ '-o', 'two' ])
23+
})
24+
25+
test.set('from and to: from array 2', async function () {
26+
const arr = ['one', '-o', 'two', '--version']
27+
const result = fromTo(arr, {
28+
from: ['--option', '-o'],
29+
to: ['--version', '-v']
30+
})
31+
a.deepEqual(result, [ '-o', 'two' ])
32+
})
33+
1634
test.set('from and to: function inputs', async function () {
1735
const arr = ['one', 'here', '--', '--', '--', 'here', '--', '--', '--', 'there']
1836
const result = fromTo(arr, {
1937
from: (val) => val === 'here',
20-
to: (val) => val === 'here' || val === 'there'
38+
to: (val) => val === 'here' || val === 'there' // equivalent to [here, there]
2139
})
2240
a.deepEqual(result, ['here', '--', '--', '--'])
2341
a.deepEqual(arr, ['one', 'here', '--', '--', '--', 'here', '--', '--', '--', 'there'])

test/test.js

Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ test.set('Input argv is not mutated', async function () {
1010
name: 'one',
1111
extractor: 'fromTo',
1212
from: '--one',
13-
to: 'singleOptionValue', // TODO: Rename as "toPreset" to be more explicit we're using a preset.
14-
output: extraction => extraction[1] // TODO: Define a FromToExtractor derived class which already includes this specific output value by default.
13+
toPreset: 'singleOptionValue',
14+
output: extraction => extraction[1]
1515
}
1616
]
1717
const cla = new CommandLineArgs(argv)
@@ -28,7 +28,7 @@ test.set('--option <no value>', async function () {
2828
name: 'one',
2929
extractor: 'fromTo',
3030
from: '--one',
31-
to: 'singleOptionValue',
31+
toPreset: 'singleOptionValue',
3232
output: extraction => extraction[1]
3333
}
3434
]
@@ -38,7 +38,7 @@ test.set('--option <no value>', async function () {
3838
a.deepEqual(cla.argv, ['one', 'two', '--two', 'three'])
3939
})
4040

41-
test.set('--option flag', async function () {
41+
test.set('single --option flag', async function () {
4242
const argv = ['one', 'two', '--one', '--two']
4343
const optionDefinitions = [
4444
{
@@ -54,6 +54,28 @@ test.set('--option flag', async function () {
5454
a.deepEqual(cla.argv, ['one', 'two', '--two'])
5555
})
5656

57+
test.set('single regex', async function () {
58+
const argv = ['one', 'two', '--one', '--two']
59+
const optionDefinitions = [
60+
{
61+
name: 'one',
62+
extractor: 'single',
63+
single: /--o[n]+e/,
64+
output: extraction => true
65+
}
66+
]
67+
const cla = new CommandLineArgs(argv)
68+
const result = cla.parse(optionDefinitions)
69+
a.deepEqual(result, { one: true })
70+
a.deepEqual(cla.argv, ['one', 'two', '--two'])
71+
72+
const argv2 = ['one', 'two', '--onnnnne', '--two']
73+
const cla2 = new CommandLineArgs(argv2)
74+
const result2 = cla2.parse(optionDefinitions)
75+
a.deepEqual(result, { one: true })
76+
a.deepEqual(cla.argv, ['one', 'two', '--two'])
77+
})
78+
5779
test.set('--option flag not present', async function () {
5880
const argv = ['one', 'two', '--not-one', '--two']
5981
const optionDefinitions = [
@@ -90,7 +112,7 @@ test.set('Positionals must be args 1 and 2, with options following', async funct
90112
name: 'option',
91113
extractor: 'fromTo',
92114
from: ['--option', '-o'],
93-
to: 'singleOptionValue',
115+
toPreset: 'singleOptionValue',
94116
output: extraction => extraction[1]
95117
},
96118
{
@@ -157,7 +179,7 @@ test.set('Positional, one single, one from-to', async function () {
157179
name: 'exchange',
158180
extractor: 'fromTo',
159181
from: '--exchange',
160-
to: 'singleOptionValue',
182+
toPreset: 'singleOptionValue',
161183
output: extraction => extraction[1]
162184
},
163185
])
@@ -216,7 +238,7 @@ test.set('Magic arg values: file1 file2 extra-large verbose output final', async
216238
name: 'output',
217239
extractor: 'fromTo',
218240
from: 'output',
219-
to: 'singleOptionValue',
241+
toPreset: 'singleOptionValue',
220242
output: extraction => extraction[1]
221243
}
222244
// {
@@ -265,29 +287,29 @@ test.set('self-defining options', async function () {
265287
'3000'
266288
]
267289

268-
/* Instead of "dynamic definition" magic, just run the parser over argv multiple times, one for each desire result object */
290+
/* Instead of "dynamic definition" magic, just run the parser over argv multiple times, one for each desired result object */
269291
/* Parse the args first for `--configName.optionName.optionValueType` format args, creating option definitions */
270292

271293
const optionDefinitions = [
272294
{
273295
name: 'one',
274296
extractor: 'fromTo',
275297
from: /^--server\.string\[\]/,
276-
to: 'multipleOptionValue',
298+
toPreset: 'multipleOptionValue',
277299
output: e => e.slice(1)
278300
},
279301
{
280302
name: 'two',
281303
extractor: 'fromTo',
282304
from: /^--server\.number\./,
283-
to: 'singleOptionValue',
305+
toPreset: 'singleOptionValue',
284306
output: e => e[1]
285307
},
286308
{
287309
name: 'broke',
288310
extractor: 'fromTo',
289311
from: /^--server\.number\./,
290-
to: 'singleOptionValue',
312+
toPreset: 'singleOptionValue',
291313
output: e => Number(e[1])
292314
},
293315
{
@@ -300,7 +322,7 @@ test.set('self-defining options', async function () {
300322
name: 'four',
301323
extractor: 'fromTo',
302324
from: /^--server\.string\./,
303-
to: 'singleOptionValue',
325+
toPreset: 'singleOptionValue',
304326
output: e => e[1]
305327
}
306328
]
@@ -365,4 +387,29 @@ skip.set('to not found: no args matched', async function () {
365387
})
366388
})
367389

390+
test.set('Multiple parses to consume all args', async function () {
391+
const argv = ['server', '--option', 'value', 'clive', 'server', '--verbose']
392+
const commandLineArgs = new CommandLineArgs(argv)
393+
const result1 = commandLineArgs.parse([
394+
{
395+
name: 'extraction',
396+
extractor: 'fromTo',
397+
from: 'server',
398+
to: 'server'
399+
}
400+
])
401+
const result2 = commandLineArgs.parse([
402+
{
403+
name: 'extraction',
404+
extractor: 'fromTo',
405+
from: 'server',
406+
to: 'server'
407+
}
408+
])
409+
// this.data = { result1, result2 }
410+
411+
a.deepEqual(result1, { extraction: [ 'server', '--option', 'value', 'clive' ] })
412+
a.deepEqual(result2, { extraction: [ 'server', '--verbose'] })
413+
})
414+
368415
export { test, only, skip }

0 commit comments

Comments
 (0)