@@ -1024,6 +1024,11 @@ equality.
10241024
10251025<!-- YAML
10261026added: v18.3.0
1027+ changes:
1028+ - version: REPLACEME
1029+ pr-url: https://github.com/nodejs/node/pull/43459
1030+ description: add support for returning detailed parse information
1031+ using `tokens` in input `config` and returned properties.
10271032-->
10281033
10291034> Stability: 1 - Experimental
@@ -1040,18 +1045,24 @@ added: v18.3.0
10401045 times. If ` true ` , all values will be collected in an array. If
10411046 ` false ` , values for the option are last-wins. ** Default:** ` false ` .
10421047 * ` short ` {string} A single character alias for the option.
1043- * ` strict ` : {boolean} Should an error be thrown when unknown arguments
1048+ * ` strict ` {boolean} Should an error be thrown when unknown arguments
10441049 are encountered, or when arguments are passed that do not match the
10451050 ` type ` configured in ` options ` .
10461051 ** Default:** ` true ` .
1047- * ` allowPositionals ` : {boolean} Whether this command accepts positional
1052+ * ` allowPositionals ` {boolean} Whether this command accepts positional
10481053 arguments.
10491054 ** Default:** ` false ` if ` strict ` is ` true ` , otherwise ` true ` .
1055+ * ` tokens ` {boolean} Return the parsed tokens. This is useful for extending
1056+ the built-in behavior, from adding additional checks through to reprocessing
1057+ the tokens in different ways.
1058+ ** Default:** ` false ` .
10501059
10511060* Returns: {Object} The parsed command line arguments:
10521061 * ` values ` {Object} A mapping of parsed option names with their {string}
10531062 or {boolean} values.
10541063 * ` positionals ` {string\[ ] } Positional arguments.
1064+ * ` tokens ` {Object\[ ] | undefined} See [ parseArgs tokens] ( #parseargs-tokens )
1065+ section. Only returned if ` config ` includes ` tokens: true ` .
10551066
10561067Provides a higher level API for command-line argument parsing than interacting
10571068with ` process.argv ` directly. Takes a specification for the expected arguments
@@ -1100,6 +1111,114 @@ console.log(values, positionals);
11001111` util.parseArgs ` is experimental and behavior may change. Join the
11011112conversation in [ pkgjs/parseargs] [ ] to contribute to the design.
11021113
1114+ ### ` parseArgs ` ` tokens `
1115+
1116+ Detailed parse information is available for adding custom behaviours by
1117+ specifying ` tokens: true ` in the configuration.
1118+ The returned tokens have properties describing:
1119+
1120+ * all tokens
1121+ * ` kind ` {string} One of 'option', 'positional', or 'option-terminator'.
1122+ * ` index ` {number} Index of element in ` args ` containing token. So the
1123+ source argument for a token is ` args[token.index] ` .
1124+ * option tokens
1125+ * ` name ` {string} Long name of option.
1126+ * ` rawName ` {string} How option used in args, like ` -f ` of ` --foo ` .
1127+ * ` value ` {string | undefined} Option value specified in args.
1128+ Undefined for boolean options.
1129+ * ` inlineValue ` {boolean | undefined} Whether option value specified inline,
1130+ like ` --foo=bar ` .
1131+ * positional tokens
1132+ * ` value ` {string} The value of the positional argument in args (i.e. ` args[index] ` ).
1133+ * option-terminator token
1134+
1135+ The returned tokens are in the order encountered in the input args. Options
1136+ that appear more than once in args produce a token for each use. Short option
1137+ groups like ` -xy ` expand to a token for each option. So ` -xxx ` produces
1138+ three tokens.
1139+
1140+ For example to use the returned tokens to add support for a negated option
1141+ like ` --no-color ` , the tokens can be reprocessed to change the value stored
1142+ for the negated option.
1143+
1144+ ``` mjs
1145+ import { parseArgs } from ' node:util' ;
1146+
1147+ const options = {
1148+ ' color' : { type: ' boolean' },
1149+ ' no-color' : { type: ' boolean' },
1150+ ' logfile' : { type: ' string' },
1151+ ' no-logfile' : { type: ' boolean' },
1152+ };
1153+ const { values , tokens } = parseArgs ({ options, tokens: true });
1154+
1155+ // Reprocess the option tokens and overwrite the returned values.
1156+ tokens
1157+ .filter ((token ) => token .kind === ' option' )
1158+ .forEach ((token ) => {
1159+ if (token .name .startsWith (' no-' )) {
1160+ // Store foo:false for --no-foo
1161+ const positiveName = token .name .slice (3 );
1162+ values[positiveName] = false ;
1163+ delete values[token .name ];
1164+ } else {
1165+ // Resave value so last one wins if both --foo and --no-foo.
1166+ values[token .name ] = token .value ?? true ;
1167+ }
1168+ });
1169+
1170+ const color = values .color ;
1171+ const logfile = values .logfile ?? ' default.log' ;
1172+
1173+ console .log ({ logfile, color });
1174+ ` ` `
1175+
1176+ ` ` ` cjs
1177+ const { parseArgs } = require (' node:util' );
1178+
1179+ const options = {
1180+ ' color' : { type: ' boolean' },
1181+ ' no-color' : { type: ' boolean' },
1182+ ' logfile' : { type: ' string' },
1183+ ' no-logfile' : { type: ' boolean' },
1184+ };
1185+ const { values , tokens } = parseArgs ({ options, tokens: true });
1186+
1187+ // Reprocess the option tokens and overwrite the returned values.
1188+ tokens
1189+ .filter ((token ) => token .kind === ' option' )
1190+ .forEach ((token ) => {
1191+ if (token .name .startsWith (' no-' )) {
1192+ // Store foo:false for --no-foo
1193+ const positiveName = token .name .slice (3 );
1194+ values[positiveName] = false ;
1195+ delete values[token .name ];
1196+ } else {
1197+ // Resave value so last one wins if both --foo and --no-foo.
1198+ values[token .name ] = token .value ?? true ;
1199+ }
1200+ });
1201+
1202+ const color = values .color ;
1203+ const logfile = values .logfile ?? ' default.log' ;
1204+
1205+ console .log ({ logfile, color });
1206+ ` ` `
1207+
1208+ Example usage showing negated options, and when an option is used
1209+ multiple ways then last one wins.
1210+
1211+ ` ` ` console
1212+ $ node negate .js
1213+ { logfile: ' default.log' , color: undefined }
1214+ $ node negate .js -- no- logfile -- no- color
1215+ { logfile: false , color: false }
1216+ $ node negate .js -- logfile= test .log -- color
1217+ { logfile: ' test.log' , color: true }
1218+ $ node negate .js -- no- logfile -- logfile= test .log -- color -- no- color
1219+ { logfile: ' test.log' , color: false }
1220+ ` ` `
1221+
11031222## ` util .promisify (original)`
11041223
11051224<!-- YAML
0 commit comments