|
1 | 1 | # util-parseargs |
2 | 2 | Polyfill of future proposal for `util.parseArgs()` |
| 3 | + |
| 4 | +### Links & Resources |
| 5 | + |
| 6 | +* [Initial Tooling Issue](https://github.com/nodejs/tooling/issues/19) |
| 7 | +* [Initial Proposal](https://github.com/nodejs/node/pull/35015) |
| 8 | + |
| 9 | +---- |
| 10 | + |
| 11 | +## `process.mainArgs` Proposal |
| 12 | + |
| 13 | +> Note: This can be moved forward independently of the `util.parseArgs()` proposal/work. |
| 14 | + |
| 15 | +### Implementation: |
| 16 | + |
| 17 | +```javascript |
| 18 | +process.mainArgs = process.argv.slice(process._exec ? 1 : 2) |
| 19 | +``` |
| 20 | + |
| 21 | +--- |
| 22 | + |
| 23 | +## `util.parseArgs([argv][, options])` Proposal |
| 24 | + |
| 25 | +* `argv` {string[]} (Optional) Array of argument strings; defaults |
| 26 | + to [`process.mainArgs`](process_argv) |
| 27 | +* `options` {Object} (Optional) The `options` parameter is an |
| 28 | + object supporting the following properties: |
| 29 | + * `withValue` {string[]} (Optional) An `Array` of argument |
| 30 | + strings which expect a value to be defined in `argv` (see [Options][] |
| 31 | + for details) |
| 32 | + * `multiples` {string[]} (Optional) An `Array` of argument |
| 33 | + strings which, when appearing multiple times in `argv`, will be concatenated |
| 34 | +into an `Array` |
| 35 | + * `short` {Object} (Optional) An `Object` of key, value pairs of strings which map a "short" alias to an argument; When appearing multiples times in `argv`; Respects `withValue` & `multiples` |
| 36 | + * `strict` {Boolean} (Optional) A `Boolean` on wheather or not to throw an error when unknown args are encountered |
| 37 | +* Returns: {Object} An object having properties: |
| 38 | + * `args` {Object}, having properties and `Boolean` values corresponding to parsed options passed |
| 39 | + * `values` {Object}, have properties and `String` values corresponding to parsed options passed |
| 40 | + * `positionals` {string[]}, containing [Positionals][] |
| 41 | + |
| 42 | +--- |
| 43 | + |
| 44 | +## Examples w/ Output |
| 45 | + |
| 46 | +```js |
| 47 | +const { parseArgs } = require('util') |
| 48 | +``` |
| 49 | + |
| 50 | +```js |
| 51 | +// default |
| 52 | +const argv = ['-f', '--foo=a', '--foo', 'b'] |
| 53 | +const options = {} |
| 54 | +const { args, values, positionals } = parseArgs(argv, options) |
| 55 | +args // { f: true, foo: true} |
| 56 | +values // { f: [undefined], foo: [undefined] } |
| 57 | +positionals // ['b'] |
| 58 | +``` |
| 59 | +```js |
| 60 | +// withValue |
| 61 | +const argv = ['-f', '--foo=a', '--foo', 'b'] |
| 62 | +const options = { |
| 63 | + withValue: ['foo'] |
| 64 | +} |
| 65 | +const { args, values, positionals } = parseArgs(argv, options) |
| 66 | +args // { f: true, foo: true} |
| 67 | +values // { f: [undefined], foo: ['b'] } |
| 68 | +positionals // [] |
| 69 | +``` |
| 70 | +```js |
| 71 | +// withValue & multiples |
| 72 | +const argv = ['-f', '--foo=a', '--foo', 'b'] |
| 73 | +const options = { |
| 74 | + withValue: ['foo'], |
| 75 | + multiples: ['foo'] |
| 76 | +} |
| 77 | +const { args, values, positionals } = parseArgs(argv, options) |
| 78 | +args // { f: true, foo: true} |
| 79 | +values // { f: [undefined], foo: ['a','b'] } |
| 80 | +positionals // [] |
| 81 | +``` |
| 82 | +```js |
| 83 | +// shorts |
| 84 | +const argv = ['-f', '--foo=a', '--foo', 'b'] |
| 85 | +const options = { |
| 86 | + short: { f: 'foo' } |
| 87 | +} |
| 88 | +const { args, values, positionals } = parseArgs(argv, options) |
| 89 | +args // { foo: true} |
| 90 | +values // { foo: [undefined] } |
| 91 | +positionals // ['b'] |
| 92 | +``` |
| 93 | + |
| 94 | +### F.A.Qs |
| 95 | + |
| 96 | +- Is `cmd --foo=bar baz` the same as `cmd baz --foo=bar`? |
| 97 | + - Yes, if `withValue: ['foo']`, otherwise no |
| 98 | +- Does the parser execute a function? |
| 99 | + - no |
| 100 | +- Does the parser execute one of several functions, depending on input? |
| 101 | + - no |
| 102 | +- Can subcommands take options that are distinct from the main command? |
| 103 | + - no (this might be a problem? at least it's a more definitive "opinion") |
| 104 | +- Does it output generated help when no options match? |
| 105 | + - no |
| 106 | +- Does it generated short usage? Like: `usage: ls [-ABCFGHLOPRSTUWabcdefghiklmnopqrstuwx1] [file ...]` |
| 107 | + - no (no usage/help at all) |
| 108 | +- Does the user provide the long usage text? For each option? For the whole command? |
| 109 | + - no |
| 110 | +- Do subcommands (if implemented) have their own usage output? |
| 111 | + - no |
| 112 | +- Does usage print if the user runs `cmd --help`? |
| 113 | + - no |
| 114 | +- Does it set `process.exitCode`? |
| 115 | + - no |
| 116 | +- Does usage print to stderr or stdout? |
| 117 | + - N/A |
| 118 | +- Does it check types? (Say, specify that an option is a boolean, number, etc.) |
| 119 | + - no |
| 120 | +- Can an option have more than one type? (string or false, for example) |
| 121 | + - no |
| 122 | +- Can the user define a type? (Say, `type: path` to call `path.resolve()` on the argument.) |
| 123 | + - no |
| 124 | +- Does a `--foo=0o22` mean 0, 22, 18, or "0o22"? |
| 125 | + - `"0o22"` |
| 126 | +- Does it coerce types? |
| 127 | + - no |
| 128 | +- Does `--no-foo` coerce to `--foo=false`? For all flags? Only boolean flags? |
| 129 | + - no, it sets `{args:{'no-foo': true}}` |
| 130 | +- Is `--foo` the same as `--foo=true`? Only for known booleans? Only at the end? |
| 131 | + - no, `--foo` is the same as `--foo=` |
| 132 | +- Does it read environment variables? Ie, is `FOO=1 cmd` the same as `cmd --foo=1`? |
| 133 | + - no |
| 134 | +- Do unknown arguments raise an error? Are they parsed? Are they treated as positional arguments? |
| 135 | + - no, they are parsed, not treated as positionals |
| 136 | +- Does `--` signal the end of flags/options? |
| 137 | + - **open question** |
| 138 | + - If `--` signals the end, is `--` included as a positional? is `program -- foo` the same as `program foo`? Are both `{positionals:['foo']}`, or is the first one `{positionals:['--', 'foo']}`? |
| 139 | +- Does the API specify whether a `--` was present/relevant? |
| 140 | + - no |
| 141 | +- Is `-foo` the same as `--foo`? |
| 142 | + - yes <-- ! kind of a blocker for shortopts ! |
| 143 | + - Recommend: "No, -foo is shortopts form of --f --o --o" (assuming none are defined, or withValues) |
| 144 | +- Is `---foo` the same as `--foo`? |
| 145 | + - no |
| 146 | + - the first flag would be parsed as `'-foo'` |
| 147 | + - the second flag would be parsed as `'foo'` |
| 148 | +- Is `-` a positional? ie, `bash some-test.sh | tap -` |
| 149 | + - no |
0 commit comments