commander 2.20.3 → 3.0.2

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/index.js CHANGED
@@ -45,7 +45,7 @@ function Option(flags, description) {
45
45
  this.flags = flags;
46
46
  this.required = flags.indexOf('<') >= 0;
47
47
  this.optional = flags.indexOf('[') >= 0;
48
- this.bool = flags.indexOf('-no-') === -1;
48
+ this.negate = flags.indexOf('-no-') !== -1;
49
49
  flags = flags.split(/[ ,|]+/);
50
50
  if (flags.length > 1 && !/^[[<]/.test(flags[1])) this.short = flags.shift();
51
51
  this.long = flags.shift();
@@ -60,9 +60,7 @@ function Option(flags, description) {
60
60
  */
61
61
 
62
62
  Option.prototype.name = function() {
63
- return this.long
64
- .replace('--', '')
65
- .replace('no-', '');
63
+ return this.long.replace(/^--/, '');
66
64
  };
67
65
 
68
66
  /**
@@ -74,7 +72,7 @@ Option.prototype.name = function() {
74
72
  */
75
73
 
76
74
  Option.prototype.attributeName = function() {
77
- return camelcase(this.name());
75
+ return camelcase(this.name().replace(/^no-/, ''));
78
76
  };
79
77
 
80
78
  /**
@@ -99,89 +97,67 @@ Option.prototype.is = function(arg) {
99
97
  function Command(name) {
100
98
  this.commands = [];
101
99
  this.options = [];
102
- this._execs = {};
100
+ this._execs = new Set();
103
101
  this._allowUnknownOption = false;
104
102
  this._args = [];
105
103
  this._name = name || '';
104
+
105
+ this._helpFlags = '-h, --help';
106
+ this._helpDescription = 'output usage information';
107
+ this._helpShortFlag = '-h';
108
+ this._helpLongFlag = '--help';
106
109
  }
107
110
 
108
111
  /**
109
- * Add command `name`.
110
- *
111
- * The `.action()` callback is invoked when the
112
- * command `name` is specified via __ARGV__,
113
- * and the remaining arguments are applied to the
114
- * function for access.
112
+ * Define a command.
115
113
  *
116
- * When the `name` is "*" an un-matched command
117
- * will be passed as the first arg, followed by
118
- * the rest of __ARGV__ remaining.
114
+ * There are two styles of command: pay attention to where to put the description.
119
115
  *
120
116
  * Examples:
121
117
  *
118
+ * // Command implemented using action handler (description is supplied separately to `.command`)
122
119
  * program
123
- * .version('0.0.1')
124
- * .option('-C, --chdir <path>', 'change the working directory')
125
- * .option('-c, --config <path>', 'set config path. defaults to ./deploy.conf')
126
- * .option('-T, --no-tests', 'ignore test hook')
127
- *
128
- * program
129
- * .command('setup')
130
- * .description('run remote setup commands')
131
- * .action(function() {
132
- * console.log('setup');
133
- * });
134
- *
135
- * program
136
- * .command('exec <cmd>')
137
- * .description('run the given remote command')
138
- * .action(function(cmd) {
139
- * console.log('exec "%s"', cmd);
120
+ * .command('clone <source> [destination]')
121
+ * .description('clone a repository into a newly created directory')
122
+ * .action((source, destination) => {
123
+ * console.log('clone command called');
140
124
  * });
141
125
  *
126
+ * // Command implemented using separate executable file (description is second parameter to `.command`)
142
127
  * program
143
- * .command('teardown <dir> [otherDirs...]')
144
- * .description('run teardown commands')
145
- * .action(function(dir, otherDirs) {
146
- * console.log('dir "%s"', dir);
147
- * if (otherDirs) {
148
- * otherDirs.forEach(function (oDir) {
149
- * console.log('dir "%s"', oDir);
150
- * });
151
- * }
152
- * });
128
+ * .command('start <service>', 'start named service')
129
+ * .command('stop [service]', 'stop named serice, or all if no name supplied');
153
130
  *
154
- * program
155
- * .command('*')
156
- * .description('deploy the given env')
157
- * .action(function(env) {
158
- * console.log('deploying "%s"', env);
159
- * });
160
- *
161
- * program.parse(process.argv);
162
- *
163
- * @param {String} name
164
- * @param {String} [desc] for git-style sub-commands
165
- * @return {Command} the new command
131
+ * @param {string} nameAndArgs - command name and arguments, args are `<required>` or `[optional]` and last may also be `variadic...`
132
+ * @param {Object|string} [actionOptsOrExecDesc] - configuration options (for action), or description (for executable)
133
+ * @param {Object} [execOpts] - configuration options (for executable)
134
+ * @return {Command} returns new command for action handler, or top-level command for executable command
166
135
  * @api public
167
136
  */
168
137
 
169
- Command.prototype.command = function(name, desc, opts) {
138
+ Command.prototype.command = function(nameAndArgs, actionOptsOrExecDesc, execOpts) {
139
+ var desc = actionOptsOrExecDesc;
140
+ var opts = execOpts;
170
141
  if (typeof desc === 'object' && desc !== null) {
171
142
  opts = desc;
172
143
  desc = null;
173
144
  }
174
145
  opts = opts || {};
175
- var args = name.split(/ +/);
146
+ var args = nameAndArgs.split(/ +/);
176
147
  var cmd = new Command(args.shift());
177
148
 
178
149
  if (desc) {
179
150
  cmd.description(desc);
180
151
  this.executables = true;
181
- this._execs[cmd._name] = true;
152
+ this._execs.add(cmd._name);
182
153
  if (opts.isDefault) this.defaultExecutable = cmd._name;
183
154
  }
184
155
  cmd._noHelp = !!opts.noHelp;
156
+ cmd._helpFlags = this._helpFlags;
157
+ cmd._helpDescription = this._helpDescription;
158
+ cmd._helpShortFlag = this._helpShortFlag;
159
+ cmd._helpLongFlag = this._helpLongFlag;
160
+ cmd._executableFile = opts.executableFile; // Custom name for executable file
185
161
  this.commands.push(cmd);
186
162
  cmd.parseExpectedArgs(args);
187
163
  cmd.parent = this;
@@ -335,14 +311,17 @@ Command.prototype.action = function(fn) {
335
311
  *
336
312
  * Examples:
337
313
  *
338
- * // simple boolean defaulting to false
314
+ * // simple boolean defaulting to undefined
339
315
  * program.option('-p, --pepper', 'add pepper');
340
316
  *
317
+ * program.pepper
318
+ * // => undefined
319
+ *
341
320
  * --pepper
342
321
  * program.pepper
343
- * // => Boolean
322
+ * // => true
344
323
  *
345
- * // simple boolean defaulting to true
324
+ * // simple boolean defaulting to true (unless non-negated option is also defined)
346
325
  * program.option('-C, --no-cheese', 'remove cheese');
347
326
  *
348
327
  * program.cheese
@@ -379,6 +358,8 @@ Command.prototype.option = function(flags, description, fn, defaultValue) {
379
358
  // default as 3rd arg
380
359
  if (typeof fn !== 'function') {
381
360
  if (fn instanceof RegExp) {
361
+ // This is a bit simplistic (especially no error messages), and probably better handled by caller using custom option processing.
362
+ // No longer documented in README, but still present for backwards compatibility.
382
363
  var regex = fn;
383
364
  fn = function(val, def) {
384
365
  var m = regex.exec(val);
@@ -390,10 +371,13 @@ Command.prototype.option = function(flags, description, fn, defaultValue) {
390
371
  }
391
372
  }
392
373
 
393
- // preassign default value only for --no-*, [optional], or <required>
394
- if (!option.bool || option.optional || option.required) {
395
- // when --no-* we make sure default is true
396
- if (!option.bool) defaultValue = true;
374
+ // preassign default value for --no-*, [optional], <required>, or plain flag if boolean value
375
+ if (option.negate || option.optional || option.required || typeof defaultValue === 'boolean') {
376
+ // when --no-foo we make sure default is true, unless a --foo option is already defined
377
+ if (option.negate) {
378
+ var opts = self.opts();
379
+ defaultValue = Object.prototype.hasOwnProperty.call(opts, name) ? opts[name] : true;
380
+ }
397
381
  // preassign only if we have a default
398
382
  if (defaultValue !== undefined) {
399
383
  self[name] = defaultValue;
@@ -412,19 +396,19 @@ Command.prototype.option = function(flags, description, fn, defaultValue) {
412
396
  val = fn(val, self[name] === undefined ? defaultValue : self[name]);
413
397
  }
414
398
 
415
- // unassigned or bool
399
+ // unassigned or boolean value
416
400
  if (typeof self[name] === 'boolean' || typeof self[name] === 'undefined') {
417
- // if no value, bool true, and we have a default, then use it!
401
+ // if no value, negate false, and we have a default, then use it!
418
402
  if (val == null) {
419
- self[name] = option.bool
420
- ? defaultValue || true
421
- : false;
403
+ self[name] = option.negate
404
+ ? false
405
+ : defaultValue || true;
422
406
  } else {
423
407
  self[name] = val;
424
408
  }
425
409
  } else if (val !== null) {
426
410
  // reassign
427
- self[name] = val;
411
+ self[name] = option.negate ? false : val;
428
412
  }
429
413
  });
430
414
 
@@ -464,36 +448,58 @@ Command.prototype.parse = function(argv) {
464
448
  // github-style sub-commands with no sub-command
465
449
  if (this.executables && argv.length < 3 && !this.defaultExecutable) {
466
450
  // this user needs help
467
- argv.push('--help');
451
+ argv.push(this._helpLongFlag);
468
452
  }
469
453
 
470
454
  // process argv
471
- var parsed = this.parseOptions(this.normalize(argv.slice(2)));
455
+ var normalized = this.normalize(argv.slice(2));
456
+ var parsed = this.parseOptions(normalized);
472
457
  var args = this.args = parsed.args;
473
458
 
474
459
  var result = this.parseArgs(this.args, parsed.unknown);
475
460
 
461
+ if (args[0] === 'help' && args.length === 1) this.help();
462
+
463
+ // <cmd> --help
464
+ if (args[0] === 'help') {
465
+ args[0] = args[1];
466
+ args[1] = this._helpLongFlag;
467
+ }
468
+
476
469
  // executable sub-commands
470
+ // (Debugging note for future: args[0] is not right if an action has been called)
477
471
  var name = result.args[0];
472
+ var subCommand = null;
478
473
 
479
- var aliasCommand = null;
480
- // check alias of sub commands
474
+ // Look for subcommand
481
475
  if (name) {
482
- aliasCommand = this.commands.filter(function(command) {
476
+ subCommand = this.commands.find(function(command) {
477
+ return command._name === name;
478
+ });
479
+ }
480
+
481
+ // Look for alias
482
+ if (!subCommand && name) {
483
+ subCommand = this.commands.find(function(command) {
483
484
  return command.alias() === name;
484
- })[0];
485
+ });
486
+ if (subCommand) {
487
+ name = subCommand._name;
488
+ args[0] = name;
489
+ }
485
490
  }
486
491
 
487
- if (this._execs[name] === true) {
488
- return this.executeSubCommand(argv, args, parsed.unknown);
489
- } else if (aliasCommand) {
490
- // is alias of a subCommand
491
- args[0] = aliasCommand._name;
492
- return this.executeSubCommand(argv, args, parsed.unknown);
493
- } else if (this.defaultExecutable) {
494
- // use the default subcommand
495
- args.unshift(this.defaultExecutable);
496
- return this.executeSubCommand(argv, args, parsed.unknown);
492
+ // Look for default subcommand
493
+ if (!subCommand && this.defaultExecutable) {
494
+ name = this.defaultExecutable;
495
+ args.unshift(name);
496
+ subCommand = this.commands.find(function(command) {
497
+ return command._name === name;
498
+ });
499
+ }
500
+
501
+ if (this._execs.has(name)) {
502
+ return this.executeSubCommand(argv, args, parsed.unknown, subCommand ? subCommand._executableFile : undefined);
497
503
  }
498
504
 
499
505
  return result;
@@ -505,31 +511,33 @@ Command.prototype.parse = function(argv) {
505
511
  * @param {Array} argv
506
512
  * @param {Array} args
507
513
  * @param {Array} unknown
514
+ * @param {String} specifySubcommand
508
515
  * @api private
509
516
  */
510
517
 
511
- Command.prototype.executeSubCommand = function(argv, args, unknown) {
518
+ Command.prototype.executeSubCommand = function(argv, args, unknown, executableFile) {
512
519
  args = args.concat(unknown);
513
520
 
514
521
  if (!args.length) this.help();
515
- if (args[0] === 'help' && args.length === 1) this.help();
516
522
 
517
- // <cmd> --help
518
- if (args[0] === 'help') {
519
- args[0] = args[1];
520
- args[1] = '--help';
521
- }
523
+ var isExplicitJS = false; // Whether to use node to launch "executable"
522
524
 
523
525
  // executable
524
- var f = argv[1];
525
- // name of the subcommand, link `pm-install`
526
- var bin = basename(f, path.extname(f)) + '-' + args[0];
526
+ var pm = argv[1];
527
+ // name of the subcommand, like `pm-install`
528
+ var bin = basename(pm, path.extname(pm)) + '-' + args[0];
529
+ if (executableFile != null) {
530
+ bin = executableFile;
531
+ // Check for same extensions as we scan for below so get consistent launch behaviour.
532
+ var executableExt = path.extname(executableFile);
533
+ isExplicitJS = executableExt === '.js' || executableExt === '.ts' || executableExt === '.mjs';
534
+ }
527
535
 
528
536
  // In case of globally installed, get the base dir where executable
529
537
  // subcommand file should be located at
530
538
  var baseDir;
531
539
 
532
- var resolvedLink = fs.realpathSync(f);
540
+ var resolvedLink = fs.realpathSync(pm);
533
541
 
534
542
  baseDir = dirname(resolvedLink);
535
543
 
@@ -537,13 +545,15 @@ Command.prototype.executeSubCommand = function(argv, args, unknown) {
537
545
  var localBin = path.join(baseDir, bin);
538
546
 
539
547
  // whether bin file is a js script with explicit `.js` or `.ts` extension
540
- var isExplicitJS = false;
541
548
  if (exists(localBin + '.js')) {
542
549
  bin = localBin + '.js';
543
550
  isExplicitJS = true;
544
551
  } else if (exists(localBin + '.ts')) {
545
552
  bin = localBin + '.ts';
546
553
  isExplicitJS = true;
554
+ } else if (exists(localBin + '.mjs')) {
555
+ bin = localBin + '.mjs';
556
+ isExplicitJS = true;
547
557
  } else if (exists(localBin)) {
548
558
  bin = localBin;
549
559
  }
@@ -555,7 +565,7 @@ Command.prototype.executeSubCommand = function(argv, args, unknown) {
555
565
  if (isExplicitJS) {
556
566
  args.unshift(bin);
557
567
  // add executable arguments to spawn
558
- args = (process.execArgv || []).concat(args);
568
+ args = incrementNodeInspectorPort(process.execArgv).concat(args);
559
569
 
560
570
  proc = spawn(process.argv[0], args, { stdio: 'inherit', customFds: [0, 1, 2] });
561
571
  } else {
@@ -563,6 +573,8 @@ Command.prototype.executeSubCommand = function(argv, args, unknown) {
563
573
  }
564
574
  } else {
565
575
  args.unshift(bin);
576
+ // add executable arguments to spawn
577
+ args = incrementNodeInspectorPort(process.execArgv).concat(args);
566
578
  proc = spawn(process.execPath, args, { stdio: 'inherit' });
567
579
  }
568
580
 
@@ -602,7 +614,9 @@ Command.prototype.normalize = function(args) {
602
614
  var ret = [],
603
615
  arg,
604
616
  lastOpt,
605
- index;
617
+ index,
618
+ short,
619
+ opt;
606
620
 
607
621
  for (var i = 0, len = args.length; i < len; ++i) {
608
622
  arg = args[i];
@@ -616,10 +630,17 @@ Command.prototype.normalize = function(args) {
616
630
  break;
617
631
  } else if (lastOpt && lastOpt.required) {
618
632
  ret.push(arg);
619
- } else if (arg.length > 1 && arg[0] === '-' && arg[1] !== '-') {
620
- arg.slice(1).split('').forEach(function(c) {
621
- ret.push('-' + c);
622
- });
633
+ } else if (arg.length > 2 && arg[0] === '-' && arg[1] !== '-') {
634
+ short = arg.slice(0, 2);
635
+ opt = this.optionFor(short);
636
+ if (opt && (opt.required || opt.optional)) {
637
+ ret.push(short);
638
+ ret.push(arg.slice(2));
639
+ } else {
640
+ arg.slice(1).split('').forEach(function(c) {
641
+ ret.push('-' + c);
642
+ });
643
+ }
623
644
  } else if (/^--/.test(arg) && ~(index = arg.indexOf('='))) {
624
645
  ret.push(arg.slice(0, index), arg.slice(index + 1));
625
646
  } else {
@@ -737,7 +758,7 @@ Command.prototype.parseOptions = function(argv) {
737
758
  ++i;
738
759
  }
739
760
  this.emit('option:' + option.name(), arg);
740
- // bool
761
+ // flag
741
762
  } else {
742
763
  this.emit('option:' + option.name());
743
764
  }
@@ -751,7 +772,7 @@ Command.prototype.parseOptions = function(argv) {
751
772
  // If the next argument looks like it might be
752
773
  // an argument for this option, we pass it on.
753
774
  // If it isn't, then it'll simply be ignored
754
- if ((i + 1) < argv.length && argv[i + 1][0] !== '-') {
775
+ if ((i + 1) < argv.length && (argv[i + 1][0] !== '-' || argv[i + 1] === '-')) {
755
776
  unknownOptions.push(argv[++i]);
756
777
  }
757
778
  continue;
@@ -789,7 +810,7 @@ Command.prototype.opts = function() {
789
810
  */
790
811
 
791
812
  Command.prototype.missingArgument = function(name) {
792
- console.error("error: missing required argument `%s'", name);
813
+ console.error("error: missing required argument '%s'", name);
793
814
  process.exit(1);
794
815
  };
795
816
 
@@ -803,9 +824,9 @@ Command.prototype.missingArgument = function(name) {
803
824
 
804
825
  Command.prototype.optionMissingArgument = function(option, flag) {
805
826
  if (flag) {
806
- console.error("error: option `%s' argument missing, got `%s'", option.flags, flag);
827
+ console.error("error: option '%s' argument missing, got '%s'", option.flags, flag);
807
828
  } else {
808
- console.error("error: option `%s' argument missing", option.flags);
829
+ console.error("error: option '%s' argument missing", option.flags);
809
830
  }
810
831
  process.exit(1);
811
832
  };
@@ -819,7 +840,7 @@ Command.prototype.optionMissingArgument = function(option, flag) {
819
840
 
820
841
  Command.prototype.unknownOption = function(flag) {
821
842
  if (this._allowUnknownOption) return;
822
- console.error("error: unknown option `%s'", flag);
843
+ console.error("error: unknown option '%s'", flag);
823
844
  process.exit(1);
824
845
  };
825
846
 
@@ -831,7 +852,7 @@ Command.prototype.unknownOption = function(flag) {
831
852
  */
832
853
 
833
854
  Command.prototype.variadicArgNotLast = function(name) {
834
- console.error("error: variadic arguments must be last `%s'", name);
855
+ console.error("error: variadic arguments must be last '%s'", name);
835
856
  process.exit(1);
836
857
  };
837
858
 
@@ -841,17 +862,21 @@ Command.prototype.variadicArgNotLast = function(name) {
841
862
  * This method auto-registers the "-V, --version" flag
842
863
  * which will print the version number when passed.
843
864
  *
865
+ * You can optionally supply the flags and description to override the defaults.
866
+ *
844
867
  * @param {String} str
845
868
  * @param {String} [flags]
869
+ * @param {String} [description]
846
870
  * @return {Command} for chaining
847
871
  * @api public
848
872
  */
849
873
 
850
- Command.prototype.version = function(str, flags) {
874
+ Command.prototype.version = function(str, flags, description) {
851
875
  if (arguments.length === 0) return this._version;
852
876
  this._version = str;
853
877
  flags = flags || '-V, --version';
854
- var versionOption = new Option(flags, 'output the version number');
878
+ description = description || 'output the version number';
879
+ var versionOption = new Option(flags, description);
855
880
  this._versionOptionName = versionOption.long.substr(2) || 'version';
856
881
  this.options.push(versionOption);
857
882
  this.on('option:' + this._versionOptionName, function() {
@@ -985,8 +1010,9 @@ Command.prototype.largestCommandLength = function() {
985
1010
  Command.prototype.largestOptionLength = function() {
986
1011
  var options = [].slice.call(this.options);
987
1012
  options.push({
988
- flags: '-h, --help'
1013
+ flags: this._helpFlags
989
1014
  });
1015
+
990
1016
  return options.reduce(function(max, option) {
991
1017
  return Math.max(max, option.flags.length);
992
1018
  }, 0);
@@ -1042,8 +1068,8 @@ Command.prototype.optionHelp = function() {
1042
1068
  // Append the help information
1043
1069
  return this.options.map(function(option) {
1044
1070
  return pad(option.flags, width) + ' ' + option.description +
1045
- ((option.bool && option.defaultValue !== undefined) ? ' (default: ' + JSON.stringify(option.defaultValue) + ')' : '');
1046
- }).concat([pad('-h, --help', width) + ' ' + 'output usage information'])
1071
+ ((!option.negate && option.defaultValue !== undefined) ? ' (default: ' + JSON.stringify(option.defaultValue) + ')' : '');
1072
+ }).concat([pad(this._helpFlags, width) + ' ' + this._helpDescription])
1047
1073
  .join('\n');
1048
1074
  };
1049
1075
 
@@ -1101,8 +1127,12 @@ Command.prototype.helpInformation = function() {
1101
1127
  if (this._alias) {
1102
1128
  cmdName = cmdName + '|' + this._alias;
1103
1129
  }
1130
+ var parentCmdNames = '';
1131
+ for (var parentCmd = this.parent; parentCmd; parentCmd = parentCmd.parent) {
1132
+ parentCmdNames = parentCmd.name() + ' ' + parentCmdNames;
1133
+ }
1104
1134
  var usage = [
1105
- 'Usage: ' + cmdName + ' ' + this.usage(),
1135
+ 'Usage: ' + parentCmdNames + cmdName + ' ' + this.usage(),
1106
1136
  ''
1107
1137
  ];
1108
1138
 
@@ -1124,7 +1154,10 @@ Command.prototype.helpInformation = function() {
1124
1154
  };
1125
1155
 
1126
1156
  /**
1127
- * Output help information for this command
1157
+ * Output help information for this command.
1158
+ *
1159
+ * When listener(s) are available for the helpLongFlag
1160
+ * those callbacks are invoked.
1128
1161
  *
1129
1162
  * @api public
1130
1163
  */
@@ -1135,13 +1168,41 @@ Command.prototype.outputHelp = function(cb) {
1135
1168
  return passthru;
1136
1169
  };
1137
1170
  }
1138
- process.stdout.write(cb(this.helpInformation()));
1139
- this.emit('--help');
1171
+ const cbOutput = cb(this.helpInformation());
1172
+ if (typeof cbOutput !== 'string' && !Buffer.isBuffer(cbOutput)) {
1173
+ throw new Error('outputHelp callback must return a string or a Buffer');
1174
+ }
1175
+ process.stdout.write(cbOutput);
1176
+ this.emit(this._helpLongFlag);
1177
+ };
1178
+
1179
+ /**
1180
+ * You can pass in flags and a description to override the help
1181
+ * flags and help description for your command.
1182
+ *
1183
+ * @param {String} [flags]
1184
+ * @param {String} [description]
1185
+ * @return {Command}
1186
+ * @api public
1187
+ */
1188
+
1189
+ Command.prototype.helpOption = function(flags, description) {
1190
+ this._helpFlags = flags || this._helpFlags;
1191
+ this._helpDescription = description || this._helpDescription;
1192
+
1193
+ var splitFlags = this._helpFlags.split(/[ ,|]+/);
1194
+
1195
+ if (splitFlags.length > 1) this._helpShortFlag = splitFlags.shift();
1196
+
1197
+ this._helpLongFlag = splitFlags.shift();
1198
+
1199
+ return this;
1140
1200
  };
1141
1201
 
1142
1202
  /**
1143
1203
  * Output help information and exit.
1144
1204
  *
1205
+ * @param {Function} [cb]
1145
1206
  * @api public
1146
1207
  */
1147
1208
 
@@ -1188,8 +1249,9 @@ function pad(str, width) {
1188
1249
 
1189
1250
  function outputHelpIfNecessary(cmd, options) {
1190
1251
  options = options || [];
1252
+
1191
1253
  for (var i = 0; i < options.length; i++) {
1192
- if (options[i] === '--help' || options[i] === '-h') {
1254
+ if (options[i] === cmd._helpLongFlag || options[i] === cmd._helpShortFlag) {
1193
1255
  cmd.outputHelp();
1194
1256
  process.exit(0);
1195
1257
  }
@@ -1197,7 +1259,7 @@ function outputHelpIfNecessary(cmd, options) {
1197
1259
  }
1198
1260
 
1199
1261
  /**
1200
- * Takes an argument an returns its human readable equivalent for help usage.
1262
+ * Takes an argument and returns its human readable equivalent for help usage.
1201
1263
  *
1202
1264
  * @param {Object} arg
1203
1265
  * @return {String}
@@ -1222,3 +1284,50 @@ function exists(file) {
1222
1284
  return false;
1223
1285
  }
1224
1286
  }
1287
+
1288
+ /**
1289
+ * Scan arguments and increment port number for inspect calls (to avoid conflicts when spawning new command).
1290
+ *
1291
+ * @param {string[]} args - array of arguments from node.execArgv
1292
+ * @returns {string[]}
1293
+ * @api private
1294
+ */
1295
+
1296
+ function incrementNodeInspectorPort(args) {
1297
+ // Testing for these options:
1298
+ // --inspect[=[host:]port]
1299
+ // --inspect-brk[=[host:]port]
1300
+ // --inspect-port=[host:]port
1301
+ return args.map((arg) => {
1302
+ var result = arg;
1303
+ if (arg.indexOf('--inspect') === 0) {
1304
+ var debugOption;
1305
+ var debugHost = '127.0.0.1';
1306
+ var debugPort = '9229';
1307
+ var match;
1308
+ if ((match = arg.match(/^(--inspect(-brk)?)$/)) !== null) {
1309
+ // e.g. --inspect
1310
+ debugOption = match[1];
1311
+ } else if ((match = arg.match(/^(--inspect(-brk|-port)?)=([^:]+)$/)) !== null) {
1312
+ debugOption = match[1];
1313
+ if (/^\d+$/.test(match[3])) {
1314
+ // e.g. --inspect=1234
1315
+ debugPort = match[3];
1316
+ } else {
1317
+ // e.g. --inspect=localhost
1318
+ debugHost = match[3];
1319
+ }
1320
+ } else if ((match = arg.match(/^(--inspect(-brk|-port)?)=([^:]+):(\d+)$/)) !== null) {
1321
+ // e.g. --inspect=localhost:1234
1322
+ debugOption = match[1];
1323
+ debugHost = match[3];
1324
+ debugPort = match[4];
1325
+ }
1326
+
1327
+ if (debugOption && debugPort !== '0') {
1328
+ result = `${debugOption}=${debugHost}:${parseInt(debugPort) + 1}`;
1329
+ }
1330
+ }
1331
+ return result;
1332
+ });
1333
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "commander",
3
- "version": "2.20.3",
3
+ "version": "3.0.2",
4
4
  "description": "the complete solution for node.js command-line programs",
5
5
  "keywords": [
6
6
  "commander",
@@ -30,7 +30,7 @@
30
30
  "eslint": "^6.4.0",
31
31
  "should": "^13.2.3",
32
32
  "sinon": "^7.5.0",
33
- "standard": "^14.3.1",
33
+ "standard": "^13.1.0",
34
34
  "ts-node": "^8.4.1",
35
35
  "typescript": "^3.6.3"
36
36
  },