-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for variadic options (#1250)
* First cut at variadic option implementation * Rework variadic regexp - remove ellipsis for symmetry with .arguments - require word character before dots * Add tests for variadic options * Add test on non-variadic pattern * Rethink interation of variadic and coercion function * Fix typos * Raise ecmaVersion to eliminate some false positive errors in example files * Improve variadic option with optional value, zero or more values * Reorder comparison to match previous test * Use consistent test names * Add example and README for variadic option * Fix typo
- Loading branch information
1 parent
e9a6109
commit 913389f
Showing
10 changed files
with
243 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#!/usr/bin/env node | ||
|
||
// This is used as an example in the README for variadic options. | ||
|
||
// const commander = require('commander'); // (normal include) | ||
const commander = require('../'); // include commander in git clone of commander repo | ||
const program = new commander.Command(); | ||
|
||
program | ||
.option('-n, --number <value...>', 'specify numbers') | ||
.option('-l, --letter [value...]', 'specify letters'); | ||
|
||
program.parse(); | ||
|
||
console.log('Options: ', program.opts()); | ||
console.log('Remaining arguments: ', program.args); | ||
|
||
// Try the following: | ||
// node options-variadic.js -n 1 2 3 --letter a b c | ||
// node options-variadic.js --letter=A -n80 operand | ||
// node options-variadic.js --letter -n 1 -n 2 3 -- operand |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
const commander = require('../'); | ||
|
||
describe('variadic option with required value', () => { | ||
test('when variadic with value missing then error', () => { | ||
// Optional. Use internal knowledge to suppress output to keep test output clean. | ||
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => { }); | ||
|
||
const program = new commander.Command(); | ||
program | ||
.exitOverride() | ||
.option('-r,--required <value...>'); | ||
|
||
expect(() => { | ||
program.parse(['--required'], { from: 'user' }); | ||
}).toThrow(); | ||
|
||
consoleErrorSpy.mockRestore(); | ||
}); | ||
|
||
test('when variadic with one value then set in array', () => { | ||
const program = new commander.Command(); | ||
program | ||
.option('-r,--required <value...>'); | ||
|
||
program.parse(['--required', 'one'], { from: 'user' }); | ||
expect(program.opts().required).toEqual(['one']); | ||
}); | ||
|
||
test('when variadic with two values then set in array', () => { | ||
const program = new commander.Command(); | ||
program | ||
.option('-r,--required <value...>'); | ||
|
||
program.parse(['--required', 'one', 'two'], { from: 'user' }); | ||
expect(program.opts().required).toEqual(['one', 'two']); | ||
}); | ||
|
||
test('when variadic with repeated values then set in array', () => { | ||
const program = new commander.Command(); | ||
program | ||
.option('-r,--required <value...>'); | ||
|
||
program.parse(['--required', 'one', '--required', 'two'], { from: 'user' }); | ||
expect(program.opts().required).toEqual(['one', 'two']); | ||
}); | ||
|
||
test('when variadic with short combined argument then not variadic', () => { | ||
const program = new commander.Command(); | ||
program | ||
.option('-r,--required <value...>') | ||
.arguments('[arg]'); | ||
|
||
program.parse(['-rone', 'operand'], { from: 'user' }); | ||
expect(program.opts().required).toEqual(['one']); | ||
}); | ||
|
||
test('when variadic with long combined argument then not variadic', () => { | ||
const program = new commander.Command(); | ||
program | ||
.option('-r,--required <value...>') | ||
.arguments('[arg]'); | ||
|
||
program.parse(['--required=one', 'operand'], { from: 'user' }); | ||
expect(program.opts().required).toEqual(['one']); | ||
}); | ||
|
||
test('when variadic with value followed by option then option not eaten', () => { | ||
const program = new commander.Command(); | ||
program | ||
.option('-r,--required <value...>') | ||
.option('-f, --flag') | ||
.arguments('[arg]'); | ||
|
||
program.parse(['-r', 'one', '-f'], { from: 'user' }); | ||
const opts = program.opts(); | ||
expect(opts.required).toEqual(['one']); | ||
expect(opts.flag).toBe(true); | ||
}); | ||
|
||
test('when variadic with no value and default then set to default', () => { | ||
const program = new commander.Command(); | ||
program | ||
.option('-r,--required <value...>', 'variadic description', 'default'); | ||
|
||
program.parse([], { from: 'user' }); | ||
expect(program.opts().required).toEqual('default'); | ||
}); | ||
|
||
test('when variadic with coercion then coercion sets value', () => { | ||
const program = new commander.Command(); | ||
program | ||
.option('-r,--required <value...>', 'variadic description', parseFloat); | ||
|
||
// variadic processing reads the multiple values, but up to custom coercion what it does. | ||
program.parse(['--required', '1e2', '1e3'], { from: 'user' }); | ||
expect(program.opts().required).toEqual(1000); | ||
}); | ||
}); | ||
|
||
// Not retesting everything, but do some tests on variadic with optional | ||
describe('variadic option with optional value', () => { | ||
test('when variadic not specified then value undefined', () => { | ||
const program = new commander.Command(); | ||
program | ||
.option('-o,--optional [value...]'); | ||
|
||
program.parse([], { from: 'user' }); | ||
expect(program.opts().optional).toBeUndefined(); | ||
}); | ||
|
||
test('when variadic used as boolean flag then value true', () => { | ||
const program = new commander.Command(); | ||
program | ||
.option('-o,--optional [value...]'); | ||
|
||
program.parse(['--optional'], { from: 'user' }); | ||
expect(program.opts().optional).toBe(true); | ||
}); | ||
|
||
test('when variadic with one value then set in array', () => { | ||
const program = new commander.Command(); | ||
program | ||
.option('-o,--optional [value...]'); | ||
|
||
program.parse(['--optional', 'one'], { from: 'user' }); | ||
expect(program.opts().optional).toEqual(['one']); | ||
}); | ||
|
||
test('when variadic with two values then set in array', () => { | ||
const program = new commander.Command(); | ||
program | ||
.option('-o,--optional [value...]'); | ||
|
||
program.parse(['--optional', 'one', 'two'], { from: 'user' }); | ||
expect(program.opts().optional).toEqual(['one', 'two']); | ||
}); | ||
}); | ||
|
||
describe('variadic special cases', () => { | ||
test('when option flags has word character before dots then is variadic', () => { | ||
const program = new commander.Command(); | ||
program | ||
.option('-c,--comma [value...]'); | ||
|
||
expect(program.options[0].variadic).toBeTruthy(); | ||
}); | ||
|
||
test('when option flags has special characters before dots then not variadic', () => { | ||
// This might be used to describe coercion for comma separated values, and is not variadic. | ||
const program = new commander.Command(); | ||
program | ||
.option('-c,--comma [value,...]'); | ||
|
||
expect(program.options[0].variadic).toBeFalsy(); | ||
}); | ||
}); |