Skip to content

Commit e2670f4

Browse files
authored
Make new excess arguments error opt-in (#1429)
* Make allowExcessArguments opt-in (again) and inherited configuration * Remove stale JSDoc * Update documentation for allowExcessArguments being opt-in * Make comment more specific about what is being checked for excess arguments * Rework example class override
1 parent 8ac84ec commit e2670f4

File tree

6 files changed

+42
-66
lines changed

6 files changed

+42
-66
lines changed

CHANGELOG.md

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
1212

1313
### Added
1414

15-
- *Breaking:* error message if there are too many command-arguments on command line for the action handler ([#1409])
16-
- if should be allowed then declare extra arguments, or use `.allowExcessArguments()`
15+
- `.allowExcessArguments(false)` to show an error message if there are too many command-arguments on command line for the action handler ([#1409])
1716
- `.configureOutput()` to modify use of stdout and stderr or customise display of errors ([#1387])
1817
- use `.addHelpText()` to add text before or after the built-in help, for just current command or also for all subcommands ([#1296])
1918
- enhance Option class ([#1331])
@@ -120,32 +119,6 @@ program
120119
});
121120
```
122121

123-
**excess command-arguments**
124-
125-
There is now an error if there are too many command-arguments on the command line (only checked if there is an action handler).
126-
If the extra arguments are supported by your command then you can either declare the expected arguments, or allow excess arguments.
127-
128-
```js
129-
// Old code before Commander 7
130-
program
131-
.action(() => {});
132-
program.parse(['a', 'b', 'c'], { from: 'user' }); // now causes an error
133-
```
134-
135-
```js
136-
// New code, declare arguments
137-
program
138-
.arguments('[args...]')
139-
.action(() => {});
140-
```
141-
142-
```js
143-
// New code, allow excess arguments
144-
program
145-
.allowExcessArguments()
146-
.action(() => {});
147-
```
148-
149122
## [7.0.0-2] (2020-12-14)
150123

151124
(Released in 7.0.0)

Readme.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,8 @@ async function main() {
483483
}
484484
```
485485
486-
A command's options and arguments on the command line are validated when the command is used. Any unknown options or unexpected command-arguments will be reported as an error, or you can suppress these checks with `.allowUnknownOption()` and `.allowExcessArguments()`.
486+
A command's options and arguments on the command line are validated when the command is used. Any unknown options or missing arguments will be reported as an error. You can suppress the unknown option checks with `.allowUnknownOption()`. By default it is not an error to
487+
pass more arguments than declared, but you can make this an error with `.allowExcessArguments(false)`.
487488
488489
### Stand-alone executable (sub)commands
489490
@@ -715,9 +716,11 @@ program --port=80 arg
715716
program arg --port=80
716717
```
717718
718-
719719
By default the option processing shows an error for an unknown option. To have an unknown option treated as an ordinary command-argument and continue looking for options, use `.allowUnknownOption()`. This lets you mix known and unknown options.
720720
721+
By default the argument processing does not display an error for more command-arguments than expected.
722+
To display an error for excess arguments, use`.allowExcessArguments(false)`.
723+
721724
### Legacy options as properties
722725
723726
Before Commander 7, the option values were stored as properties on the command.

examples/custom-command-class.js

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,47 +4,47 @@
44
const commander = require('../'); // include commander in git clone of commander repo
55

66
// Use a class override to customise the command and its subcommands.
7-
//
8-
// Configuring the command for compatibility with Commander v6 defaults behaviours.
9-
10-
class Command6 extends commander.Command {
11-
constructor(name) {
12-
super(name);
13-
14-
// Revert to Commander v6 behaviours.
15-
this.storeOptionsAsProperties();
16-
this.allowExcessArguments();
17-
}
187

8+
class CommandWithTrace extends commander.Command {
199
createCommand(name) {
20-
return new Command6(name);
10+
const cmd = new CommandWithTrace(name);
11+
// Add an option to subcommands created using `.command()`
12+
cmd.option('-t, --trace', 'display extra information when run command');
13+
return cmd;
2114
}
2215
};
2316

24-
function inspectCommand(command, optionName) {
17+
function inpectCommand(command) {
2518
// The option value is stored as property on command because we called .storeOptionsAsProperties()
26-
console.log(`Inspecting '${command.name()}'`);
27-
console.log(`option '${optionName}': ${command[optionName]}`);
19+
console.log(`Called '${command.name()}'`);
2820
console.log(`args: ${command.args}`);
21+
console.log('opts: %o', command.opts());
2922
};
3023

31-
const program = new Command6('program')
32-
.option('-p, --port <number>')
33-
.action(() => {
34-
inspectCommand(program, 'port');
24+
const program = new CommandWithTrace('program')
25+
.option('-v, ---verbose')
26+
.action((options, command) => {
27+
inpectCommand(command);
28+
});
29+
30+
program
31+
.command('serve [params...]')
32+
.option('-p, --port <number>', 'port number')
33+
.action((params, options, command) => {
34+
inpectCommand(command);
3535
});
3636

3737
program
38-
.command('sub')
39-
.option('-d, --debug')
40-
.action((options, command) => {
41-
inspectCommand(command, 'debug');
38+
.command('build <target>')
39+
.action((buildTarget, options, command) => {
40+
inpectCommand(command);
4241
});
4342

4443
program.parse();
4544

46-
// We can pass excess arguments without an error as we called .allowExcessArguments()
47-
//
4845
// Try the following:
49-
// node custom-command-class.js --port 80 extra arguments
50-
// node custom-command-class.js sub --debug extra arguments
46+
// node custom-command-class.js --help
47+
// node custom-command-class.js serve --help
48+
// node custom-command-class.js serve -t -p 80 a b c
49+
// node custom-command-class.js build --help
50+
// node custom-command-class.js build --trace foo

index.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,7 @@ class Command extends EventEmitter {
535535
this.options = [];
536536
this.parent = null;
537537
this._allowUnknownOption = false;
538-
this._allowExcessArguments = false;
538+
this._allowExcessArguments = true;
539539
this._args = [];
540540
this.rawArgs = null;
541541
this._scriptPath = null;
@@ -635,6 +635,7 @@ class Command extends EventEmitter {
635635
cmd._exitCallback = this._exitCallback;
636636
cmd._storeOptionsAsProperties = this._storeOptionsAsProperties;
637637
cmd._combineFlagAndOptionalValue = this._combineFlagAndOptionalValue;
638+
cmd._allowExcessArguments = this._allowExcessArguments;
638639
cmd._enablePositionalOptions = this._enablePositionalOptions;
639640

640641
cmd._executableFile = opts.executableFile || null; // Custom name for executable file, set missing to null to match constructor
@@ -1126,7 +1127,7 @@ class Command extends EventEmitter {
11261127
};
11271128

11281129
/**
1129-
* Allow excess arguments on the command line.
1130+
* Allow excess command-arguments on the command line. Pass false to make excess arguments an error.
11301131
*
11311132
* @param {Boolean} [allowExcess=true] - if `true` or omitted, no error will be thrown
11321133
* for excess arguments.
@@ -1724,10 +1725,9 @@ class Command extends EventEmitter {
17241725
};
17251726

17261727
/**
1727-
* `Option` is missing an argument, but received `flag` or nothing.
1728+
* `Option` is missing an argument.
17281729
*
17291730
* @param {Option} option
1730-
* @param {string} [flag]
17311731
* @api private
17321732
*/
17331733

tests/command.allowExcessArguments.test.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@ describe('allowUnknownOption', () => {
1818
writeErrorSpy.mockRestore();
1919
});
2020

21-
test('when specify excess program argument then error by default', () => {
21+
test('when specify excess program argument then no error by default', () => {
2222
const program = new commander.Command();
2323
program
2424
.exitOverride()
2525
.action(() => {});
2626

2727
expect(() => {
2828
program.parse(['excess'], { from: 'user' });
29-
}).toThrow();
29+
}).not.toThrow();
3030
});
3131

3232
test('when specify excess program argument and allowExcessArguments(false) then error', () => {
@@ -65,7 +65,7 @@ describe('allowUnknownOption', () => {
6565
}).not.toThrow();
6666
});
6767

68-
test('when specify excess command argument then error (by default)', () => {
68+
test('when specify excess command argument then no error (by default)', () => {
6969
const program = new commander.Command();
7070
program
7171
.exitOverride()
@@ -74,7 +74,7 @@ describe('allowUnknownOption', () => {
7474

7575
expect(() => {
7676
program.parse(['sub', 'excess'], { from: 'user' });
77-
}).toThrow();
77+
}).not.toThrow();
7878
});
7979

8080
test('when specify excess command argument and allowExcessArguments(false) then error', () => {

typings/index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ declare namespace commander {
402402
allowUnknownOption(allowUnknown?: boolean): this;
403403

404404
/**
405-
* Allow excess arguments on the command line.
405+
* Allow excess command-arguments on the command line. Pass false to make excess arguments an error.
406406
*
407407
* @returns `this` command for chaining
408408
*/

0 commit comments

Comments
 (0)