commander 11.0.0 → 12.0.0-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 +26 -22
- package/index.js +8 -11
- package/lib/argument.js +3 -5
- package/lib/command.js +222 -181
- package/lib/error.js +0 -2
- package/lib/help.js +10 -12
- package/lib/option.js +8 -11
- package/package.json +11 -21
- package/typings/index.d.ts +33 -38
package/lib/command.js
CHANGED
|
@@ -10,8 +10,6 @@ const { Help } = require('./help.js');
|
|
|
10
10
|
const { Option, splitOptionFlags, DualOptions } = require('./option.js');
|
|
11
11
|
const { suggestSimilar } = require('./suggestSimilar');
|
|
12
12
|
|
|
13
|
-
// @ts-check
|
|
14
|
-
|
|
15
13
|
class Command extends EventEmitter {
|
|
16
14
|
/**
|
|
17
15
|
* Initialize a new `Command`.
|
|
@@ -29,7 +27,8 @@ class Command extends EventEmitter {
|
|
|
29
27
|
this._allowUnknownOption = false;
|
|
30
28
|
this._allowExcessArguments = true;
|
|
31
29
|
/** @type {Argument[]} */
|
|
32
|
-
this.
|
|
30
|
+
this.registeredArguments = [];
|
|
31
|
+
this._args = this.registeredArguments; // deprecated old name
|
|
33
32
|
/** @type {string[]} */
|
|
34
33
|
this.args = []; // cli args with options removed
|
|
35
34
|
this.rawArgs = [];
|
|
@@ -109,6 +108,19 @@ class Command extends EventEmitter {
|
|
|
109
108
|
return this;
|
|
110
109
|
}
|
|
111
110
|
|
|
111
|
+
/**
|
|
112
|
+
* @returns {Command[]}
|
|
113
|
+
* @private
|
|
114
|
+
*/
|
|
115
|
+
|
|
116
|
+
_getCommandAndAncestors() {
|
|
117
|
+
const result = [];
|
|
118
|
+
for (let command = this; command; command = command.parent) {
|
|
119
|
+
result.push(command);
|
|
120
|
+
}
|
|
121
|
+
return result;
|
|
122
|
+
}
|
|
123
|
+
|
|
112
124
|
/**
|
|
113
125
|
* Define a command.
|
|
114
126
|
*
|
|
@@ -153,7 +165,7 @@ class Command extends EventEmitter {
|
|
|
153
165
|
cmd._hidden = !!(opts.noHelp || opts.hidden); // noHelp is deprecated old name for hidden
|
|
154
166
|
cmd._executableFile = opts.executableFile || null; // Custom name for executable file, set missing to null to match constructor
|
|
155
167
|
if (args) cmd.arguments(args);
|
|
156
|
-
this.
|
|
168
|
+
this._registerCommand(cmd);
|
|
157
169
|
cmd.parent = this;
|
|
158
170
|
cmd.copyInheritedSettings(this);
|
|
159
171
|
|
|
@@ -270,8 +282,10 @@ class Command extends EventEmitter {
|
|
|
270
282
|
if (opts.isDefault) this._defaultCommandName = cmd._name;
|
|
271
283
|
if (opts.noHelp || opts.hidden) cmd._hidden = true; // modifying passed command due to existing implementation
|
|
272
284
|
|
|
273
|
-
this.
|
|
285
|
+
this._registerCommand(cmd);
|
|
274
286
|
cmd.parent = this;
|
|
287
|
+
cmd._checkForBrokenPassThrough();
|
|
288
|
+
|
|
275
289
|
return this;
|
|
276
290
|
}
|
|
277
291
|
|
|
@@ -343,14 +357,14 @@ class Command extends EventEmitter {
|
|
|
343
357
|
* @return {Command} `this` command for chaining
|
|
344
358
|
*/
|
|
345
359
|
addArgument(argument) {
|
|
346
|
-
const previousArgument = this.
|
|
360
|
+
const previousArgument = this.registeredArguments.slice(-1)[0];
|
|
347
361
|
if (previousArgument && previousArgument.variadic) {
|
|
348
362
|
throw new Error(`only the last argument can be variadic '${previousArgument.name()}'`);
|
|
349
363
|
}
|
|
350
364
|
if (argument.required && argument.defaultValue !== undefined && argument.parseArg === undefined) {
|
|
351
365
|
throw new Error(`a default value for a required argument is never used: '${argument.name()}'`);
|
|
352
366
|
}
|
|
353
|
-
this.
|
|
367
|
+
this.registeredArguments.push(argument);
|
|
354
368
|
return this;
|
|
355
369
|
}
|
|
356
370
|
|
|
@@ -380,7 +394,7 @@ class Command extends EventEmitter {
|
|
|
380
394
|
|
|
381
395
|
/**
|
|
382
396
|
* @return {boolean}
|
|
383
|
-
* @
|
|
397
|
+
* @package internal use only
|
|
384
398
|
*/
|
|
385
399
|
|
|
386
400
|
_hasImplicitHelpCommand() {
|
|
@@ -441,7 +455,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
441
455
|
* @param {string} code an id string representing the error
|
|
442
456
|
* @param {string} message human-readable description of the error
|
|
443
457
|
* @return never
|
|
444
|
-
* @
|
|
458
|
+
* @private
|
|
445
459
|
*/
|
|
446
460
|
|
|
447
461
|
_exit(exitCode, code, message) {
|
|
@@ -470,7 +484,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
470
484
|
action(fn) {
|
|
471
485
|
const listener = (args) => {
|
|
472
486
|
// The .action callback takes an extra parameter which is the command or options.
|
|
473
|
-
const expectedArgsCount = this.
|
|
487
|
+
const expectedArgsCount = this.registeredArguments.length;
|
|
474
488
|
const actionArgs = args.slice(0, expectedArgsCount);
|
|
475
489
|
if (this._storeOptionsAsProperties) {
|
|
476
490
|
actionArgs[expectedArgsCount] = this; // backwards compatible "options"
|
|
@@ -500,6 +514,71 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
500
514
|
return new Option(flags, description);
|
|
501
515
|
}
|
|
502
516
|
|
|
517
|
+
/**
|
|
518
|
+
* Wrap parseArgs to catch 'commander.invalidArgument'.
|
|
519
|
+
*
|
|
520
|
+
* @param {Option | Argument} target
|
|
521
|
+
* @param {string} value
|
|
522
|
+
* @param {*} previous
|
|
523
|
+
* @param {string} invalidArgumentMessage
|
|
524
|
+
* @private
|
|
525
|
+
*/
|
|
526
|
+
|
|
527
|
+
_callParseArg(target, value, previous, invalidArgumentMessage) {
|
|
528
|
+
try {
|
|
529
|
+
return target.parseArg(value, previous);
|
|
530
|
+
} catch (err) {
|
|
531
|
+
if (err.code === 'commander.invalidArgument') {
|
|
532
|
+
const message = `${invalidArgumentMessage} ${err.message}`;
|
|
533
|
+
this.error(message, { exitCode: err.exitCode, code: err.code });
|
|
534
|
+
}
|
|
535
|
+
throw err;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
/**
|
|
540
|
+
* Check for option flag conflicts.
|
|
541
|
+
* Register option if no conflicts found, or throw on conflict.
|
|
542
|
+
*
|
|
543
|
+
* @param {Option} option
|
|
544
|
+
* @api private
|
|
545
|
+
*/
|
|
546
|
+
|
|
547
|
+
_registerOption(option) {
|
|
548
|
+
const matchingOption = (option.short && this._findOption(option.short)) ||
|
|
549
|
+
(option.long && this._findOption(option.long));
|
|
550
|
+
if (matchingOption) {
|
|
551
|
+
const matchingFlag = (option.long && this._findOption(option.long)) ? option.long : option.short;
|
|
552
|
+
throw new Error(`Cannot add option '${option.flags}'${this._name && ` to command '${this._name}'`} due to conflicting flag '${matchingFlag}'
|
|
553
|
+
- already used by option '${matchingOption.flags}'`);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
this.options.push(option);
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
/**
|
|
560
|
+
* Check for command name and alias conflicts with existing commands.
|
|
561
|
+
* Register command if no conflicts found, or throw on conflict.
|
|
562
|
+
*
|
|
563
|
+
* @param {Command} command
|
|
564
|
+
* @api private
|
|
565
|
+
*/
|
|
566
|
+
|
|
567
|
+
_registerCommand(command) {
|
|
568
|
+
const knownBy = (cmd) => {
|
|
569
|
+
return [cmd.name()].concat(cmd.aliases());
|
|
570
|
+
};
|
|
571
|
+
|
|
572
|
+
const alreadyUsed = knownBy(command).find((name) => this._findCommand(name));
|
|
573
|
+
if (alreadyUsed) {
|
|
574
|
+
const existingCmd = knownBy(this._findCommand(alreadyUsed)).join('|');
|
|
575
|
+
const newCmd = knownBy(command).join('|');
|
|
576
|
+
throw new Error(`cannot add command '${newCmd}' as already have command '${existingCmd}'`);
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
this.commands.push(command);
|
|
580
|
+
}
|
|
581
|
+
|
|
503
582
|
/**
|
|
504
583
|
* Add an option.
|
|
505
584
|
*
|
|
@@ -507,6 +586,8 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
507
586
|
* @return {Command} `this` command for chaining
|
|
508
587
|
*/
|
|
509
588
|
addOption(option) {
|
|
589
|
+
this._registerOption(option);
|
|
590
|
+
|
|
510
591
|
const oname = option.name();
|
|
511
592
|
const name = option.attributeName();
|
|
512
593
|
|
|
@@ -521,9 +602,6 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
521
602
|
this.setOptionValueWithSource(name, option.defaultValue, 'default');
|
|
522
603
|
}
|
|
523
604
|
|
|
524
|
-
// register the option
|
|
525
|
-
this.options.push(option);
|
|
526
|
-
|
|
527
605
|
// handler for cli and env supplied values
|
|
528
606
|
const handleOptionValue = (val, invalidValueMessage, valueSource) => {
|
|
529
607
|
// val is null for optional option used without an optional-argument.
|
|
@@ -535,15 +613,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
535
613
|
// custom processing
|
|
536
614
|
const oldValue = this.getOptionValue(name);
|
|
537
615
|
if (val !== null && option.parseArg) {
|
|
538
|
-
|
|
539
|
-
val = option.parseArg(val, oldValue);
|
|
540
|
-
} catch (err) {
|
|
541
|
-
if (err.code === 'commander.invalidArgument') {
|
|
542
|
-
const message = `${invalidValueMessage} ${err.message}`;
|
|
543
|
-
this.error(message, { exitCode: err.exitCode, code: err.code });
|
|
544
|
-
}
|
|
545
|
-
throw err;
|
|
546
|
-
}
|
|
616
|
+
val = this._callParseArg(option, val, oldValue, invalidValueMessage);
|
|
547
617
|
} else if (val !== null && option.variadic) {
|
|
548
618
|
val = option._concatValue(val, oldValue);
|
|
549
619
|
}
|
|
@@ -579,7 +649,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
579
649
|
/**
|
|
580
650
|
* Internal implementation shared by .option() and .requiredOption()
|
|
581
651
|
*
|
|
582
|
-
* @
|
|
652
|
+
* @private
|
|
583
653
|
*/
|
|
584
654
|
_optionEx(config, flags, description, fn, defaultValue) {
|
|
585
655
|
if (typeof flags === 'object' && flags instanceof Option) {
|
|
@@ -605,57 +675,29 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
605
675
|
}
|
|
606
676
|
|
|
607
677
|
/**
|
|
608
|
-
* Define option with `flags`, `description
|
|
609
|
-
* coercion `fn`.
|
|
678
|
+
* Define option with `flags`, `description`, and optional argument parsing function or `defaultValue` or both.
|
|
610
679
|
*
|
|
611
|
-
* The `flags` string contains the short and/or long flags,
|
|
612
|
-
*
|
|
613
|
-
* all will output this way when `--help` is used.
|
|
680
|
+
* The `flags` string contains the short and/or long flags, separated by comma, a pipe or space. A required
|
|
681
|
+
* option-argument is indicated by `<>` and an optional option-argument by `[]`.
|
|
614
682
|
*
|
|
615
|
-
*
|
|
616
|
-
* "-p|--pepper"
|
|
617
|
-
* "-p --pepper"
|
|
683
|
+
* See the README for more details, and see also addOption() and requiredOption().
|
|
618
684
|
*
|
|
619
685
|
* @example
|
|
620
|
-
*
|
|
621
|
-
*
|
|
622
|
-
*
|
|
623
|
-
*
|
|
624
|
-
* //
|
|
625
|
-
*
|
|
626
|
-
* --pepper
|
|
627
|
-
* program.pepper
|
|
628
|
-
* // => true
|
|
629
|
-
*
|
|
630
|
-
* // simple boolean defaulting to true (unless non-negated option is also defined)
|
|
631
|
-
* program.option('-C, --no-cheese', 'remove cheese');
|
|
632
|
-
*
|
|
633
|
-
* program.cheese
|
|
634
|
-
* // => true
|
|
635
|
-
*
|
|
636
|
-
* --no-cheese
|
|
637
|
-
* program.cheese
|
|
638
|
-
* // => false
|
|
639
|
-
*
|
|
640
|
-
* // required argument
|
|
641
|
-
* program.option('-C, --chdir <path>', 'change the working directory');
|
|
642
|
-
*
|
|
643
|
-
* --chdir /tmp
|
|
644
|
-
* program.chdir
|
|
645
|
-
* // => "/tmp"
|
|
646
|
-
*
|
|
647
|
-
* // optional argument
|
|
648
|
-
* program.option('-c, --cheese [type]', 'add cheese [marble]');
|
|
686
|
+
* program
|
|
687
|
+
* .option('-p, --pepper', 'add pepper')
|
|
688
|
+
* .option('-p, --pizza-type <TYPE>', 'type of pizza') // required option-argument
|
|
689
|
+
* .option('-c, --cheese [CHEESE]', 'add extra cheese', 'mozzarella') // optional option-argument with default
|
|
690
|
+
* .option('-t, --tip <VALUE>', 'add tip to purchase cost', parseFloat) // custom parse function
|
|
649
691
|
*
|
|
650
692
|
* @param {string} flags
|
|
651
693
|
* @param {string} [description]
|
|
652
|
-
* @param {Function|*} [
|
|
694
|
+
* @param {Function|*} [parseArg] - custom option processing function or default value
|
|
653
695
|
* @param {*} [defaultValue]
|
|
654
696
|
* @return {Command} `this` command for chaining
|
|
655
697
|
*/
|
|
656
698
|
|
|
657
|
-
option(flags, description,
|
|
658
|
-
return this._optionEx({}, flags, description,
|
|
699
|
+
option(flags, description, parseArg, defaultValue) {
|
|
700
|
+
return this._optionEx({}, flags, description, parseArg, defaultValue);
|
|
659
701
|
}
|
|
660
702
|
|
|
661
703
|
/**
|
|
@@ -666,13 +708,13 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
666
708
|
*
|
|
667
709
|
* @param {string} flags
|
|
668
710
|
* @param {string} [description]
|
|
669
|
-
* @param {Function|*} [
|
|
711
|
+
* @param {Function|*} [parseArg] - custom option processing function or default value
|
|
670
712
|
* @param {*} [defaultValue]
|
|
671
713
|
* @return {Command} `this` command for chaining
|
|
672
714
|
*/
|
|
673
715
|
|
|
674
|
-
requiredOption(flags, description,
|
|
675
|
-
return this._optionEx({ mandatory: true }, flags, description,
|
|
716
|
+
requiredOption(flags, description, parseArg, defaultValue) {
|
|
717
|
+
return this._optionEx({ mandatory: true }, flags, description, parseArg, defaultValue);
|
|
676
718
|
}
|
|
677
719
|
|
|
678
720
|
/**
|
|
@@ -735,12 +777,20 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
735
777
|
*/
|
|
736
778
|
passThroughOptions(passThrough = true) {
|
|
737
779
|
this._passThroughOptions = !!passThrough;
|
|
738
|
-
|
|
739
|
-
throw new Error('passThroughOptions can not be used without turning on enablePositionalOptions for parent command(s)');
|
|
740
|
-
}
|
|
780
|
+
this._checkForBrokenPassThrough();
|
|
741
781
|
return this;
|
|
742
782
|
}
|
|
743
783
|
|
|
784
|
+
/**
|
|
785
|
+
* @private
|
|
786
|
+
*/
|
|
787
|
+
|
|
788
|
+
_checkForBrokenPassThrough() {
|
|
789
|
+
if (this.parent && this._passThroughOptions && !this.parent._enablePositionalOptions) {
|
|
790
|
+
throw new Error(`passThroughOptions cannot be used for '${this._name}' without turning on enablePositionalOptions for parent command(s)`);
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
|
|
744
794
|
/**
|
|
745
795
|
* Whether to store option values as properties on command object,
|
|
746
796
|
* or store separately (specify false). In both cases the option values can be accessed using .opts().
|
|
@@ -750,10 +800,13 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
750
800
|
*/
|
|
751
801
|
|
|
752
802
|
storeOptionsAsProperties(storeAsProperties = true) {
|
|
753
|
-
this._storeOptionsAsProperties = !!storeAsProperties;
|
|
754
803
|
if (this.options.length) {
|
|
755
804
|
throw new Error('call .storeOptionsAsProperties() before adding options');
|
|
756
805
|
}
|
|
806
|
+
if (Object.keys(this._optionValues).length) {
|
|
807
|
+
throw new Error('call .storeOptionsAsProperties() before setting option values');
|
|
808
|
+
}
|
|
809
|
+
this._storeOptionsAsProperties = !!storeAsProperties;
|
|
757
810
|
return this;
|
|
758
811
|
}
|
|
759
812
|
|
|
@@ -825,7 +878,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
825
878
|
getOptionValueSourceWithGlobals(key) {
|
|
826
879
|
// global overwrites local, like optsWithGlobals
|
|
827
880
|
let source;
|
|
828
|
-
|
|
881
|
+
this._getCommandAndAncestors().forEach((cmd) => {
|
|
829
882
|
if (cmd.getOptionValueSource(key) !== undefined) {
|
|
830
883
|
source = cmd.getOptionValueSource(key);
|
|
831
884
|
}
|
|
@@ -837,7 +890,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
837
890
|
* Get user arguments from implied or explicit arguments.
|
|
838
891
|
* Side-effects: set _scriptPath if args included script. Used for default program name, and subcommand searches.
|
|
839
892
|
*
|
|
840
|
-
* @
|
|
893
|
+
* @private
|
|
841
894
|
*/
|
|
842
895
|
|
|
843
896
|
_prepareUserArgs(argv, parseOptions) {
|
|
@@ -940,7 +993,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
940
993
|
/**
|
|
941
994
|
* Execute a sub-command executable.
|
|
942
995
|
*
|
|
943
|
-
* @
|
|
996
|
+
* @private
|
|
944
997
|
*/
|
|
945
998
|
|
|
946
999
|
_executeSubCommand(subcommand, args) {
|
|
@@ -1027,15 +1080,15 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1027
1080
|
}
|
|
1028
1081
|
|
|
1029
1082
|
// By default terminate process when spawned process terminates.
|
|
1030
|
-
// Suppressing the exit if exitCallback defined is a bit messy and of limited use, but does allow process to stay running!
|
|
1031
1083
|
const exitCallback = this._exitCallback;
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1084
|
+
proc.on('close', (code, _signal) => {
|
|
1085
|
+
code = code ?? 1; // code is null if spawned process terminated due to a signal
|
|
1086
|
+
if (!exitCallback) {
|
|
1087
|
+
process.exit(code);
|
|
1088
|
+
} else {
|
|
1089
|
+
exitCallback(new CommanderError(code, 'commander.executeSubCommandAsync', '(close)'));
|
|
1090
|
+
}
|
|
1091
|
+
});
|
|
1039
1092
|
proc.on('error', (err) => {
|
|
1040
1093
|
// @ts-ignore
|
|
1041
1094
|
if (err.code === 'ENOENT') {
|
|
@@ -1065,30 +1118,30 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1065
1118
|
}
|
|
1066
1119
|
|
|
1067
1120
|
/**
|
|
1068
|
-
* @
|
|
1121
|
+
* @private
|
|
1069
1122
|
*/
|
|
1070
1123
|
|
|
1071
1124
|
_dispatchSubcommand(commandName, operands, unknown) {
|
|
1072
1125
|
const subCommand = this._findCommand(commandName);
|
|
1073
1126
|
if (!subCommand) this.help({ error: true });
|
|
1074
1127
|
|
|
1075
|
-
let
|
|
1076
|
-
|
|
1077
|
-
|
|
1128
|
+
let promiseChain;
|
|
1129
|
+
promiseChain = this._chainOrCallSubCommandHook(promiseChain, subCommand, 'preSubcommand');
|
|
1130
|
+
promiseChain = this._chainOrCall(promiseChain, () => {
|
|
1078
1131
|
if (subCommand._executableHandler) {
|
|
1079
1132
|
this._executeSubCommand(subCommand, operands.concat(unknown));
|
|
1080
1133
|
} else {
|
|
1081
1134
|
return subCommand._parseCommand(operands, unknown);
|
|
1082
1135
|
}
|
|
1083
1136
|
});
|
|
1084
|
-
return
|
|
1137
|
+
return promiseChain;
|
|
1085
1138
|
}
|
|
1086
1139
|
|
|
1087
1140
|
/**
|
|
1088
1141
|
* Invoke help directly if possible, or dispatch if necessary.
|
|
1089
1142
|
* e.g. help foo
|
|
1090
1143
|
*
|
|
1091
|
-
* @
|
|
1144
|
+
* @private
|
|
1092
1145
|
*/
|
|
1093
1146
|
|
|
1094
1147
|
_dispatchHelpCommand(subcommandName) {
|
|
@@ -1101,35 +1154,37 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1101
1154
|
}
|
|
1102
1155
|
|
|
1103
1156
|
// Fallback to parsing the help flag to invoke the help.
|
|
1104
|
-
return this._dispatchSubcommand(subcommandName, [], [
|
|
1157
|
+
return this._dispatchSubcommand(subcommandName, [], [
|
|
1158
|
+
this._helpLongFlag || this._helpShortFlag
|
|
1159
|
+
]);
|
|
1105
1160
|
}
|
|
1106
1161
|
|
|
1107
1162
|
/**
|
|
1108
|
-
* Check this.args against expected this.
|
|
1163
|
+
* Check this.args against expected this.registeredArguments.
|
|
1109
1164
|
*
|
|
1110
|
-
* @
|
|
1165
|
+
* @private
|
|
1111
1166
|
*/
|
|
1112
1167
|
|
|
1113
1168
|
_checkNumberOfArguments() {
|
|
1114
1169
|
// too few
|
|
1115
|
-
this.
|
|
1170
|
+
this.registeredArguments.forEach((arg, i) => {
|
|
1116
1171
|
if (arg.required && this.args[i] == null) {
|
|
1117
1172
|
this.missingArgument(arg.name());
|
|
1118
1173
|
}
|
|
1119
1174
|
});
|
|
1120
1175
|
// too many
|
|
1121
|
-
if (this.
|
|
1176
|
+
if (this.registeredArguments.length > 0 && this.registeredArguments[this.registeredArguments.length - 1].variadic) {
|
|
1122
1177
|
return;
|
|
1123
1178
|
}
|
|
1124
|
-
if (this.args.length > this.
|
|
1179
|
+
if (this.args.length > this.registeredArguments.length) {
|
|
1125
1180
|
this._excessArguments(this.args);
|
|
1126
1181
|
}
|
|
1127
1182
|
}
|
|
1128
1183
|
|
|
1129
1184
|
/**
|
|
1130
|
-
* Process this.args using this.
|
|
1185
|
+
* Process this.args using this.registeredArguments and save as this.processedArgs!
|
|
1131
1186
|
*
|
|
1132
|
-
* @
|
|
1187
|
+
* @private
|
|
1133
1188
|
*/
|
|
1134
1189
|
|
|
1135
1190
|
_processArguments() {
|
|
@@ -1137,15 +1192,8 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1137
1192
|
// Extra processing for nice error message on parsing failure.
|
|
1138
1193
|
let parsedValue = value;
|
|
1139
1194
|
if (value !== null && argument.parseArg) {
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
} catch (err) {
|
|
1143
|
-
if (err.code === 'commander.invalidArgument') {
|
|
1144
|
-
const message = `error: command-argument value '${value}' is invalid for argument '${argument.name()}'. ${err.message}`;
|
|
1145
|
-
this.error(message, { exitCode: err.exitCode, code: err.code });
|
|
1146
|
-
}
|
|
1147
|
-
throw err;
|
|
1148
|
-
}
|
|
1195
|
+
const invalidValueMessage = `error: command-argument value '${value}' is invalid for argument '${argument.name()}'.`;
|
|
1196
|
+
parsedValue = this._callParseArg(argument, value, previous, invalidValueMessage);
|
|
1149
1197
|
}
|
|
1150
1198
|
return parsedValue;
|
|
1151
1199
|
};
|
|
@@ -1153,7 +1201,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1153
1201
|
this._checkNumberOfArguments();
|
|
1154
1202
|
|
|
1155
1203
|
const processedArgs = [];
|
|
1156
|
-
this.
|
|
1204
|
+
this.registeredArguments.forEach((declaredArg, index) => {
|
|
1157
1205
|
let value = declaredArg.defaultValue;
|
|
1158
1206
|
if (declaredArg.variadic) {
|
|
1159
1207
|
// Collect together remaining arguments for passing together as an array.
|
|
@@ -1184,7 +1232,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1184
1232
|
* @param {Promise|undefined} promise
|
|
1185
1233
|
* @param {Function} fn
|
|
1186
1234
|
* @return {Promise|undefined}
|
|
1187
|
-
* @
|
|
1235
|
+
* @private
|
|
1188
1236
|
*/
|
|
1189
1237
|
|
|
1190
1238
|
_chainOrCall(promise, fn) {
|
|
@@ -1202,13 +1250,13 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1202
1250
|
* @param {Promise|undefined} promise
|
|
1203
1251
|
* @param {string} event
|
|
1204
1252
|
* @return {Promise|undefined}
|
|
1205
|
-
* @
|
|
1253
|
+
* @private
|
|
1206
1254
|
*/
|
|
1207
1255
|
|
|
1208
1256
|
_chainOrCallHooks(promise, event) {
|
|
1209
1257
|
let result = promise;
|
|
1210
1258
|
const hooks = [];
|
|
1211
|
-
|
|
1259
|
+
this._getCommandAndAncestors()
|
|
1212
1260
|
.reverse()
|
|
1213
1261
|
.filter(cmd => cmd._lifeCycleHooks[event] !== undefined)
|
|
1214
1262
|
.forEach(hookedCommand => {
|
|
@@ -1234,7 +1282,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1234
1282
|
* @param {Command} subCommand
|
|
1235
1283
|
* @param {string} event
|
|
1236
1284
|
* @return {Promise|undefined}
|
|
1237
|
-
* @
|
|
1285
|
+
* @private
|
|
1238
1286
|
*/
|
|
1239
1287
|
|
|
1240
1288
|
_chainOrCallSubCommandHook(promise, subCommand, event) {
|
|
@@ -1253,7 +1301,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1253
1301
|
* Process arguments in context of this command.
|
|
1254
1302
|
* Returns action result, in case it is a promise.
|
|
1255
1303
|
*
|
|
1256
|
-
* @
|
|
1304
|
+
* @private
|
|
1257
1305
|
*/
|
|
1258
1306
|
|
|
1259
1307
|
_parseCommand(operands, unknown) {
|
|
@@ -1271,7 +1319,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1271
1319
|
return this._dispatchHelpCommand(operands[1]);
|
|
1272
1320
|
}
|
|
1273
1321
|
if (this._defaultCommandName) {
|
|
1274
|
-
|
|
1322
|
+
this._outputHelpIfRequested(unknown); // Run the help for default command from parent rather than passing to default command
|
|
1275
1323
|
return this._dispatchSubcommand(this._defaultCommandName, operands, unknown);
|
|
1276
1324
|
}
|
|
1277
1325
|
if (this.commands.length && this.args.length === 0 && !this._actionHandler && !this._defaultCommandName) {
|
|
@@ -1279,7 +1327,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1279
1327
|
this.help({ error: true });
|
|
1280
1328
|
}
|
|
1281
1329
|
|
|
1282
|
-
|
|
1330
|
+
this._outputHelpIfRequested(parsed.unknown);
|
|
1283
1331
|
this._checkForMissingMandatoryOptions();
|
|
1284
1332
|
this._checkForConflictingOptions();
|
|
1285
1333
|
|
|
@@ -1295,16 +1343,16 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1295
1343
|
checkForUnknownOptions();
|
|
1296
1344
|
this._processArguments();
|
|
1297
1345
|
|
|
1298
|
-
let
|
|
1299
|
-
|
|
1300
|
-
|
|
1346
|
+
let promiseChain;
|
|
1347
|
+
promiseChain = this._chainOrCallHooks(promiseChain, 'preAction');
|
|
1348
|
+
promiseChain = this._chainOrCall(promiseChain, () => this._actionHandler(this.processedArgs));
|
|
1301
1349
|
if (this.parent) {
|
|
1302
|
-
|
|
1350
|
+
promiseChain = this._chainOrCall(promiseChain, () => {
|
|
1303
1351
|
this.parent.emit(commandEvent, operands, unknown); // legacy
|
|
1304
1352
|
});
|
|
1305
1353
|
}
|
|
1306
|
-
|
|
1307
|
-
return
|
|
1354
|
+
promiseChain = this._chainOrCallHooks(promiseChain, 'postAction');
|
|
1355
|
+
return promiseChain;
|
|
1308
1356
|
}
|
|
1309
1357
|
if (this.parent && this.parent.listenerCount(commandEvent)) {
|
|
1310
1358
|
checkForUnknownOptions();
|
|
@@ -1337,7 +1385,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1337
1385
|
/**
|
|
1338
1386
|
* Find matching command.
|
|
1339
1387
|
*
|
|
1340
|
-
* @
|
|
1388
|
+
* @private
|
|
1341
1389
|
*/
|
|
1342
1390
|
_findCommand(name) {
|
|
1343
1391
|
if (!name) return undefined;
|
|
@@ -1349,7 +1397,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1349
1397
|
*
|
|
1350
1398
|
* @param {string} arg
|
|
1351
1399
|
* @return {Option}
|
|
1352
|
-
* @
|
|
1400
|
+
* @package internal use only
|
|
1353
1401
|
*/
|
|
1354
1402
|
|
|
1355
1403
|
_findOption(arg) {
|
|
@@ -1360,24 +1408,24 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1360
1408
|
* Display an error message if a mandatory option does not have a value.
|
|
1361
1409
|
* Called after checking for help flags in leaf subcommand.
|
|
1362
1410
|
*
|
|
1363
|
-
* @
|
|
1411
|
+
* @private
|
|
1364
1412
|
*/
|
|
1365
1413
|
|
|
1366
1414
|
_checkForMissingMandatoryOptions() {
|
|
1367
1415
|
// Walk up hierarchy so can call in subcommand after checking for displaying help.
|
|
1368
|
-
|
|
1416
|
+
this._getCommandAndAncestors().forEach((cmd) => {
|
|
1369
1417
|
cmd.options.forEach((anOption) => {
|
|
1370
1418
|
if (anOption.mandatory && (cmd.getOptionValue(anOption.attributeName()) === undefined)) {
|
|
1371
1419
|
cmd.missingMandatoryOptionValue(anOption);
|
|
1372
1420
|
}
|
|
1373
1421
|
});
|
|
1374
|
-
}
|
|
1422
|
+
});
|
|
1375
1423
|
}
|
|
1376
1424
|
|
|
1377
1425
|
/**
|
|
1378
1426
|
* Display an error message if conflicting options are used together in this.
|
|
1379
1427
|
*
|
|
1380
|
-
* @
|
|
1428
|
+
* @private
|
|
1381
1429
|
*/
|
|
1382
1430
|
_checkForConflictingLocalOptions() {
|
|
1383
1431
|
const definedNonDefaultOptions = this.options.filter(
|
|
@@ -1408,13 +1456,13 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1408
1456
|
* Display an error message if conflicting options are used together.
|
|
1409
1457
|
* Called after checking for help flags in leaf subcommand.
|
|
1410
1458
|
*
|
|
1411
|
-
* @
|
|
1459
|
+
* @private
|
|
1412
1460
|
*/
|
|
1413
1461
|
_checkForConflictingOptions() {
|
|
1414
1462
|
// Walk up hierarchy so can call in subcommand after checking for displaying help.
|
|
1415
|
-
|
|
1463
|
+
this._getCommandAndAncestors().forEach((cmd) => {
|
|
1416
1464
|
cmd._checkForConflictingLocalOptions();
|
|
1417
|
-
}
|
|
1465
|
+
});
|
|
1418
1466
|
}
|
|
1419
1467
|
|
|
1420
1468
|
/**
|
|
@@ -1577,7 +1625,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1577
1625
|
*/
|
|
1578
1626
|
optsWithGlobals() {
|
|
1579
1627
|
// globals overwrite locals
|
|
1580
|
-
return
|
|
1628
|
+
return this._getCommandAndAncestors().reduce(
|
|
1581
1629
|
(combinedOptions, cmd) => Object.assign(combinedOptions, cmd.opts()),
|
|
1582
1630
|
{}
|
|
1583
1631
|
);
|
|
@@ -1612,7 +1660,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1612
1660
|
* Apply any option related environment variables, if option does
|
|
1613
1661
|
* not have a value from cli or client code.
|
|
1614
1662
|
*
|
|
1615
|
-
* @
|
|
1663
|
+
* @private
|
|
1616
1664
|
*/
|
|
1617
1665
|
_parseOptionsEnv() {
|
|
1618
1666
|
this.options.forEach((option) => {
|
|
@@ -1635,7 +1683,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1635
1683
|
/**
|
|
1636
1684
|
* Apply any implied option values, if option is undefined or default value.
|
|
1637
1685
|
*
|
|
1638
|
-
* @
|
|
1686
|
+
* @private
|
|
1639
1687
|
*/
|
|
1640
1688
|
_parseOptionsImplied() {
|
|
1641
1689
|
const dualHelper = new DualOptions(this.options);
|
|
@@ -1659,7 +1707,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1659
1707
|
* Argument `name` is missing.
|
|
1660
1708
|
*
|
|
1661
1709
|
* @param {string} name
|
|
1662
|
-
* @
|
|
1710
|
+
* @private
|
|
1663
1711
|
*/
|
|
1664
1712
|
|
|
1665
1713
|
missingArgument(name) {
|
|
@@ -1671,7 +1719,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1671
1719
|
* `Option` is missing an argument.
|
|
1672
1720
|
*
|
|
1673
1721
|
* @param {Option} option
|
|
1674
|
-
* @
|
|
1722
|
+
* @private
|
|
1675
1723
|
*/
|
|
1676
1724
|
|
|
1677
1725
|
optionMissingArgument(option) {
|
|
@@ -1683,7 +1731,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1683
1731
|
* `Option` does not have a value, and is a mandatory option.
|
|
1684
1732
|
*
|
|
1685
1733
|
* @param {Option} option
|
|
1686
|
-
* @
|
|
1734
|
+
* @private
|
|
1687
1735
|
*/
|
|
1688
1736
|
|
|
1689
1737
|
missingMandatoryOptionValue(option) {
|
|
@@ -1696,7 +1744,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1696
1744
|
*
|
|
1697
1745
|
* @param {Option} option
|
|
1698
1746
|
* @param {Option} conflictingOption
|
|
1699
|
-
* @
|
|
1747
|
+
* @private
|
|
1700
1748
|
*/
|
|
1701
1749
|
_conflictingOption(option, conflictingOption) {
|
|
1702
1750
|
// The calling code does not know whether a negated option is the source of the
|
|
@@ -1733,7 +1781,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1733
1781
|
* Unknown option `flag`.
|
|
1734
1782
|
*
|
|
1735
1783
|
* @param {string} flag
|
|
1736
|
-
* @
|
|
1784
|
+
* @private
|
|
1737
1785
|
*/
|
|
1738
1786
|
|
|
1739
1787
|
unknownOption(flag) {
|
|
@@ -1762,13 +1810,13 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1762
1810
|
* Excess arguments, more than expected.
|
|
1763
1811
|
*
|
|
1764
1812
|
* @param {string[]} receivedArgs
|
|
1765
|
-
* @
|
|
1813
|
+
* @private
|
|
1766
1814
|
*/
|
|
1767
1815
|
|
|
1768
1816
|
_excessArguments(receivedArgs) {
|
|
1769
1817
|
if (this._allowExcessArguments) return;
|
|
1770
1818
|
|
|
1771
|
-
const expected = this.
|
|
1819
|
+
const expected = this.registeredArguments.length;
|
|
1772
1820
|
const s = (expected === 1) ? '' : 's';
|
|
1773
1821
|
const forSubcommand = this.parent ? ` for '${this.name()}'` : '';
|
|
1774
1822
|
const message = `error: too many arguments${forSubcommand}. Expected ${expected} argument${s} but got ${receivedArgs.length}.`;
|
|
@@ -1778,7 +1826,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1778
1826
|
/**
|
|
1779
1827
|
* Unknown command.
|
|
1780
1828
|
*
|
|
1781
|
-
* @
|
|
1829
|
+
* @private
|
|
1782
1830
|
*/
|
|
1783
1831
|
|
|
1784
1832
|
unknownCommand() {
|
|
@@ -1800,17 +1848,16 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1800
1848
|
}
|
|
1801
1849
|
|
|
1802
1850
|
/**
|
|
1803
|
-
*
|
|
1851
|
+
* Get or set the program version.
|
|
1804
1852
|
*
|
|
1805
|
-
* This method auto-registers the "-V, --version"
|
|
1806
|
-
* which will print the version number when passed.
|
|
1853
|
+
* This method auto-registers the "-V, --version" option which will print the version number.
|
|
1807
1854
|
*
|
|
1808
|
-
* You can optionally supply the
|
|
1855
|
+
* You can optionally supply the flags and description to override the defaults.
|
|
1809
1856
|
*
|
|
1810
|
-
* @param {string} str
|
|
1857
|
+
* @param {string} [str]
|
|
1811
1858
|
* @param {string} [flags]
|
|
1812
1859
|
* @param {string} [description]
|
|
1813
|
-
* @return {this | string} `this` command for chaining, or version string if no arguments
|
|
1860
|
+
* @return {this | string | undefined} `this` command for chaining, or version string if no arguments
|
|
1814
1861
|
*/
|
|
1815
1862
|
|
|
1816
1863
|
version(str, flags, description) {
|
|
@@ -1820,7 +1867,8 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1820
1867
|
description = description || 'output the version number';
|
|
1821
1868
|
const versionOption = this.createOption(flags, description);
|
|
1822
1869
|
this._versionOptionName = versionOption.attributeName();
|
|
1823
|
-
this.
|
|
1870
|
+
this._registerOption(versionOption);
|
|
1871
|
+
|
|
1824
1872
|
this.on('option:' + versionOption.name(), () => {
|
|
1825
1873
|
this._outputConfiguration.writeOut(`${str}\n`);
|
|
1826
1874
|
this._exit(0, 'commander.version', str);
|
|
@@ -1876,6 +1924,12 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1876
1924
|
}
|
|
1877
1925
|
|
|
1878
1926
|
if (alias === command._name) throw new Error('Command alias can\'t be the same as its name');
|
|
1927
|
+
const matchingCommand = this.parent?._findCommand(alias);
|
|
1928
|
+
if (matchingCommand) {
|
|
1929
|
+
// c.f. _registerCommand
|
|
1930
|
+
const existingCmd = [matchingCommand.name()].concat(matchingCommand.aliases()).join('|');
|
|
1931
|
+
throw new Error(`cannot add alias '${alias}' to command '${this.name()}' as already have command '${existingCmd}'`);
|
|
1932
|
+
}
|
|
1879
1933
|
|
|
1880
1934
|
command._aliases.push(alias);
|
|
1881
1935
|
return this;
|
|
@@ -1909,13 +1963,13 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1909
1963
|
if (str === undefined) {
|
|
1910
1964
|
if (this._usage) return this._usage;
|
|
1911
1965
|
|
|
1912
|
-
const args = this.
|
|
1966
|
+
const args = this.registeredArguments.map((arg) => {
|
|
1913
1967
|
return humanReadableArgName(arg);
|
|
1914
1968
|
});
|
|
1915
1969
|
return [].concat(
|
|
1916
1970
|
(this.options.length || this._hasHelpOption ? '[options]' : []),
|
|
1917
1971
|
(this.commands.length ? '[command]' : []),
|
|
1918
|
-
(this.
|
|
1972
|
+
(this.registeredArguments.length ? args : [])
|
|
1919
1973
|
).join(' ');
|
|
1920
1974
|
}
|
|
1921
1975
|
|
|
@@ -1964,7 +2018,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1964
2018
|
* program.executableDir('subcommands');
|
|
1965
2019
|
*
|
|
1966
2020
|
* @param {string} [path]
|
|
1967
|
-
* @return {string|Command}
|
|
2021
|
+
* @return {string|null|Command}
|
|
1968
2022
|
*/
|
|
1969
2023
|
|
|
1970
2024
|
executableDir(path) {
|
|
@@ -1989,7 +2043,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1989
2043
|
}
|
|
1990
2044
|
|
|
1991
2045
|
/**
|
|
1992
|
-
* @
|
|
2046
|
+
* @private
|
|
1993
2047
|
*/
|
|
1994
2048
|
|
|
1995
2049
|
_getHelpContext(contextOptions) {
|
|
@@ -2022,7 +2076,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2022
2076
|
}
|
|
2023
2077
|
const context = this._getHelpContext(contextOptions);
|
|
2024
2078
|
|
|
2025
|
-
|
|
2079
|
+
this._getCommandAndAncestors().reverse().forEach(command => command.emit('beforeAllHelp', context));
|
|
2026
2080
|
this.emit('beforeHelp', context);
|
|
2027
2081
|
|
|
2028
2082
|
let helpInformation = this.helpInformation(context);
|
|
@@ -2034,9 +2088,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2034
2088
|
}
|
|
2035
2089
|
context.write(helpInformation);
|
|
2036
2090
|
|
|
2037
|
-
|
|
2091
|
+
if (this._helpLongFlag) {
|
|
2092
|
+
this.emit(this._helpLongFlag); // deprecated
|
|
2093
|
+
}
|
|
2038
2094
|
this.emit('afterHelp', context);
|
|
2039
|
-
|
|
2095
|
+
this._getCommandAndAncestors().forEach(command => command.emit('afterAllHelp', context));
|
|
2040
2096
|
}
|
|
2041
2097
|
|
|
2042
2098
|
/**
|
|
@@ -2113,22 +2169,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2113
2169
|
});
|
|
2114
2170
|
return this;
|
|
2115
2171
|
}
|
|
2116
|
-
}
|
|
2117
2172
|
|
|
2118
|
-
/**
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
*/
|
|
2173
|
+
/**
|
|
2174
|
+
* Output help information if help flags specified
|
|
2175
|
+
*
|
|
2176
|
+
* @param {Array} args - array of options to search for help flags
|
|
2177
|
+
* @private
|
|
2178
|
+
*/
|
|
2125
2179
|
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2180
|
+
_outputHelpIfRequested(args) {
|
|
2181
|
+
const helpOption = this._hasHelpOption && args.find(arg => arg === this._helpLongFlag || arg === this._helpShortFlag);
|
|
2182
|
+
if (helpOption) {
|
|
2183
|
+
this.outputHelp();
|
|
2184
|
+
// (Do not have all displayed text available so only passing placeholder.)
|
|
2185
|
+
this._exit(0, 'commander.helpDisplayed', '(outputHelp)');
|
|
2186
|
+
}
|
|
2132
2187
|
}
|
|
2133
2188
|
}
|
|
2134
2189
|
|
|
@@ -2137,7 +2192,7 @@ function outputHelpIfRequested(cmd, args) {
|
|
|
2137
2192
|
*
|
|
2138
2193
|
* @param {string[]} args - array of arguments from node.execArgv
|
|
2139
2194
|
* @returns {string[]}
|
|
2140
|
-
* @
|
|
2195
|
+
* @private
|
|
2141
2196
|
*/
|
|
2142
2197
|
|
|
2143
2198
|
function incrementNodeInspectorPort(args) {
|
|
@@ -2179,18 +2234,4 @@ function incrementNodeInspectorPort(args) {
|
|
|
2179
2234
|
});
|
|
2180
2235
|
}
|
|
2181
2236
|
|
|
2182
|
-
/**
|
|
2183
|
-
* @param {Command} startCommand
|
|
2184
|
-
* @returns {Command[]}
|
|
2185
|
-
* @api private
|
|
2186
|
-
*/
|
|
2187
|
-
|
|
2188
|
-
function getCommandAndParents(startCommand) {
|
|
2189
|
-
const result = [];
|
|
2190
|
-
for (let command = startCommand; command; command = command.parent) {
|
|
2191
|
-
result.push(command);
|
|
2192
|
-
}
|
|
2193
|
-
return result;
|
|
2194
|
-
}
|
|
2195
|
-
|
|
2196
2237
|
exports.Command = Command;
|