@@ -1018,6 +1018,11 @@ equality.
10181018
10191019<!-- YAML
10201020added: REPLACEME
1021+ changes:
1022+ - version: REPLACEME
1023+ pr-url: https://github.com/nodejs/node/pull/43459
1024+ description: add support for returning detailed parse information
1025+ using `tokens` in input `config` and returned properties.
10211026-->
10221027
10231028> Stability: 1 - Experimental
@@ -1034,18 +1039,24 @@ added: REPLACEME
10341039 times. If ` true ` , all values will be collected in an array. If
10351040 ` false ` , values for the option are last-wins. ** Default:** ` false ` .
10361041 * ` short ` {string} A single character alias for the option.
1037- * ` strict ` : {boolean} Should an error be thrown when unknown arguments
1042+ * ` strict ` {boolean} Should an error be thrown when unknown arguments
10381043 are encountered, or when arguments are passed that do not match the
10391044 ` type ` configured in ` options ` .
10401045 ** Default:** ` true ` .
1041- * ` allowPositionals ` : {boolean} Whether this command accepts positional
1046+ * ` allowPositionals ` {boolean} Whether this command accepts positional
10421047 arguments.
10431048 ** Default:** ` false ` if ` strict ` is ` true ` , otherwise ` true ` .
1049+ * ` tokens ` {boolean} Return the parsed tokens. This is useful for extending
1050+ the built-in behavior, from adding additional checks through to reprocessing
1051+ the tokens in different ways.
1052+ ** Default:** ` false ` .
10441053
10451054* Returns: {Object} The parsed command line arguments:
10461055 * ` values ` {Object} A mapping of parsed option names with their {string}
10471056 or {boolean} values.
10481057 * ` positionals ` {string\[ ] } Positional arguments.
1058+ * ` tokens ` {Object\[ ] | undefined} See [ parseArgs tokens] ( #parseargs-tokens )
1059+ section. Only returned if ` config ` includes ` tokens: true ` .
10491060
10501061Provides a higher level API for command-line argument parsing than interacting
10511062with ` process.argv ` directly. Takes a specification for the expected arguments
@@ -1094,6 +1105,114 @@ console.log(values, positionals);
10941105` util.parseArgs ` is experimental and behavior may change. Join the
10951106conversation in [ pkgjs/parseargs] [ ] to contribute to the design.
10961107
1108+ ### ` parseArgs ` ` tokens `
1109+
1110+ Detailed parse information is available for adding custom behaviours by
1111+ specifying ` tokens: true ` in the configuration.
1112+ The returned tokens have properties describing:
1113+
1114+ * all tokens
1115+ * ` kind ` {string} One of 'option', 'positional', or 'option-terminator'.
1116+ * ` index ` {number} Index of element in ` args ` containing token. So the
1117+ source argument for a token is ` args[token.index] ` .
1118+ * option tokens
1119+ * ` name ` {string} Long name of option.
1120+ * ` rawName ` {string} How option used in args, like ` -f ` of ` --foo ` .
1121+ * ` value ` {string | undefined} Option value specified in args.
1122+ Undefined for boolean options.
1123+ * ` inlineValue ` {boolean | undefined} Whether option value specified inline,
1124+ like ` --foo=bar ` .
1125+ * positional tokens
1126+ * ` value ` {string} The value of the positional argument in args (i.e. ` args[index] ` ).
1127+ * option-terminator token
1128+
1129+ The returned tokens are in the order encountered in the input args. Options
1130+ that appear more than once in args produce a token for each use. Short option
1131+ groups like ` -xy ` expand to a token for each option. So ` -xxx ` produces
1132+ three tokens.
1133+
1134+ For example to use the returned tokens to add support for a negated option
1135+ like ` --no-color ` , the tokens can be reprocessed to change the value stored
1136+ for the negated option.
1137+
1138+ ``` mjs
1139+ import { parseArgs } from ' node:util' ;
1140+
1141+ const options = {
1142+ ' color' : { type: ' boolean' },
1143+ ' no-color' : { type: ' boolean' },
1144+ ' logfile' : { type: ' string' },
1145+ ' no-logfile' : { type: ' boolean' },
1146+ };
1147+ const { values , tokens } = parseArgs ({ options, tokens: true });
1148+
1149+ // Reprocess the option tokens and overwrite the returned values.
1150+ tokens
1151+ .filter ((token ) => token .kind === ' option' )
1152+ .forEach ((token ) => {
1153+ if (token .name .startsWith (' no-' )) {
1154+ // Store foo:false for --no-foo
1155+ const positiveName = token .name .slice (3 );
1156+ values[positiveName] = false ;
1157+ delete values[token .name ];
1158+ } else {
1159+ // Resave value so last one wins if both --foo and --no-foo.
1160+ values[token .name ] = token .value ?? true ;
1161+ }
1162+ });
1163+
1164+ const color = values .color ;
1165+ const logfile = values .logfile ?? ' default.log' ;
1166+
1167+ console .log ({ logfile, color });
1168+ ` ` `
1169+
1170+ ` ` ` cjs
1171+ const { parseArgs } = require (' node:util' );
1172+
1173+ const options = {
1174+ ' color' : { type: ' boolean' },
1175+ ' no-color' : { type: ' boolean' },
1176+ ' logfile' : { type: ' string' },
1177+ ' no-logfile' : { type: ' boolean' },
1178+ };
1179+ const { values , tokens } = parseArgs ({ options, tokens: true });
1180+
1181+ // Reprocess the option tokens and overwrite the returned values.
1182+ tokens
1183+ .filter ((token ) => token .kind === ' option' )
1184+ .forEach ((token ) => {
1185+ if (token .name .startsWith (' no-' )) {
1186+ // Store foo:false for --no-foo
1187+ const positiveName = token .name .slice (3 );
1188+ values[positiveName] = false ;
1189+ delete values[token .name ];
1190+ } else {
1191+ // Resave value so last one wins if both --foo and --no-foo.
1192+ values[token .name ] = token .value ?? true ;
1193+ }
1194+ });
1195+
1196+ const color = values .color ;
1197+ const logfile = values .logfile ?? ' default.log' ;
1198+
1199+ console .log ({ logfile, color });
1200+ ` ` `
1201+
1202+ Example usage showing negated options, and when an option is used
1203+ multiple ways then last one wins.
1204+
1205+ ` ` ` console
1206+ $ node negate .js
1207+ { logfile: ' default.log' , color: undefined }
1208+ $ node negate .js -- no- logfile -- no- color
1209+ { logfile: false , color: false }
1210+ $ node negate .js -- logfile= test .log -- color
1211+ { logfile: ' test.log' , color: true }
1212+ $ node negate .js -- no- logfile -- logfile= test .log -- color -- no- color
1213+ { logfile: ' test.log' , color: false }
1214+ ` ` `
1215+
10971216## ` util .promisify (original)`
10981217
10991218<!-- YAML
0 commit comments