3
3
4
4
[ ![ Coverage] [ coverage-image ]] [ coverage-url ]
5
5
6
- Polyfill of proposal for ` util.parseArgs() `
6
+ Polyfill of ` util.parseArgs() `
7
7
8
8
## ` util.parseArgs([config]) `
9
9
10
10
<!-- YAML
11
- added: REPLACEME
11
+ added: v18.3.0
12
+ changes:
13
+ - version: REPLACEME
14
+ pr-url: https://github.com/nodejs/node/pull/43459
15
+ description: add support for returning detailed parse information
16
+ using `tokens` in input `config` and returned properties.
12
17
-->
13
18
14
19
> Stability: 1 - Experimental
@@ -25,18 +30,24 @@ added: REPLACEME
25
30
times. If ` true ` , all values will be collected in an array. If
26
31
` false ` , values for the option are last-wins. ** Default:** ` false ` .
27
32
* ` short ` {string} A single character alias for the option.
28
- * ` strict ` : {boolean} Should an error be thrown when unknown arguments
33
+ * ` strict ` {boolean} Should an error be thrown when unknown arguments
29
34
are encountered, or when arguments are passed that do not match the
30
35
` type ` configured in ` options ` .
31
36
** Default:** ` true ` .
32
- * ` allowPositionals ` : {boolean} Whether this command accepts positional
37
+ * ` allowPositionals ` {boolean} Whether this command accepts positional
33
38
arguments.
34
39
** Default:** ` false ` if ` strict ` is ` true ` , otherwise ` true ` .
40
+ * ` tokens ` {boolean} Return the parsed tokens. This is useful for extending
41
+ the built-in behavior, from adding additional checks through to reprocessing
42
+ the tokens in different ways.
43
+ ** Default:** ` false ` .
35
44
36
45
* Returns: {Object} The parsed command line arguments:
37
46
* ` values ` {Object} A mapping of parsed option names with their {string}
38
47
or {boolean} values.
39
48
* ` positionals ` {string\[ ] } Positional arguments.
49
+ * ` tokens ` {Object\[ ] | undefined} See [ parseArgs tokens] ( #parseargs-tokens )
50
+ section. Only returned if ` config ` includes ` tokens: true ` .
40
51
41
52
Provides a higher level API for command-line argument parsing than interacting
42
53
with ` process.argv ` directly. Takes a specification for the expected arguments
@@ -79,12 +90,120 @@ const {
79
90
positionals
80
91
} = parseArgs ({ args, options });
81
92
console .log (values, positionals);
82
- // Prints: [Object: null prototype] { foo: true, bar: 'b' } []ss
93
+ // Prints: [Object: null prototype] { foo: true, bar: 'b' } []
83
94
```
84
95
85
96
` util.parseArgs ` is experimental and behavior may change. Join the
86
97
conversation in [ pkgjs/parseargs] [ ] to contribute to the design.
87
98
99
+ ### ` parseArgs ` ` tokens `
100
+
101
+ Detailed parse information is available for adding custom behaviours by
102
+ specifying ` tokens: true ` in the configuration.
103
+ The returned tokens have properties describing:
104
+
105
+ * all tokens
106
+ * ` kind ` {string} One of 'option', 'positional', or 'option-terminator'.
107
+ * ` index ` {number} Index of element in ` args ` containing token. So the
108
+ source argument for a token is ` args[token.index] ` .
109
+ * option tokens
110
+ * ` name ` {string} Long name of option.
111
+ * ` rawName ` {string} How option used in args, like ` -f ` of ` --foo ` .
112
+ * ` value ` {string | undefined} Option value specified in args.
113
+ Undefined for boolean options.
114
+ * ` inlineValue ` {boolean | undefined} Whether option value specified inline,
115
+ like ` --foo=bar ` .
116
+ * positional tokens
117
+ * ` value ` {string} The value of the positional argument in args (i.e. ` args[index] ` ).
118
+ * option-terminator token
119
+
120
+ The returned tokens are in the order encountered in the input args. Options
121
+ that appear more than once in args produce a token for each use. Short option
122
+ groups like ` -xy ` expand to a token for each option. So ` -xxx ` produces
123
+ three tokens.
124
+
125
+ For example to use the returned tokens to add support for a negated option
126
+ like ` --no-color ` , the tokens can be reprocessed to change the value stored
127
+ for the negated option.
128
+
129
+ ``` mjs
130
+ import { parseArgs } from ' node:util' ;
131
+
132
+ const options = {
133
+ ' color' : { type: ' boolean' },
134
+ ' no-color' : { type: ' boolean' },
135
+ ' logfile' : { type: ' string' },
136
+ ' no-logfile' : { type: ' boolean' },
137
+ };
138
+ const { values , tokens } = parseArgs ({ options, tokens: true });
139
+
140
+ // Reprocess the option tokens and overwrite the returned values.
141
+ tokens
142
+ .filter ((token ) => token .kind === ' option' )
143
+ .forEach ((token ) => {
144
+ if (token .name .startsWith (' no-' )) {
145
+ // Store foo:false for --no-foo
146
+ const positiveName = token .name .slice (3 );
147
+ values[positiveName] = false ;
148
+ delete values[token .name ];
149
+ } else {
150
+ // Resave value so last one wins if both --foo and --no-foo.
151
+ values[token .name ] = token .value ?? true ;
152
+ }
153
+ });
154
+
155
+ const color = values .color ;
156
+ const logfile = values .logfile ?? ' default.log' ;
157
+
158
+ console .log ({ logfile, color });
159
+ ` ` `
160
+
161
+ ` ` ` cjs
162
+ const { parseArgs } = require (' node:util' );
163
+
164
+ const options = {
165
+ ' color' : { type: ' boolean' },
166
+ ' no-color' : { type: ' boolean' },
167
+ ' logfile' : { type: ' string' },
168
+ ' no-logfile' : { type: ' boolean' },
169
+ };
170
+ const { values , tokens } = parseArgs ({ options, tokens: true });
171
+
172
+ // Reprocess the option tokens and overwrite the returned values.
173
+ tokens
174
+ .filter ((token ) => token .kind === ' option' )
175
+ .forEach ((token ) => {
176
+ if (token .name .startsWith (' no-' )) {
177
+ // Store foo:false for --no-foo
178
+ const positiveName = token .name .slice (3 );
179
+ values[positiveName] = false ;
180
+ delete values[token .name ];
181
+ } else {
182
+ // Resave value so last one wins if both --foo and --no-foo.
183
+ values[token .name ] = token .value ?? true ;
184
+ }
185
+ });
186
+
187
+ const color = values .color ;
188
+ const logfile = values .logfile ?? ' default.log' ;
189
+
190
+ console .log ({ logfile, color });
191
+ ` ` `
192
+
193
+ Example usage showing negated options, and when an option is used
194
+ multiple ways then last one wins.
195
+
196
+ ` ` ` console
197
+ $ node negate .js
198
+ { logfile: ' default.log' , color: undefined }
199
+ $ node negate .js -- no- logfile -- no- color
200
+ { logfile: false , color: false }
201
+ $ node negate .js -- logfile= test .log -- color
202
+ { logfile: ' test.log' , color: true }
203
+ $ node negate .js -- no- logfile -- logfile= test .log -- color -- no- color
204
+ { logfile: ' test.log' , color: false }
205
+ ` ` `
206
+
88
207
-----
89
208
90
209
<!-- omit in toc -->
0 commit comments