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