|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574 |
- A light, featureful and explicit option parsing library for node.js.
-
- [Why another one? See below](#why). tl;dr: The others I've tried are one of
- too loosey goosey (not explicit), too big/too many deps, or ill specified.
- YMMV.
-
- Follow <a href="https://twitter.com/intent/user?screen_name=trentmick" target="_blank">@trentmick</a>
- for updates to node-dashdash.
-
- # Install
-
- npm install dashdash
-
-
- # Usage
-
- ```javascript
- var dashdash = require('dashdash');
-
- // Specify the options. Minimally `name` (or `names`) and `type`
- // must be given for each.
- var options = [
- {
- // `names` or a single `name`. First element is the `opts.KEY`.
- names: ['help', 'h'],
- // See "Option specs" below for types.
- type: 'bool',
- help: 'Print this help and exit.'
- }
- ];
-
- // Shortcut form. As called it infers `process.argv`. See below for
- // the longer form to use methods like `.help()` on the Parser object.
- var opts = dashdash.parse({options: options});
-
- console.log("opts:", opts);
- console.log("args:", opts._args);
- ```
-
-
- # Longer Example
-
- A more realistic [starter script "foo.js"](./examples/foo.js) is as follows.
- This also shows using `parser.help()` for formatted option help.
-
- ```javascript
- var dashdash = require('./lib/dashdash');
-
- var options = [
- {
- name: 'version',
- type: 'bool',
- help: 'Print tool version and exit.'
- },
- {
- names: ['help', 'h'],
- type: 'bool',
- help: 'Print this help and exit.'
- },
- {
- names: ['verbose', 'v'],
- type: 'arrayOfBool',
- help: 'Verbose output. Use multiple times for more verbose.'
- },
- {
- names: ['file', 'f'],
- type: 'string',
- help: 'File to process',
- helpArg: 'FILE'
- }
- ];
-
- var parser = dashdash.createParser({options: options});
- try {
- var opts = parser.parse(process.argv);
- } catch (e) {
- console.error('foo: error: %s', e.message);
- process.exit(1);
- }
-
- console.log("# opts:", opts);
- console.log("# args:", opts._args);
-
- // Use `parser.help()` for formatted options help.
- if (opts.help) {
- var help = parser.help({includeEnv: true}).trimRight();
- console.log('usage: node foo.js [OPTIONS]\n'
- + 'options:\n'
- + help);
- process.exit(0);
- }
-
- // ...
- ```
-
-
- Some example output from this script (foo.js):
-
- ```
- $ node foo.js -h
- # opts: { help: true,
- _order: [ { name: 'help', value: true, from: 'argv' } ],
- _args: [] }
- # args: []
- usage: node foo.js [OPTIONS]
- options:
- --version Print tool version and exit.
- -h, --help Print this help and exit.
- -v, --verbose Verbose output. Use multiple times for more verbose.
- -f FILE, --file=FILE File to process
-
- $ node foo.js -v
- # opts: { verbose: [ true ],
- _order: [ { name: 'verbose', value: true, from: 'argv' } ],
- _args: [] }
- # args: []
-
- $ node foo.js --version arg1
- # opts: { version: true,
- _order: [ { name: 'version', value: true, from: 'argv' } ],
- _args: [ 'arg1' ] }
- # args: [ 'arg1' ]
-
- $ node foo.js -f bar.txt
- # opts: { file: 'bar.txt',
- _order: [ { name: 'file', value: 'bar.txt', from: 'argv' } ],
- _args: [] }
- # args: []
-
- $ node foo.js -vvv --file=blah
- # opts: { verbose: [ true, true, true ],
- file: 'blah',
- _order:
- [ { name: 'verbose', value: true, from: 'argv' },
- { name: 'verbose', value: true, from: 'argv' },
- { name: 'verbose', value: true, from: 'argv' },
- { name: 'file', value: 'blah', from: 'argv' } ],
- _args: [] }
- # args: []
- ```
-
-
- See the ["examples"](examples/) dir for a number of starter examples using
- some of dashdash's features.
-
-
- # Environment variable integration
-
- If you want to allow environment variables to specify options to your tool,
- dashdash makes this easy. We can change the 'verbose' option in the example
- above to include an 'env' field:
-
- ```javascript
- {
- names: ['verbose', 'v'],
- type: 'arrayOfBool',
- env: 'FOO_VERBOSE', // <--- add this line
- help: 'Verbose output. Use multiple times for more verbose.'
- },
- ```
-
- then the **"FOO_VERBOSE" environment variable** can be used to set this
- option:
-
- ```shell
- $ FOO_VERBOSE=1 node foo.js
- # opts: { verbose: [ true ],
- _order: [ { name: 'verbose', value: true, from: 'env' } ],
- _args: [] }
- # args: []
- ```
-
- Boolean options will interpret the empty string as unset, '0' as false
- and anything else as true.
-
- ```shell
- $ FOO_VERBOSE= node examples/foo.js # not set
- # opts: { _order: [], _args: [] }
- # args: []
-
- $ FOO_VERBOSE=0 node examples/foo.js # '0' is false
- # opts: { verbose: [ false ],
- _order: [ { key: 'verbose', value: false, from: 'env' } ],
- _args: [] }
- # args: []
-
- $ FOO_VERBOSE=1 node examples/foo.js # true
- # opts: { verbose: [ true ],
- _order: [ { key: 'verbose', value: true, from: 'env' } ],
- _args: [] }
- # args: []
-
- $ FOO_VERBOSE=boogabooga node examples/foo.js # true
- # opts: { verbose: [ true ],
- _order: [ { key: 'verbose', value: true, from: 'env' } ],
- _args: [] }
- # args: []
- ```
-
- Non-booleans can be used as well. Strings:
-
- ```shell
- $ FOO_FILE=data.txt node examples/foo.js
- # opts: { file: 'data.txt',
- _order: [ { key: 'file', value: 'data.txt', from: 'env' } ],
- _args: [] }
- # args: []
- ```
-
- Numbers:
-
- ```shell
- $ FOO_TIMEOUT=5000 node examples/foo.js
- # opts: { timeout: 5000,
- _order: [ { key: 'timeout', value: 5000, from: 'env' } ],
- _args: [] }
- # args: []
-
- $ FOO_TIMEOUT=blarg node examples/foo.js
- foo: error: arg for "FOO_TIMEOUT" is not a positive integer: "blarg"
- ```
-
- With the `includeEnv: true` config to `parser.help()` the environment
- variable can also be included in **help output**:
-
- usage: node foo.js [OPTIONS]
- options:
- --version Print tool version and exit.
- -h, --help Print this help and exit.
- -v, --verbose Verbose output. Use multiple times for more verbose.
- Environment: FOO_VERBOSE=1
- -f FILE, --file=FILE File to process
-
-
- # Bash completion
-
- Dashdash provides a simple way to create a Bash completion file that you
- can place in your "bash_completion.d" directory -- sometimes that is
- "/usr/local/etc/bash_completion.d/"). Features:
-
- - Support for short and long opts
- - Support for knowing which options take arguments
- - Support for subcommands (e.g. 'git log <TAB>' to show just options for the
- log subcommand). See
- [node-cmdln](https://github.com/trentm/node-cmdln#bash-completion) for
- how to integrate that.
- - Does the right thing with "--" to stop options.
- - Custom optarg and arg types for custom completions.
-
- Dashdash will return bash completion file content given a parser instance:
-
- var parser = dashdash.createParser({options: options});
- console.log( parser.bashCompletion({name: 'mycli'}) );
-
- or directly from a `options` array of options specs:
-
- var code = dashdash.bashCompletionFromOptions({
- name: 'mycli',
- options: OPTIONS
- });
-
- Write that content to "/usr/local/etc/bash_completion.d/mycli" and you will
- have Bash completions for `mycli`. Alternatively you can write it to
- any file (e.g. "~/.bashrc") and source it.
-
- You could add a `--completion` hidden option to your tool that emits the
- completion content and document for your users to call that to install
- Bash completions.
-
- See [examples/ddcompletion.js](examples/ddcompletion.js) for a complete
- example, including how one can define bash functions for completion of custom
- option types. Also see [node-cmdln](https://github.com/trentm/node-cmdln) for
- how it uses this for Bash completion for full multi-subcommand tools.
-
- - TODO: document specExtra
- - TODO: document includeHidden
- - TODO: document custom types, `function complete\_FOO` guide, completionType
- - TODO: document argtypes
-
-
- # Parser config
-
- Parser construction (i.e. `dashdash.createParser(CONFIG)`) takes the
- following fields:
-
- - `options` (Array of option specs). Required. See the
- [Option specs](#option-specs) section below.
-
- - `interspersed` (Boolean). Optional. Default is true. If true this allows
- interspersed arguments and options. I.e.:
-
- node ./tool.js -v arg1 arg2 -h # '-h' is after interspersed args
-
- Set it to false to have '-h' **not** get parsed as an option in the above
- example.
-
- - `allowUnknown` (Boolean). Optional. Default is false. If false, this causes
- unknown arguments to throw an error. I.e.:
-
- node ./tool.js -v arg1 --afe8asefksjefhas
-
- Set it to true to treat the unknown option as a positional
- argument.
-
- **Caveat**: When a shortopt group, such as `-xaz` contains a mix of
- known and unknown options, the *entire* group is passed through
- unmolested as a positional argument.
-
- Consider if you have a known short option `-a`, and parse the
- following command line:
-
- node ./tool.js -xaz
-
- where `-x` and `-z` are unknown. There are multiple ways to
- interpret this:
-
- 1. `-x` takes a value: `{x: 'az'}`
- 2. `-x` and `-z` are both booleans: `{x:true,a:true,z:true}`
-
- Since dashdash does not know what `-x` and `-z` are, it can't know
- if you'd prefer to receive `{a:true,_args:['-x','-z']}` or
- `{x:'az'}`, or `{_args:['-xaz']}`. Leaving the positional arg unprocessed
- is the easiest mistake for the user to recover from.
-
-
- # Option specs
-
- Example using all fields (required fields are noted):
-
- ```javascript
- {
- names: ['file', 'f'], // Required (one of `names` or `name`).
- type: 'string', // Required.
- completionType: 'filename',
- env: 'MYTOOL_FILE',
- help: 'Config file to load before running "mytool"',
- helpArg: 'PATH',
- helpWrap: false,
- default: path.resolve(process.env.HOME, '.mytoolrc')
- }
- ```
-
- Each option spec in the `options` array must/can have the following fields:
-
- - `name` (String) or `names` (Array). Required. These give the option name
- and aliases. The first name (if more than one given) is the key for the
- parsed `opts` object.
-
- - `type` (String). Required. One of:
-
- - bool
- - string
- - number
- - integer
- - positiveInteger
- - date (epoch seconds, e.g. 1396031701, or ISO 8601 format
- `YYYY-MM-DD[THH:MM:SS[.sss][Z]]`, e.g. "2014-03-28T18:35:01.489Z")
- - arrayOfBool
- - arrayOfString
- - arrayOfNumber
- - arrayOfInteger
- - arrayOfPositiveInteger
- - arrayOfDate
-
- FWIW, these names attempt to match with asserts on
- [assert-plus](https://github.com/mcavage/node-assert-plus).
- You can add your own custom option types with `dashdash.addOptionType`.
- See below.
-
- - `completionType` (String). Optional. This is used for [Bash
- completion](#bash-completion) for an option argument. If not specified,
- then the value of `type` is used. Any string may be specified, but only the
- following values have meaning:
-
- - `none`: Provide no completions.
- - `file`: Bash's default completion (i.e. `complete -o default`), which
- includes filenames.
- - *Any string FOO for which a `function complete_FOO` Bash function is
- defined.* This is for custom completions for a given tool. Typically
- these custom functions are provided in the `specExtra` argument to
- `dashdash.bashCompletionFromOptions()`. See
- ["examples/ddcompletion.js"](examples/ddcompletion.js) for an example.
-
- - `env` (String or Array of String). Optional. An environment variable name
- (or names) that can be used as a fallback for this option. For example,
- given a "foo.js" like this:
-
- var options = [{names: ['dry-run', 'n'], env: 'FOO_DRY_RUN'}];
- var opts = dashdash.parse({options: options});
-
- Both `node foo.js --dry-run` and `FOO_DRY_RUN=1 node foo.js` would result
- in `opts.dry_run = true`.
-
- An environment variable is only used as a fallback, i.e. it is ignored if
- the associated option is given in `argv`.
-
- - `help` (String). Optional. Used for `parser.help()` output.
-
- - `helpArg` (String). Optional. Used in help output as the placeholder for
- the option argument, e.g. the "PATH" in:
-
- ...
- -f PATH, --file=PATH File to process
- ...
-
- - `helpWrap` (Boolean). Optional, default true. Set this to `false` to have
- that option's `help` *not* be text wrapped in `<parser>.help()` output.
-
- - `default`. Optional. A default value used for this option, if the
- option isn't specified in argv.
-
- - `hidden` (Boolean). Optional, default false. If true, help output will not
- include this option. See also the `includeHidden` option to
- `bashCompletionFromOptions()` for [Bash completion](#bash-completion).
-
-
- # Option group headings
-
- You can add headings between option specs in the `options` array. To do so,
- simply add an object with only a `group` property -- the string to print as
- the heading for the subsequent options in the array. For example:
-
- ```javascript
- var options = [
- {
- group: 'Armament Options'
- },
- {
- names: [ 'weapon', 'w' ],
- type: 'string'
- },
- {
- group: 'General Options'
- },
- {
- names: [ 'help', 'h' ],
- type: 'bool'
- }
- ];
- ...
- ```
-
- Note: You can use an empty string, `{group: ''}`, to get a blank line in help
- output between groups of options.
-
-
- # Help config
-
- The `parser.help(...)` function is configurable as follows:
-
- Options:
- Armament Options:
- ^^ -w WEAPON, --weapon=WEAPON Weapon with which to crush. One of: |
- / sword, spear, maul |
- / General Options: |
- / -h, --help Print this help and exit. |
- / ^^^^ ^ |
- \ `-- indent `-- helpCol maxCol ---'
- `-- headingIndent
-
- - `indent` (Number or String). Default 4. Set to a number (for that many
- spaces) or a string for the literal indent.
- - `headingIndent` (Number or String). Default half length of `indent`. Set to
- a number (for that many spaces) or a string for the literal indent. This
- indent applies to group heading lines, between normal option lines.
- - `nameSort` (String). Default is 'length'. By default the names are
- sorted to put the short opts first (i.e. '-h, --help' preferred
- to '--help, -h'). Set to 'none' to not do this sorting.
- - `maxCol` (Number). Default 80. Note that reflow is just done on whitespace
- so a long token in the option help can overflow maxCol.
- - `helpCol` (Number). If not set a reasonable value will be determined
- between `minHelpCol` and `maxHelpCol`.
- - `minHelpCol` (Number). Default 20.
- - `maxHelpCol` (Number). Default 40.
- - `helpWrap` (Boolean). Default true. Set to `false` to have option `help`
- strings *not* be textwrapped to the helpCol..maxCol range.
- - `includeEnv` (Boolean). Default false. If the option has associated
- environment variables (via the `env` option spec attribute), then
- append mentioned of those envvars to the help string.
- - `includeDefault` (Boolean). Default false. If the option has a default value
- (via the `default` option spec attribute, or a default on the option's type),
- then a "Default: VALUE" string will be appended to the help string.
-
-
- # Custom option types
-
- Dashdash includes a good starter set of option types that it will parse for
- you. However, you can add your own via:
-
- var dashdash = require('dashdash');
- dashdash.addOptionType({
- name: '...',
- takesArg: true,
- helpArg: '...',
- parseArg: function (option, optstr, arg) {
- ...
- },
- array: false, // optional
- arrayFlatten: false, // optional
- default: ..., // optional
- completionType: ... // optional
- });
-
- For example, a simple option type that accepts 'yes', 'y', 'no' or 'n' as
- a boolean argument would look like:
-
- var dashdash = require('dashdash');
-
- function parseYesNo(option, optstr, arg) {
- var argLower = arg.toLowerCase()
- if (~['yes', 'y'].indexOf(argLower)) {
- return true;
- } else if (~['no', 'n'].indexOf(argLower)) {
- return false;
- } else {
- throw new Error(format(
- 'arg for "%s" is not "yes" or "no": "%s"',
- optstr, arg));
- }
- }
-
- dashdash.addOptionType({
- name: 'yesno'
- takesArg: true,
- helpArg: '<yes|no>',
- parseArg: parseYesNo
- });
-
- var options = {
- {names: ['answer', 'a'], type: 'yesno'}
- };
- var opts = dashdash.parse({options: options});
-
- See "examples/custom-option-\*.js" for other examples.
- See the `addOptionType` block comment in "lib/dashdash.js" for more details.
- Please let me know [with an
- issue](https://github.com/trentm/node-dashdash/issues/new) if you write a
- generally useful one.
-
-
-
- # Why
-
- Why another node.js option parsing lib?
-
- - `nopt` really is just for "tools like npm". Implicit opts (e.g. '--no-foo'
- works for every '--foo'). Can't disable abbreviated opts. Can't do multiple
- usages of same opt, e.g. '-vvv' (I think). Can't do grouped short opts.
-
- - `optimist` has surprise interpretation of options (at least to me).
- Implicit opts mean ambiguities and poor error handling for fat-fingering.
- `process.exit` calls makes it hard to use as a libary.
-
- - `optparse` Incomplete docs. Is this an attempted clone of Python's `optparse`.
- Not clear. Some divergence. `parser.on("name", ...)` API is weird.
-
- - `argparse` Dep on underscore. No thanks just for option processing.
- `find lib | wc -l` -> `26`. Overkill.
- Argparse is a bit different anyway. Not sure I want that.
-
- - `posix-getopt` No type validation. Though that isn't a killer. AFAIK can't
- have a long opt without a short alias. I.e. no `getopt_long` semantics.
- Also, no whizbang features like generated help output.
-
- - ["commander.js"](https://github.com/visionmedia/commander.js): I wrote
- [a critique](http://trentm.com/2014/01/a-critique-of-commander-for-nodejs.html)
- a while back. It seems fine, but last I checked had
- [an outstanding bug](https://github.com/visionmedia/commander.js/pull/121)
- that would prevent me from using it.
-
-
- # License
-
- MIT. See LICENSE.txt.
|