@@ -334,22 +334,19 @@ Command.prototype.action = function(fn) {
334
334
outputHelpIfRequested ( self , parsed . unknown ) ;
335
335
self . _checkForMissingMandatoryOptions ( ) ;
336
336
337
- // If there are still any unknown options, then we simply
338
- // die, unless someone asked for help, in which case we give it
339
- // to them, and then we die.
337
+ // If there are still any unknown options, then we simply die.
340
338
if ( parsed . unknown . length > 0 ) {
341
339
self . unknownOption ( parsed . unknown [ 0 ] ) ;
342
340
}
343
341
344
- // Leftover arguments need to be pushed back. Fixes issue #56
345
- if ( parsed . args . length ) args = parsed . args . concat ( args ) ;
342
+ args = args . concat ( parsed . operands , parsed . unknown ) ;
346
343
347
- self . _args . forEach ( function ( arg , i ) {
348
- if ( arg . required && args [ i ] == null ) {
349
- self . missingArgument ( arg . name ) ;
350
- } else if ( arg . variadic ) {
344
+ self . _args . forEach ( function ( expectedArg , i ) {
345
+ if ( expectedArg . required && args [ i ] == null ) {
346
+ self . missingArgument ( expectedArg . name ) ;
347
+ } else if ( expectedArg . variadic ) {
351
348
if ( i !== self . _args . length - 1 ) {
352
- self . variadicArgNotLast ( arg . name ) ;
349
+ self . variadicArgNotLast ( expectedArg . name ) ;
353
350
}
354
351
355
352
args [ i ] = args . splice ( i ) ;
@@ -641,11 +638,12 @@ Command.prototype.parse = function(argv) {
641
638
}
642
639
643
640
// process argv
644
- var normalized = this . normalize ( argv . slice ( 2 ) ) ;
645
- var parsed = this . parseOptions ( normalized ) ;
646
- var args = this . args = parsed . args ;
641
+ const normalized = this . normalize ( argv . slice ( 2 ) ) ;
642
+ const parsed = this . parseOptions ( normalized ) ;
643
+ const args = parsed . operands . concat ( parsed . unknown ) ;
644
+ this . args = args . slice ( ) ;
647
645
648
- var result = this . parseArgs ( this . args , parsed . unknown ) ;
646
+ var result = this . parseArgs ( parsed . operands , parsed . unknown ) ;
649
647
650
648
if ( args [ 0 ] === 'help' && args . length === 1 ) this . help ( ) ;
651
649
@@ -695,7 +693,7 @@ Command.prototype.parse = function(argv) {
695
693
}
696
694
697
695
if ( this . _execs . has ( name ) ) {
698
- return this . executeSubCommand ( argv , args , parsed . unknown , subCommand ? subCommand . _executableFile : undefined ) ;
696
+ return this . executeSubCommand ( argv , args , subCommand ? subCommand . _executableFile : undefined ) ;
699
697
}
700
698
701
699
return result ;
@@ -725,9 +723,7 @@ Command.prototype.parseAsync = function(argv) {
725
723
* @api private
726
724
*/
727
725
728
- Command . prototype . executeSubCommand = function ( argv , args , unknown , executableFile ) {
729
- args = args . concat ( unknown ) ;
730
-
726
+ Command . prototype . executeSubCommand = function ( argv , args , executableFile ) {
731
727
if ( ! args . length ) this . help ( ) ;
732
728
733
729
var isExplicitJS = false ; // Whether to use node to launch "executable"
@@ -889,16 +885,14 @@ Command.prototype.normalize = function(args) {
889
885
* @api private
890
886
*/
891
887
892
- Command . prototype . parseArgs = function ( args , unknown ) {
893
- var name ;
894
-
895
- if ( args . length ) {
896
- name = args [ 0 ] ;
888
+ Command . prototype . parseArgs = function ( operands , unknown ) {
889
+ if ( operands . length ) {
890
+ const name = operands [ 0 ] ;
897
891
if ( this . listeners ( 'command:' + name ) . length ) {
898
- this . emit ( 'command:' + args . shift ( ) , args , unknown ) ;
892
+ this . emit ( 'command:' + operands [ 0 ] , operands . slice ( 1 ) , unknown ) ;
899
893
} else {
900
- this . emit ( 'program-command' , args , unknown ) ;
901
- this . emit ( 'command:*' , args , unknown ) ;
894
+ this . emit ( 'program-command' , operands , unknown ) ;
895
+ this . emit ( 'command:*' , operands , unknown ) ;
902
896
}
903
897
} else {
904
898
outputHelpIfRequested ( this , unknown ) ;
@@ -926,11 +920,7 @@ Command.prototype.parseArgs = function(args, unknown) {
926
920
*/
927
921
928
922
Command . prototype . optionFor = function ( arg ) {
929
- for ( var i = 0 , len = this . options . length ; i < len ; ++ i ) {
930
- if ( this . options [ i ] . is ( arg ) ) {
931
- return this . options [ i ] ;
932
- }
933
- }
923
+ return this . options . find ( option => option . is ( arg ) ) ;
934
924
} ;
935
925
936
926
/**
@@ -951,82 +941,79 @@ Command.prototype._checkForMissingMandatoryOptions = function() {
951
941
} ;
952
942
953
943
/**
954
- * Parse options from `argv` returning `argv`
955
- * void of these options .
944
+ * Parse options from `argv` removing known options,
945
+ * and return argv split into operands and unknown arguments .
956
946
*
957
- * @param {Array } argv
958
- * @return {{args: Array, unknown: Array} }
947
+ * Examples:
948
+ *
949
+ * argv => operands, unknown
950
+ * --known kkk op => [op], []
951
+ * op --known kkk => [op], []
952
+ * sub --unknown uuu op => [sub], [--unknown uuu op]
953
+ * sub -- --unknown uuu op => [sub --unknown uuu op], []
954
+ *
955
+ * @param {String[] } argv
956
+ * @return {{operands: String[], unknown: String[]} }
959
957
* @api public
960
958
*/
961
959
962
960
Command . prototype . parseOptions = function ( argv ) {
963
- var args = [ ] ,
964
- len = argv . length ,
965
- literal ,
966
- option ,
967
- arg ;
968
-
969
- var unknownOptions = [ ] ;
961
+ const operands = [ ] ; // operands, not options or values
962
+ const unknown = [ ] ; // first unknown option and remaining unknown args
963
+ let literal = false ;
964
+ let dest = operands ;
970
965
971
966
// parse options
972
- for ( var i = 0 ; i < len ; ++ i ) {
973
- arg = argv [ i ] ;
967
+ for ( var i = 0 ; i < argv . length ; ++ i ) {
968
+ const arg = argv [ i ] ;
974
969
975
970
// literal args after --
976
971
if ( literal ) {
977
- args . push ( arg ) ;
972
+ dest . push ( arg ) ;
978
973
continue ;
979
974
}
980
975
981
976
if ( arg === '--' ) {
982
977
literal = true ;
978
+ if ( dest === unknown ) dest . push ( '--' ) ;
983
979
continue ;
984
980
}
985
981
986
982
// find matching Option
987
- option = this . optionFor ( arg ) ;
983
+ const option = this . optionFor ( arg ) ;
988
984
989
- // option is defined
985
+ // recognised option, call listener to assign value with possible custom processing
990
986
if ( option ) {
991
- // requires arg
992
987
if ( option . required ) {
993
- arg = argv [ ++ i ] ;
994
- if ( arg == null ) return this . optionMissingArgument ( option ) ;
995
- this . emit ( 'option:' + option . name ( ) , arg ) ;
996
- // optional arg
988
+ const value = argv [ ++ i ] ;
989
+ if ( value === undefined ) this . optionMissingArgument ( option ) ;
990
+ this . emit ( 'option:' + option . name ( ) , value ) ;
997
991
} else if ( option . optional ) {
998
- arg = argv [ i + 1 ] ;
999
- if ( arg == null || ( arg [ 0 ] === '-' && arg !== '-' ) ) {
1000
- arg = null ;
992
+ let value = argv [ i + 1 ] ;
993
+ // do not use a following option as a value
994
+ if ( value === undefined || ( value [ 0 ] === '-' && value !== '-' ) ) {
995
+ value = null ;
1001
996
} else {
1002
997
++ i ;
1003
998
}
1004
- this . emit ( 'option:' + option . name ( ) , arg ) ;
999
+ this . emit ( 'option:' + option . name ( ) , value ) ;
1005
1000
// flag
1006
1001
} else {
1007
1002
this . emit ( 'option:' + option . name ( ) ) ;
1008
1003
}
1009
1004
continue ;
1010
1005
}
1011
1006
1012
- // looks like an option
1007
+ // looks like an option, unknowns from here
1013
1008
if ( arg . length > 1 && arg [ 0 ] === '-' ) {
1014
- unknownOptions . push ( arg ) ;
1015
-
1016
- // If the next argument looks like it might be
1017
- // an argument for this option, we pass it on.
1018
- // If it isn't, then it'll simply be ignored
1019
- if ( ( i + 1 ) < argv . length && ( argv [ i + 1 ] [ 0 ] !== '-' || argv [ i + 1 ] === '-' ) ) {
1020
- unknownOptions . push ( argv [ ++ i ] ) ;
1021
- }
1022
- continue ;
1009
+ dest = unknown ;
1023
1010
}
1024
1011
1025
1012
// arg
1026
- args . push ( arg ) ;
1013
+ dest . push ( arg ) ;
1027
1014
}
1028
1015
1029
- return { args : args , unknown : unknownOptions } ;
1016
+ return { operands , unknown } ;
1030
1017
} ;
1031
1018
1032
1019
/**
0 commit comments