commander 7.0.0-1 → 7.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Readme.md CHANGED
@@ -23,7 +23,7 @@ Read this in other languages: English | [简体中文](./Readme_zh-CN.md)
23
23
  - [Custom option processing](#custom-option-processing)
24
24
  - [Commands](#commands)
25
25
  - [Specify the argument syntax](#specify-the-argument-syntax)
26
- - [Action handler (sub)commands](#action-handler-subcommands)
26
+ - [Action handler](#action-handler)
27
27
  - [Stand-alone executable (sub)commands](#stand-alone-executable-subcommands)
28
28
  - [Automated help](#automated-help)
29
29
  - [Custom help](#custom-help)
@@ -35,10 +35,10 @@ Read this in other languages: English | [简体中文](./Readme_zh-CN.md)
35
35
  - [Custom event listeners](#custom-event-listeners)
36
36
  - [Bits and pieces](#bits-and-pieces)
37
37
  - [.parse() and .parseAsync()](#parse-and-parseasync)
38
- - [Avoiding option name clashes](#avoiding-option-name-clashes)
38
+ - [Parsing Configuration](#parsing-configuration)
39
+ - [Legacy options as properties](#legacy-options-as-properties)
39
40
  - [TypeScript](#typescript)
40
41
  - [createCommand()](#createcommand)
41
- - [Import into ECMAScript Module](#import-into-ecmascript-module)
42
42
  - [Node options such as `--harmony`](#node-options-such-as---harmony)
43
43
  - [Debugging stand-alone executable subcommands](#debugging-stand-alone-executable-subcommands)
44
44
  - [Override exit and output handling](#override-exit-and-output-handling)
@@ -73,18 +73,35 @@ const program = new Command();
73
73
  program.version('0.0.1');
74
74
  ```
75
75
 
76
+ For named imports in ECMAScript modules, import from `commander/esm.mjs`.
77
+
78
+ ```js
79
+ // index.mjs
80
+ import { Command } from 'commander/esm.mjs';
81
+ const program = new Command();
82
+ ```
83
+
84
+ And in TypeScript:
85
+
86
+ ```ts
87
+ // index.ts
88
+ import { Command } from 'commander';
89
+ const program = new Command();
90
+ ```
91
+
92
+
76
93
  ## Options
77
94
 
78
95
  Options are defined with the `.option()` method, also serving as documentation for the options. Each option can have a short flag (single character) and a long name, separated by a comma or space or vertical bar ('|').
79
96
 
80
- The options can be accessed as properties on the Command object. Multi-word options such as "--template-engine" are camel-cased, becoming `program.templateEngine` etc. See also optional new behaviour to [avoid name clashes](#avoiding-option-name-clashes).
97
+ The parsed options can be accessed by calling `.opts()` on a `Command` object, and are passed to the action handler. Multi-word options such as "--template-engine" are camel-cased, becoming `program.opts().templateEngine` etc.
81
98
 
82
99
  Multiple short flags may optionally be combined in a single argument following the dash: boolean flags, followed by a single option taking a value (possibly followed by the value).
83
100
  For example `-a -b -p 80` may be written as `-ab -p80` or even `-abp80`.
84
101
 
85
102
  You can use `--` to indicate the end of the options, and any remaining arguments will be used without being interpreted.
86
103
 
87
- Options on the command line are not positional, and can be specified before or after other arguments.
104
+ By default options on the command line are not positional, and can be specified before or after other arguments.
88
105
 
89
106
  ### Common option types, boolean and value
90
107
 
@@ -101,10 +118,11 @@ program
101
118
 
102
119
  program.parse(process.argv);
103
120
 
104
- if (program.debug) console.log(program.opts());
121
+ const options = program.opts();
122
+ if (options.debug) console.log(options);
105
123
  console.log('pizza details:');
106
- if (program.small) console.log('- small pizza size');
107
- if (program.pizzaType) console.log(`- ${program.pizzaType}`);
124
+ if (options.small) console.log('- small pizza size');
125
+ if (options.pizzaType) console.log(`- ${options.pizzaType}`);
108
126
  ```
109
127
 
110
128
  ```bash
@@ -123,7 +141,7 @@ pizza details:
123
141
  - cheese
124
142
  ```
125
143
 
126
- `program.parse(arguments)` processes the arguments, leaving any args not consumed by the program options in the `program.args` array.
144
+ `program.parse(arguments)` processes the arguments, leaving any args not consumed by the program options in the `program.args` array. The parameter is optional and defaults to `process.argv`.
127
145
 
128
146
  ### Default option value
129
147
 
@@ -135,9 +153,9 @@ Example file: [options-defaults.js](./examples/options-defaults.js)
135
153
  program
136
154
  .option('-c, --cheese <type>', 'add the specified type of cheese', 'blue');
137
155
 
138
- program.parse(process.argv);
156
+ program.parse();
139
157
 
140
- console.log(`cheese: ${program.cheese}`);
158
+ console.log(`cheese: ${program.opts().cheese}`);
141
159
  ```
142
160
 
143
161
  ```bash
@@ -162,10 +180,11 @@ program
162
180
  .option('--no-sauce', 'Remove sauce')
163
181
  .option('--cheese <flavour>', 'cheese flavour', 'mozzarella')
164
182
  .option('--no-cheese', 'plain with no cheese')
165
- .parse(process.argv);
183
+ .parse();
166
184
 
167
- const sauceStr = program.sauce ? 'sauce' : 'no sauce';
168
- const cheeseStr = (program.cheese === false) ? 'no cheese' : `${program.cheese} cheese`;
185
+ const options = program.opts();
186
+ const sauceStr = options.sauce ? 'sauce' : 'no sauce';
187
+ const cheeseStr = (options.cheese === false) ? 'no cheese' : `${options.cheese} cheese`;
169
188
  console.log(`You ordered a pizza with ${sauceStr} and ${cheeseStr}`);
170
189
  ```
171
190
 
@@ -191,9 +210,10 @@ program
191
210
 
192
211
  program.parse(process.argv);
193
212
 
194
- if (program.cheese === undefined) console.log('no cheese');
195
- else if (program.cheese === true) console.log('add cheese');
196
- else console.log(`add cheese type ${program.cheese}`);
213
+ const options = program.opts();
214
+ if (options.cheese === undefined) console.log('no cheese');
215
+ else if (options.cheese === true) console.log('add cheese');
216
+ else console.log(`add cheese type ${options.cheese}`);
197
217
  ```
198
218
 
199
219
  ```bash
@@ -217,7 +237,7 @@ Example file: [options-required.js](./examples/options-required.js)
217
237
  program
218
238
  .requiredOption('-c, --cheese <type>', 'pizza must have cheese');
219
239
 
220
- program.parse(process.argv);
240
+ program.parse();
221
241
  ```
222
242
 
223
243
  ```bash
@@ -303,7 +323,7 @@ Options:
303
323
  -h, --help display help for command
304
324
 
305
325
  $ extra --drink huge
306
- error: option '-d, --drink <size>' argument of 'huge' not in allowed choices: small, medium, large
326
+ error: option '-d, --drink <size>' argument 'huge' is invalid. Allowed choices are small, medium, large.
307
327
  ```
308
328
 
309
329
  ### Custom option processing
@@ -319,8 +339,12 @@ Example file: [options-custom-processing.js](./examples/options-custom-processin
319
339
 
320
340
  ```js
321
341
  function myParseInt(value, dummyPrevious) {
322
- // parseInt takes a string and an optional radix
323
- return parseInt(value);
342
+ // parseInt takes a string and a radix
343
+ const parsedValue = parseInt(value, 10);
344
+ if (isNaN(parsedValue)) {
345
+ throw new commander.InvalidOptionArgumentError('Not a number.');
346
+ }
347
+ return parsedValue;
324
348
  }
325
349
 
326
350
  function increaseVerbosity(dummyValue, previous) {
@@ -343,13 +367,14 @@ program
343
367
  .option('-l, --list <items>', 'comma separated list', commaSeparatedList)
344
368
  ;
345
369
 
346
- program.parse(process.argv);
370
+ program.parse();
347
371
 
348
- if (program.float !== undefined) console.log(`float: ${program.float}`);
349
- if (program.integer !== undefined) console.log(`integer: ${program.integer}`);
350
- if (program.verbose > 0) console.log(`verbosity: ${program.verbose}`);
351
- if (program.collect.length > 0) console.log(program.collect);
352
- if (program.list !== undefined) console.log(program.list);
372
+ const options = program.opts();
373
+ if (options.float !== undefined) console.log(`float: ${options.float}`);
374
+ if (options.integer !== undefined) console.log(`integer: ${options.integer}`);
375
+ if (options.verbose > 0) console.log(`verbosity: ${options.verbose}`);
376
+ if (options.collect.length > 0) console.log(options.collect);
377
+ if (options.list !== undefined) console.log(options.list);
353
378
  ```
354
379
 
355
380
  ```bash
@@ -408,64 +433,57 @@ included in the `.command` call. Angled brackets (e.g. `<required>`) indicate re
408
433
  Square brackets (e.g. `[optional]`) indicate optional command-arguments.
409
434
  You can optionally describe the arguments in the help by supplying a hash as second parameter to `.description()`.
410
435
 
411
- Example file: [env](./examples/env)
436
+ Example file: [arguments.js](./examples/arguments.js)
412
437
 
413
438
  ```js
414
439
  program
415
440
  .version('0.1.0')
416
- .arguments('<cmd> [env]')
441
+ .arguments('<username> [password]')
417
442
  .description('test command', {
418
- cmd: 'command to run',
419
- env: 'environment to run test in'
443
+ username: 'user to login',
444
+ password: 'password for user, if required'
420
445
  })
421
- .action(function (cmd, env) {
422
- console.log('command:', cmd);
423
- console.log('environment:', env || 'no environment given');
446
+ .action((username, password) => {
447
+ console.log('username:', username);
448
+ console.log('environment:', password || 'no password given');
424
449
  });
425
-
426
- program.parse(process.argv);
427
450
  ```
428
451
 
429
452
  The last argument of a command can be variadic, and only the last argument. To make an argument variadic you
430
453
  append `...` to the argument name. For example:
431
454
 
432
455
  ```js
433
- const { program } = require('commander');
434
-
435
456
  program
436
457
  .version('0.1.0')
437
- .command('rmdir <dir> [otherDirs...]')
438
- .action(function (dir, otherDirs) {
439
- console.log('rmdir %s', dir);
440
- if (otherDirs) {
441
- otherDirs.forEach(function (oDir) {
442
- console.log('rmdir %s', oDir);
443
- });
444
- }
458
+ .command('rmdir <dirs...>')
459
+ .action(function (dirs) {
460
+ dirs.forEach((dir) => {
461
+ console.log('rmdir %s', dir);
462
+ });
445
463
  });
446
-
447
- program.parse(process.argv);
448
464
  ```
449
465
 
450
466
  The variadic argument is passed to the action handler as an array.
451
467
 
452
- ### Action handler (sub)commands
468
+ ### Action handler
453
469
 
454
- You can add options to a command that uses an action handler.
455
- The action handler gets passed a parameter for each argument you declared, and one additional argument which is the
456
- command object itself. This command argument has the values for the command-specific options added as properties.
470
+ The action handler gets passed a parameter for each command-argument you declared, and two additional parameters
471
+ which are the parsed options and the command object itself.
457
472
 
458
- ```js
459
- const { program } = require('commander');
473
+ Example file: [thank.js](./examples/thank.js)
460
474
 
475
+ ```js
461
476
  program
462
- .command('rm <dir>')
463
- .option('-r, --recursive', 'Remove recursively')
464
- .action(function (dir, cmdObj) {
465
- console.log('remove ' + dir + (cmdObj.recursive ? ' recursively' : ''))
466
- })
467
-
468
- program.parse(process.argv)
477
+ .arguments('<name>')
478
+ .option('-t, --title <honorific>', 'title to use before name')
479
+ .option('-d, --debug', 'display some debugging')
480
+ .action((name, options, command) => {
481
+ if (options.debug) {
482
+ console.error('Called %s with options %o', command.name(), options);
483
+ }
484
+ const title = options.title ? `${options.title} ` : '';
485
+ console.log(`Thank-you ${title}${name}`);
486
+ });
469
487
  ```
470
488
 
471
489
  You may supply an `async` action handler, in which case you call `.parseAsync` rather than `.parse`.
@@ -481,7 +499,8 @@ async function main() {
481
499
  }
482
500
  ```
483
501
 
484
- A command's options on the command line are validated when the command is used. Any unknown options will be reported as an error.
502
+ 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
503
+ pass more arguments than declared, but you can make this an error with `.allowExcessArguments(false)`.
485
504
 
486
505
  ### Stand-alone executable (sub)commands
487
506
 
@@ -517,10 +536,9 @@ Example file: [pizza](./examples/pizza)
517
536
  $ node ./examples/pizza --help
518
537
  Usage: pizza [options]
519
538
 
520
- An application for pizzas ordering
539
+ An application for pizza ordering
521
540
 
522
541
  Options:
523
- -V, --version output the version number
524
542
  -p, --peppers Add peppers
525
543
  -c, --cheese <type> Add the specified type of cheese (default: "marble")
526
544
  -C, --no-cheese You do not want any cheese
@@ -653,7 +671,7 @@ You can execute custom actions by listening to command and option events.
653
671
 
654
672
  ```js
655
673
  program.on('option:verbose', function () {
656
- process.env.VERBOSE = this.verbose;
674
+ process.env.VERBOSE = this.opts().verbose;
657
675
  });
658
676
 
659
677
  program.on('command:*', function (operands) {
@@ -684,47 +702,59 @@ program.parse(); // Implicit, and auto-detect electron
684
702
  program.parse(['-f', 'filename'], { from: 'user' });
685
703
  ```
686
704
 
687
- ### Avoiding option name clashes
705
+ ### Parsing Configuration
688
706
 
689
- The original and default behaviour is that the option values are stored
690
- as properties on the program, and the action handler is passed a
691
- command object with the options values stored as properties.
692
- This is very convenient to code, but the downside is possible clashes with
693
- existing properties of Command.
707
+ If the default parsing does not suit your needs, there are some behaviours to support other usage patterns.
694
708
 
695
- There are two new routines to change the behaviour, and the default behaviour may change in the future:
709
+ By default program options are recognised before and after subcommands. To only look for program options before subcommands, use `.enablePositionalOptions()`. This lets you use
710
+ an option for a different purpose in subcommands.
696
711
 
697
- - `storeOptionsAsProperties`: whether to store option values as properties on command object, or store separately (specify false) and access using `.opts()`
698
- - `passCommandToAction`: whether to pass command to action handler,
699
- or just the options (specify false)
712
+ Example file: [positional-options.js](./examples/positional-options.js)
700
713
 
701
- Example file: [storeOptionsAsProperties-action.js](./examples/storeOptionsAsProperties-action.js)
714
+ With positional options, the `-b` is a program option in the first line and a subcommand option in the second line:
702
715
 
703
- ```js
704
- program
705
- .storeOptionsAsProperties(false)
706
- .passCommandToAction(false);
716
+ ```sh
717
+ program -b subcommand
718
+ program subcommand -b
719
+ ```
707
720
 
708
- program
709
- .name('my-program-name')
710
- .option('-n,--name <name>');
721
+ By default options are recognised before and after command-arguments. To only process options that come
722
+ before the command-arguments, use `.passThroughOptions()`. This lets you pass the arguments and following options through to another program
723
+ without needing to use `--` to end the option processing.
724
+ To use pass through options in a subcommand, the program needs to enable positional options.
711
725
 
712
- program
713
- .command('show')
714
- .option('-a,--action <action>')
715
- .action((options) => {
716
- console.log(options.action);
717
- });
726
+ Example file: [pass-through-options.js](./examples/pass-through-options.js)
718
727
 
719
- program.parse(process.argv);
728
+ With pass through options, the `--port=80` is a program option in the first line and passed through as a command-argument in the second line:
720
729
 
721
- const programOptions = program.opts();
722
- console.log(programOptions.name);
730
+ ```sh
731
+ program --port=80 arg
732
+ program arg --port=80
723
733
  ```
724
734
 
725
- ### TypeScript
735
+ 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.
736
+
737
+ By default the argument processing does not display an error for more command-arguments than expected.
738
+ To display an error for excess arguments, use`.allowExcessArguments(false)`.
739
+
740
+ ### Legacy options as properties
741
+
742
+ Before Commander 7, the option values were stored as properties on the command.
743
+ This was convenient to code but the downside was possible clashes with
744
+ existing properties of `Command`. You can revert to the old behaviour to run unmodified legacy code by using `.storeOptionsAsProperties()`.
745
+
746
+ ```js
747
+ program
748
+ .storeOptionsAsProperties()
749
+ .option('-d, --debug')
750
+ .action((commandAndOptions) => {
751
+ if (commandAndOptions.debug) {
752
+ console.error(`Called ${commandAndOptions.name()}`);
753
+ }
754
+ });
755
+ ```
726
756
 
727
- The Commander package includes its TypeScript Definition file.
757
+ ### TypeScript
728
758
 
729
759
  If you use `ts-node` and stand-alone executable subcommands written as `.ts` files, you need to call your program through node to get the subcommands called correctly. e.g.
730
760
 
@@ -743,18 +773,7 @@ const program = createCommand();
743
773
 
744
774
  `createCommand` is also a method of the Command object, and creates a new command rather than a subcommand. This gets used internally
745
775
  when creating subcommands using `.command()`, and you may override it to
746
- customise the new subcommand (examples using [subclass](./examples/custom-command-class.js) and [function](./examples/custom-command-function.js)).
747
-
748
- ### Import into ECMAScript Module
749
-
750
- Commander is currently a CommonJS package, and the default export can be imported into an ES Module:
751
-
752
- ```js
753
- // index.mjs
754
- import commander from 'commander';
755
- const program = commander.program;
756
- const newCommand = new commander.Command();
757
- ```
776
+ customise the new subcommand (example file [custom-command-class.js](./examples/custom-command-class.js)).
758
777
 
759
778
  ### Node options such as `--harmony`
760
779
 
@@ -821,49 +840,73 @@ There is more information available about:
821
840
 
822
841
  ## Examples
823
842
 
824
- Example file: [deploy](./examples/deploy)
843
+ In a single command program, you might not need an action handler.
844
+
845
+ Example file: [pizza](./examples/pizza)
825
846
 
826
847
  ```js
827
848
  const { program } = require('commander');
828
849
 
829
850
  program
830
- .version('0.1.0')
831
- .option('-C, --chdir <path>', 'change the working directory')
832
- .option('-c, --config <path>', 'set config path. defaults to ./deploy.conf')
833
- .option('-T, --no-tests', 'ignore test hook');
851
+ .description('An application for pizza ordering')
852
+ .option('-p, --peppers', 'Add peppers')
853
+ .option('-c, --cheese <type>', 'Add the specified type of cheese', 'marble')
854
+ .option('-C, --no-cheese', 'You do not want any cheese');
855
+
856
+ program.parse();
857
+
858
+ const options = program.opts();
859
+ console.log('you ordered a pizza with:');
860
+ if (options.peppers) console.log(' - peppers');
861
+ const cheese = !options.cheese ? 'no' : options.cheese;
862
+ console.log(' - %s cheese', cheese);
863
+ ```
864
+
865
+ In a multi-command program, you will have action handlers for each command (or stand-alone executables for the commands).
866
+
867
+ Example file: [deploy](./examples/deploy)
868
+
869
+ ```js
870
+ const { Command } = require('commander');
871
+ const program = new Command();
872
+
873
+ program
874
+ .version('0.0.1')
875
+ .option('-c, --config <path>', 'set config path', './deploy.conf');
834
876
 
835
877
  program
836
878
  .command('setup [env]')
837
879
  .description('run setup commands for all envs')
838
- .option("-s, --setup_mode [mode]", "Which setup mode to use")
839
- .action(function(env, options){
840
- const mode = options.setup_mode || "normal";
880
+ .option('-s, --setup_mode <mode>', 'Which setup mode to use', 'normal')
881
+ .action((env, options) => {
841
882
  env = env || 'all';
842
- console.log('setup for %s env(s) with %s mode', env, mode);
883
+ console.log('read config from %s', program.opts().config);
884
+ console.log('setup for %s env(s) with %s mode', env, options.setup_mode);
843
885
  });
844
886
 
845
887
  program
846
- .command('exec <cmd>')
888
+ .command('exec <script>')
847
889
  .alias('ex')
848
890
  .description('execute the given remote cmd')
849
- .option("-e, --exec_mode <mode>", "Which exec mode to use")
850
- .action(function(cmd, options){
851
- console.log('exec "%s" using %s mode', cmd, options.exec_mode);
891
+ .option('-e, --exec_mode <mode>', 'Which exec mode to use', 'fast')
892
+ .action((script, options) => {
893
+ console.log('read config from %s', program.opts().config);
894
+ console.log('exec "%s" using %s mode and config %s', script, options.exec_mode, program.opts().config);
852
895
  }).addHelpText('after', `
853
896
  Examples:
854
897
  $ deploy exec sequential
855
898
  $ deploy exec async`
856
899
  );
857
-
900
+
858
901
  program.parse(process.argv);
859
902
  ```
860
903
 
861
- More Demos can be found in the [examples](https://github.com/tj/commander.js/tree/master/examples) directory.
904
+ More samples can be found in the [examples](https://github.com/tj/commander.js/tree/master/examples) directory.
862
905
 
863
906
  ## Support
864
907
 
865
- The current version of Commander is fully supported on Long Term Support versions of Node, and is likely to work with Node 6 but not tested.
866
- (For versions of Node below Node 6, use Commander 3.x or 2.x.)
908
+ The current version of Commander is fully supported on Long Term Support versions of node, and requires at least node v10.
909
+ (For older versions of node, use an older version of Commander. Commander version 2.x has the widest support.)
867
910
 
868
911
  The main forum for free and community support is the project [Issues](https://github.com/tj/commander.js/issues) on GitHub.
869
912
 
package/esm.mjs ADDED
@@ -0,0 +1,4 @@
1
+ import commander from './index.js';
2
+
3
+ // wrapper to provide named exports for ESM.
4
+ export const { program, Option, Command, CommanderError, InvalidOptionArgumentError, Help, createCommand } = commander;