summaryrefslogtreecommitdiff
path: root/node_modules/dashdash
diff options
context:
space:
mode:
authorLinuxWizard42 <computerwizard@linuxmail.org>2022-10-12 22:54:37 +0300
committerLinuxWizard42 <computerwizard@linuxmail.org>2022-10-12 22:54:37 +0300
commit703e03aba33f234712206769f57717ba7d92d23d (patch)
tree0041f04ccb75bd5379c764e9fe42249fffe75fc3 /node_modules/dashdash
parentab6e257e6e9d9a483d7e86f220d8b209a2cd7753 (diff)
downloadFlashRunner-703e03aba33f234712206769f57717ba7d92d23d.tar.gz
FlashRunner-703e03aba33f234712206769f57717ba7d92d23d.tar.zst
Added export_allowed file to make repository visible in cgit
Diffstat (limited to 'node_modules/dashdash')
-rw-r--r--node_modules/dashdash/CHANGES.md364
-rw-r--r--node_modules/dashdash/LICENSE.txt24
-rw-r--r--node_modules/dashdash/README.md574
-rw-r--r--node_modules/dashdash/etc/dashdash.bash_completion.in389
-rw-r--r--node_modules/dashdash/lib/dashdash.js1055
-rw-r--r--node_modules/dashdash/package.json26
6 files changed, 2432 insertions, 0 deletions
diff --git a/node_modules/dashdash/CHANGES.md b/node_modules/dashdash/CHANGES.md
new file mode 100644
index 0000000..d7c8f4e
--- /dev/null
+++ b/node_modules/dashdash/CHANGES.md
@@ -0,0 +1,364 @@
+# node-dashdash changelog
+
+## not yet released
+
+(nothing yet)
+
+## 1.14.1
+
+- [issue #30] Change the output used by dashdash's Bash completion support to
+ indicate "there are no completions for this argument" to cope with different
+ sorting rules on different Bash/platforms. For example:
+
+ $ triton -v -p test2 package get <TAB> # before
+ ##-no -tritonpackage- completions-##
+
+ $ triton -v -p test2 package get <TAB> # after
+ ##-no-completion- -results-##
+
+## 1.14.0
+
+- New `synopsisFromOpt(<option spec>)` function. This will be used by
+ [node-cmdln](https://github.com/trentm/node-cmdln) to put together a synopsis
+ of options for a command. Some examples:
+
+ > synopsisFromOpt({names: ['help', 'h'], type: 'bool'});
+ '[ --help | -h ]'
+ > synopsisFromOpt({name: 'file', type: 'string', helpArg: 'FILE'});
+ '[ --file=FILE ]'
+
+
+## 1.13.1
+
+- [issue #20] `bashCompletionSpecFromOptions` breaks on an options array with
+ an empty-string group.
+
+
+## 1.13.0
+
+- Update assert-plus dep to 1.x to get recent fixes (particularly for
+ `assert.optional*`).
+
+- Drop testing (and official support in packages.json#engines) for node 0.8.x.
+ Add testing against node 5.x and 4.x with `make testall`.
+
+- [pull #16] Change the `positiveInteger` type to NOT accept zero (0).
+ For those who might need the old behaviour, see
+ "examples/custom-option-intGteZero.js". (By Dave Pacheco.)
+
+
+## 1.12.2
+
+- Bash completion: Add `argtypes` to specify the types of positional args.
+ E.g. this would allow you to have an `ssh` command with `argtypes = ['host',
+ 'cmd']` for bash completion. You then have to provide Bash functions to
+ handle completing those types via the `specExtra` arg. See
+ "[examples/ddcompletion.js](examples/ddcompletion.js)" for an example.
+
+- Bash completion: Tweak so that options or only offered as completions when
+ there is a leading '-'. E.g. `mytool <TAB>` does NOT offer options, `mytool
+ -<TAB>` *does*. Without this, a tool with options would never be able to
+ fallback to Bash's "default" completion. For example `ls <TAB>` wouldn't
+ result in filename completion. Now it will.
+
+- Bash completion: A workaround for not being able to explicitly have *no*
+ completion results. Because dashdash's completion uses `complete -o default`,
+ we fallback to Bash's "default" completion (typically for filename
+ completion). Before this change, an attempt to explicitly say "there are
+ no completions that match" would unintentionally trigger filename completion.
+ Instead as a workaround we return:
+
+ $ ddcompletion --none <TAB> # the 'none' argtype
+ ##-no completions-##
+
+ $ ddcompletion # a custom 'fruit' argtype
+ apple banana orange
+ $ ddcompletion z
+ ##-no -fruit- completions-##
+
+ This is a bit of a hack, but IMO a better experience than the surprise
+ of matching a local filename beginning with 'z', which isn't, in this
+ case, a "fruit".
+
+## 1.12.1
+
+- Bash completion: Document `<option spec>.completionType`. Add `includeHidden`
+ option to `bashCompletionSpecFromOptions()`. Add support for dealing with
+ hidden subcmds.
+
+
+## 1.12.0
+
+- Support for generating Bash completion files. See the "Bash completion"
+ section of the README.md and "examples/ddcompletion.js" for an example.
+
+
+## 1.11.0
+
+- Add the `arrayFlatten` boolean option to `dashdash.addOptionType` used for
+ custom option types. This allows one to create an `arrayOf...` option type
+ where each usage of the option can return multiple results. For example:
+
+ node mytool.js --foo a,b --foo c
+
+ We could define an option type for `--foo` such that
+ `opts.foo = ['a', 'b', 'c']`. See
+ "[examples/custom-option-arrayOfCommaSepString.js](examples/custom-option-arrayOfCommaSepString.js)"
+ for an example.
+
+
+## 1.10.1
+
+- Trim the published package to the minimal bits. Before: 24K tarball, 144K unpacked.
+ After: 12K tarball, 48K unpacked. `npm` won't let me drop the README.md. :)
+
+
+## 1.10.0
+
+- [issue #9] Support `includeDefault` in help config (similar to `includeEnv`) to have a
+ note of an option's default value, if any, in help output.
+- [issue #11] Fix option group breakage introduced in v1.9.0.
+
+
+## 1.9.0
+
+- [issue #10] Custom option types added with `addOptionType` can specify a
+ "default" value. See "examples/custom-option-fruit.js".
+
+
+## 1.8.0
+
+- Support `hidden: true` in an option spec to have help output exclude this
+ option.
+
+
+## 1.7.3
+
+- [issue #8] Fix parsing of a short option group when one of the
+ option takes an argument. For example, consider `tail` with
+ a `-f` boolean option and a `-n` option that takes a number
+ argument. This should parse:
+
+ tail -fn5
+
+ Before this change, that would not parse correctly.
+ It is suspected that this was introduced in version 1.4.0
+ (with commit 656fa8bc71c372ebddad0a7026bd71611e2ec99a).
+
+
+## 1.7.2
+
+- Known issues: #8
+
+- Exclude 'tools/' dir in packages published to npm.
+
+
+## 1.7.1
+
+- Known issues: #8
+
+- Support an option group *empty string* value:
+
+ ...
+ { group: '' },
+ ...
+
+ to render as a blank line in option help. This can help separate loosely
+ related sets of options without resorting to a title for option groups.
+
+
+## 1.7.0
+
+- Known issues: #8
+
+- [pull #7] Support for `<parser>.help({helpWrap: false, ...})` option to be able
+ to fully control the formatting for option help (by Patrick Mooney) `helpWrap:
+ false` can also be set on individual options in the option objects, e.g.:
+
+ var options = [
+ {
+ names: ['foo'],
+ type: 'string',
+ helpWrap: false,
+ help: 'long help with\n newlines' +
+ '\n spaces\n and such\nwill render correctly'
+ },
+ ...
+ ];
+
+
+## 1.6.0
+
+- Known issues: #8
+
+- [pull #6] Support headings between groups of options (by Joshua M. Clulow)
+ so that this code:
+
+ var options = [
+ { group: 'Armament Options' },
+ { names: [ 'weapon', 'w' ], type: 'string' },
+ { group: 'General Options' },
+ { names: [ 'help', 'h' ], type: 'bool' }
+ ];
+ ...
+
+ will give you this help output:
+
+ ...
+ Armament Options:
+ -w, --weapon
+
+ General Options:
+ -h, --help
+ ...
+
+
+## 1.5.0
+
+- Known issues: #8
+
+- Add support for adding custom option types. "examples/custom-option-duration.js"
+ shows an example adding a "duration" option type.
+
+ $ node custom-option-duration.js -t 1h
+ duration: 3600000 ms
+ $ node custom-option-duration.js -t 1s
+ duration: 1000 ms
+ $ node custom-option-duration.js -t 5d
+ duration: 432000000 ms
+ $ node custom-option-duration.js -t bogus
+ custom-option-duration.js: error: arg for "-t" is not a valid duration: "bogus"
+
+ A custom option type is added via:
+
+ var dashdash = require('dashdash');
+ dashdash.addOptionType({
+ name: '...',
+ takesArg: true,
+ helpArg: '...',
+ parseArg: function (option, optstr, arg) {
+ ...
+ }
+ });
+
+- [issue #4] Add `date` and `arrayOfDate` option types. They accept these date
+ formats: epoch second times (e.g. 1396031701) and ISO 8601 format:
+ `YYYY-MM-DD[THH:MM:SS[.sss][Z]]` (e.g. "2014-03-28",
+ "2014-03-28T18:35:01.489Z"). See "examples/date.js" for an example usage.
+
+ $ node examples/date.js -s 2014-01-01 -e $(date +%s)
+ start at 2014-01-01T00:00:00.000Z
+ end at 2014-03-29T04:26:18.000Z
+
+
+## 1.4.0
+
+- Known issues: #8
+
+- [pull #2, pull #3] Add a `allowUnknown: true` option on `createParser` to
+ allow unknown options to be passed through as `opts._args` instead of parsing
+ throwing an exception (by https://github.com/isaacs).
+
+ See 'allowUnknown' in the README for a subtle caveat.
+
+
+## 1.3.2
+
+- Fix a subtlety where a *bool* option using both `env` and `default` didn't
+ work exactly correctly. If `default: false` then all was fine (by luck).
+ However, if you had an option like this:
+
+ options: [ {
+ names: ['verbose', 'v'],
+ env: 'FOO_VERBOSE',
+ 'default': true, // <--- this
+ type: 'bool'
+ } ],
+
+ wanted `FOO_VERBOSE=0` to make the option false, then you need the fix
+ in this version of dashdash.
+
+
+## 1.3.1
+
+- [issue #1] Fix an envvar not winning over an option 'default'. Previously
+ an option with both `default` and `env` would never take a value from the
+ environment variable. E.g. `FOO_FILE` would never work here:
+
+ options: [ {
+ names: ['file', 'f'],
+ env: 'FOO_FILE',
+ 'default': 'default.file',
+ type: 'string'
+ } ],
+
+
+## 1.3.0
+
+- [Backward incompatible change for boolean envvars] Change the
+ interpretation of environment variables for boolean options to consider '0'
+ to be false. Previous to this *any* value to the envvar was considered
+ true -- which was quite misleading. Example:
+
+ $ FOO_VERBOSE=0 node examples/foo.js
+ # opts: { verbose: [ false ],
+ _order: [ { key: 'verbose', value: false, from: 'env' } ],
+ _args: [] }
+ # args: []
+
+
+## 1.2.1
+
+- Fix for `parse.help({includeEnv: true, ...})` handling to ensure that an
+ option with an `env` **but no `help`** still has the "Environment: ..."
+ output. E.g.:
+
+ { names: ['foo'], type: 'string', env: 'FOO' }
+
+ ...
+
+ --foo=ARG Environment: FOO=ARG
+
+
+## 1.2.0
+
+- Transform the option key on the `opts` object returned from
+ `<parser>.parse()` for convenience. Currently this is just
+ `s/-/_/g`, e.g. '--dry-run' -> `opts.dry_run`. This allow one to use hyphen
+ in option names (common) but not have to do silly things like
+ `opt["dry-run"]` to access the parsed results.
+
+
+## 1.1.0
+
+- Environment variable integration. Envvars can be associated with an option,
+ then option processing will fallback to using that envvar if defined and
+ if the option isn't specified in argv. See the "Environment variable
+ integration" section in the README.
+
+- Change the `<parser>.parse()` signature to take a single object with keys
+ for arguments. The old signature is still supported.
+
+- `dashdash.createParser(CONFIG)` alternative to `new dashdash.Parser(CONFIG)`
+ a la many node-land APIs.
+
+
+## 1.0.2
+
+- Add "positiveInteger" and "arrayOfPositiveInteger" option types that only
+ accept positive integers.
+
+- Add "integer" and "arrayOfInteger" option types that accepts only integers.
+ Note that, for better or worse, these do NOT accept: "0x42" (hex), "1e2"
+ (with exponent) or "1.", "3.0" (floats).
+
+
+## 1.0.1
+
+- Fix not modifying the given option spec objects (which breaks creating
+ a Parser with them more than once).
+
+
+## 1.0.0
+
+First release.
diff --git a/node_modules/dashdash/LICENSE.txt b/node_modules/dashdash/LICENSE.txt
new file mode 100644
index 0000000..54706c6
--- /dev/null
+++ b/node_modules/dashdash/LICENSE.txt
@@ -0,0 +1,24 @@
+# This is the MIT license
+
+Copyright (c) 2013 Trent Mick. All rights reserved.
+Copyright (c) 2013 Joyent Inc. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
diff --git a/node_modules/dashdash/README.md b/node_modules/dashdash/README.md
new file mode 100644
index 0000000..e47b106
--- /dev/null
+++ b/node_modules/dashdash/README.md
@@ -0,0 +1,574 @@
+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.
diff --git a/node_modules/dashdash/etc/dashdash.bash_completion.in b/node_modules/dashdash/etc/dashdash.bash_completion.in
new file mode 100644
index 0000000..dc33309
--- /dev/null
+++ b/node_modules/dashdash/etc/dashdash.bash_completion.in
@@ -0,0 +1,389 @@
+#!/bin/bash
+#
+# Bash completion generated for '{{name}}' at {{date}}.
+#
+# The original template lives here:
+# https://github.com/trentm/node-dashdash/blob/master/etc/dashdash.bash_completion.in
+#
+
+#
+# Copyright 2016 Trent Mick
+# Copyright 2016 Joyent, Inc.
+#
+#
+# A generic Bash completion driver script.
+#
+# This is meant to provide a re-usable chunk of Bash to use for
+# "etc/bash_completion.d/" files for individual tools. Only the "Configuration"
+# section with tool-specific info need differ. 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)
+# - does the right thing with "--" to stop options
+# - custom optarg and arg types for custom completions
+# - (TODO) support for shells other than Bash (tcsh, zsh, fish?, etc.)
+#
+#
+# Examples/design:
+#
+# 1. Bash "default" completion. By default Bash's 'complete -o default' is
+# enabled. That means when there are no completions (e.g. if no opts match
+# the current word), then you'll get Bash's default completion. Most notably
+# that means you get filename completion. E.g.:
+# $ tool ./<TAB>
+# $ tool READ<TAB>
+#
+# 2. all opts and subcmds:
+# $ tool <TAB>
+# $ tool -v <TAB> # assuming '-v' doesn't take an arg
+# $ tool -<TAB> # matching opts
+# $ git lo<TAB> # matching subcmds
+#
+# Long opt completions are given *without* the '=', i.e. we prefer space
+# separated because that's easier for good completions.
+#
+# 3. long opt arg with '='
+# $ tool --file=<TAB>
+# $ tool --file=./d<TAB>
+# We maintain the "--file=" prefix. Limitation: With the attached prefix
+# the 'complete -o filenames' doesn't know to do dirname '/' suffixing. Meh.
+#
+# 4. envvars:
+# $ tool $<TAB>
+# $ tool $P<TAB>
+# Limitation: Currently only getting exported vars, so we miss "PS1" and
+# others.
+#
+# 5. Defer to other completion in a subshell:
+# $ tool --file $(cat ./<TAB>
+# We get this from 'complete -o default ...'.
+#
+# 6. Custom completion types from a provided bash function.
+# $ tool --profile <TAB> # complete available "profiles"
+#
+#
+# Dev Notes:
+# - compgen notes, from http://unix.stackexchange.com/questions/151118/understand-compgen-builtin-command
+# - https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion-Builtins.html
+#
+
+
+# Debugging this completion:
+# 1. Uncomment the "_{{name}}_log_file=..." line.
+# 2. 'tail -f /var/tmp/dashdash-completion.log' in one terminal.
+# 3. Re-source this bash completion file.
+#_{{name}}_log=/var/tmp/dashdash-completion.log
+
+function _{{name}}_completer {
+
+ # ---- cmd definition
+
+ {{spec}}
+
+
+ # ---- locals
+
+ declare -a argv
+
+
+ # ---- support functions
+
+ function trace {
+ [[ -n "$_{{name}}_log" ]] && echo "$*" >&2
+ }
+
+ function _dashdash_complete {
+ local idx context
+ idx=$1
+ context=$2
+
+ local shortopts longopts optargs subcmds allsubcmds argtypes
+ shortopts="$(eval "echo \${cmd${context}_shortopts}")"
+ longopts="$(eval "echo \${cmd${context}_longopts}")"
+ optargs="$(eval "echo \${cmd${context}_optargs}")"
+ subcmds="$(eval "echo \${cmd${context}_subcmds}")"
+ allsubcmds="$(eval "echo \${cmd${context}_allsubcmds}")"
+ IFS=', ' read -r -a argtypes <<< "$(eval "echo \${cmd${context}_argtypes}")"
+
+ trace ""
+ trace "_dashdash_complete(idx=$idx, context=$context)"
+ trace " shortopts: $shortopts"
+ trace " longopts: $longopts"
+ trace " optargs: $optargs"
+ trace " subcmds: $subcmds"
+ trace " allsubcmds: $allsubcmds"
+
+ # Get 'state' of option parsing at this COMP_POINT.
+ # Copying "dashdash.js#parse()" behaviour here.
+ local state=
+ local nargs=0
+ local i=$idx
+ local argtype
+ local optname
+ local prefix
+ local word
+ local dashdashseen=
+ while [[ $i -lt $len && $i -le $COMP_CWORD ]]; do
+ argtype=
+ optname=
+ prefix=
+ word=
+
+ arg=${argv[$i]}
+ trace " consider argv[$i]: '$arg'"
+
+ if [[ "$arg" == "--" && $i -lt $COMP_CWORD ]]; then
+ trace " dashdash seen"
+ dashdashseen=yes
+ state=arg
+ word=$arg
+ elif [[ -z "$dashdashseen" && "${arg:0:2}" == "--" ]]; then
+ arg=${arg:2}
+ if [[ "$arg" == *"="* ]]; then
+ optname=${arg%%=*}
+ val=${arg##*=}
+ trace " long opt: optname='$optname' val='$val'"
+ state=arg
+ argtype=$(echo "$optargs" | awk -F "-$optname=" '{print $2}' | cut -d' ' -f1)
+ word=$val
+ prefix="--$optname="
+ else
+ optname=$arg
+ val=
+ trace " long opt: optname='$optname'"
+ state=longopt
+ word=--$optname
+
+ if [[ "$optargs" == *"-$optname="* && $i -lt $COMP_CWORD ]]; then
+ i=$(( $i + 1 ))
+ state=arg
+ argtype=$(echo "$optargs" | awk -F "-$optname=" '{print $2}' | cut -d' ' -f1)
+ word=${argv[$i]}
+ trace " takes arg (consume argv[$i], word='$word')"
+ fi
+ fi
+ elif [[ -z "$dashdashseen" && "${arg:0:1}" == "-" ]]; then
+ trace " short opt group"
+ state=shortopt
+ word=$arg
+
+ local j=1
+ while [[ $j -lt ${#arg} ]]; do
+ optname=${arg:$j:1}
+ trace " consider index $j: optname '$optname'"
+
+ if [[ "$optargs" == *"-$optname="* ]]; then
+ argtype=$(echo "$optargs" | awk -F "-$optname=" '{print $2}' | cut -d' ' -f1)
+ if [[ $(( $j + 1 )) -lt ${#arg} ]]; then
+ state=arg
+ word=${arg:$(( $j + 1 ))}
+ trace " takes arg (rest of this arg, word='$word', argtype='$argtype')"
+ elif [[ $i -lt $COMP_CWORD ]]; then
+ state=arg
+ i=$(( $i + 1 ))
+ word=${argv[$i]}
+ trace " takes arg (word='$word', argtype='$argtype')"
+ fi
+ break
+ fi
+
+ j=$(( $j + 1 ))
+ done
+ elif [[ $i -lt $COMP_CWORD && -n "$arg" ]] && $(echo "$allsubcmds" | grep -w "$arg" >/dev/null); then
+ trace " complete subcmd: recurse _dashdash_complete"
+ _dashdash_complete $(( $i + 1 )) "${context}__${arg/-/_}"
+ return
+ else
+ trace " not an opt or a complete subcmd"
+ state=arg
+ word=$arg
+ nargs=$(( $nargs + 1 ))
+ if [[ ${#argtypes[@]} -gt 0 ]]; then
+ argtype="${argtypes[$(( $nargs - 1 ))]}"
+ if [[ -z "$argtype" ]]; then
+ # If we have more args than argtypes, we use the
+ # last type.
+ argtype="${argtypes[@]: -1:1}"
+ fi
+ fi
+ fi
+
+ trace " state=$state prefix='$prefix' word='$word'"
+ i=$(( $i + 1 ))
+ done
+
+ trace " parsed: state=$state optname='$optname' argtype='$argtype' prefix='$prefix' word='$word' dashdashseen=$dashdashseen"
+ local compgen_opts=
+ if [[ -n "$prefix" ]]; then
+ compgen_opts="$compgen_opts -P $prefix"
+ fi
+
+ case $state in
+ shortopt)
+ compgen $compgen_opts -W "$shortopts $longopts" -- "$word"
+ ;;
+ longopt)
+ compgen $compgen_opts -W "$longopts" -- "$word"
+ ;;
+ arg)
+ # If we don't know what completion to do, then emit nothing. We
+ # expect that we are running with:
+ # complete -o default ...
+ # where "default" means: "Use Readline's default completion if
+ # the compspec generates no matches." This gives us the good filename
+ # completion, completion in subshells/backticks.
+ #
+ # We cannot support an argtype="directory" because
+ # compgen -S '/' -A directory -- "$word"
+ # doesn't give a satisfying result. It doesn't stop at the trailing '/'
+ # so you cannot descend into dirs.
+ if [[ "${word:0:1}" == '$' ]]; then
+ # By default, Bash will complete '$<TAB>' to all envvars. Apparently
+ # 'complete -o default' does *not* give us that. The following
+ # gets *close* to the same completions: '-A export' misses envvars
+ # like "PS1".
+ trace " completing envvars"
+ compgen $compgen_opts -P '$' -A export -- "${word:1}"
+ elif [[ -z "$argtype" ]]; then
+ # Only include opts in completions if $word is not empty.
+ # This is to avoid completing the leading '-', which foils
+ # using 'default' completion.
+ if [[ -n "$dashdashseen" ]]; then
+ trace " completing subcmds, if any (no argtype, dashdash seen)"
+ compgen $compgen_opts -W "$subcmds" -- "$word"
+ elif [[ -z "$word" ]]; then
+ trace " completing subcmds, if any (no argtype, empty word)"
+ compgen $compgen_opts -W "$subcmds" -- "$word"
+ else
+ trace " completing opts & subcmds (no argtype)"
+ compgen $compgen_opts -W "$shortopts $longopts $subcmds" -- "$word"
+ fi
+ elif [[ $argtype == "none" ]]; then
+ # We want *no* completions, i.e. some way to get the active
+ # 'complete -o default' to not do filename completion.
+ trace " completing 'none' (hack to imply no completions)"
+ echo "##-no-completion- -results-##"
+ elif [[ $argtype == "file" ]]; then
+ # 'complete -o default' gives the best filename completion, at least
+ # on Mac.
+ trace " completing 'file' (let 'complete -o default' handle it)"
+ echo ""
+ elif ! type complete_$argtype 2>/dev/null >/dev/null; then
+ trace " completing '$argtype' (fallback to default b/c complete_$argtype is unknown)"
+ echo ""
+ else
+ trace " completing custom '$argtype'"
+ completions=$(complete_$argtype "$word")
+ if [[ -z "$completions" ]]; then
+ trace " no custom '$argtype' completions"
+ # These are in ascii and "dictionary" order so they sort
+ # correctly.
+ echo "##-no-completion- -results-##"
+ else
+ echo $completions
+ fi
+ fi
+ ;;
+ *)
+ trace " unknown state: $state"
+ ;;
+ esac
+ }
+
+
+ trace ""
+ trace "-- $(date)"
+ #trace "\$IFS: '$IFS'"
+ #trace "\$@: '$@'"
+ #trace "COMP_WORDBREAKS: '$COMP_WORDBREAKS'"
+ trace "COMP_CWORD: '$COMP_CWORD'"
+ trace "COMP_LINE: '$COMP_LINE'"
+ trace "COMP_POINT: $COMP_POINT"
+
+ # Guard against negative COMP_CWORD. This is a Bash bug at least on
+ # Mac 10.10.4's bash. See
+ # <https://lists.gnu.org/archive/html/bug-bash/2009-07/msg00125.html>.
+ if [[ $COMP_CWORD -lt 0 ]]; then
+ trace "abort on negative COMP_CWORD"
+ exit 1;
+ fi
+
+ # I don't know how to do array manip on argv vars,
+ # so copy over to argv array to work on them.
+ shift # the leading '--'
+ i=0
+ len=$#
+ while [[ $# -gt 0 ]]; do
+ argv[$i]=$1
+ shift;
+ i=$(( $i + 1 ))
+ done
+ trace "argv: '${argv[@]}'"
+ trace "argv[COMP_CWORD-1]: '${argv[$(( $COMP_CWORD - 1 ))]}'"
+ trace "argv[COMP_CWORD]: '${argv[$COMP_CWORD]}'"
+ trace "argv len: '$len'"
+
+ _dashdash_complete 1 ""
+}
+
+
+# ---- mainline
+
+# Note: This if-block to help work with 'compdef' and 'compctl' is
+# adapted from 'npm completion'.
+if type complete &>/dev/null; then
+ function _{{name}}_completion {
+ local _log_file=/dev/null
+ [[ -z "$_{{name}}_log" ]] || _log_file="$_{{name}}_log"
+ COMPREPLY=($(COMP_CWORD="$COMP_CWORD" \
+ COMP_LINE="$COMP_LINE" \
+ COMP_POINT="$COMP_POINT" \
+ _{{name}}_completer -- "${COMP_WORDS[@]}" \
+ 2>$_log_file)) || return $?
+ }
+ complete -o default -F _{{name}}_completion {{name}}
+elif type compdef &>/dev/null; then
+ function _{{name}}_completion {
+ local _log_file=/dev/null
+ [[ -z "$_{{name}}_log" ]] || _log_file="$_{{name}}_log"
+ compadd -- $(COMP_CWORD=$((CURRENT-1)) \
+ COMP_LINE=$BUFFER \
+ COMP_POINT=0 \
+ _{{name}}_completer -- "${words[@]}" \
+ 2>$_log_file)
+ }
+ compdef _{{name}}_completion {{name}}
+elif type compctl &>/dev/null; then
+ function _{{name}}_completion {
+ local cword line point words si
+ read -Ac words
+ read -cn cword
+ let cword-=1
+ read -l line
+ read -ln point
+ local _log_file=/dev/null
+ [[ -z "$_{{name}}_log" ]] || _log_file="$_{{name}}_log"
+ reply=($(COMP_CWORD="$cword" \
+ COMP_LINE="$line" \
+ COMP_POINT="$point" \
+ _{{name}}_completer -- "${words[@]}" \
+ 2>$_log_file)) || return $?
+ }
+ compctl -K _{{name}}_completion {{name}}
+fi
+
+
+##
+## This is a Bash completion file for the '{{name}}' command. You can install
+## with either:
+##
+## cp FILE /usr/local/etc/bash_completion.d/{{name}} # Mac
+## cp FILE /etc/bash_completion.d/{{name}} # Linux
+##
+## or:
+##
+## cp FILE > ~/.{{name}}.completion
+## echo "source ~/.{{name}}.completion" >> ~/.bashrc
+## \ No newline at end of file
diff --git a/node_modules/dashdash/lib/dashdash.js b/node_modules/dashdash/lib/dashdash.js
new file mode 100644
index 0000000..adb6f13
--- /dev/null
+++ b/node_modules/dashdash/lib/dashdash.js
@@ -0,0 +1,1055 @@
+/**
+ * dashdash - A light, featureful and explicit option parsing library for
+ * node.js.
+ */
+// vim: set ts=4 sts=4 sw=4 et:
+
+var assert = require('assert-plus');
+var format = require('util').format;
+var fs = require('fs');
+var path = require('path');
+
+
+var DEBUG = true;
+if (DEBUG) {
+ var debug = console.warn;
+} else {
+ var debug = function () {};
+}
+
+
+
+// ---- internal support stuff
+
+// Replace {{variable}} in `s` with the template data in `d`.
+function renderTemplate(s, d) {
+ return s.replace(/{{([a-zA-Z]+)}}/g, function (match, key) {
+ return d.hasOwnProperty(key) ? d[key] : match;
+ });
+}
+
+/**
+ * Return a shallow copy of the given object;
+ */
+function shallowCopy(obj) {
+ if (!obj) {
+ return (obj);
+ }
+ var copy = {};
+ Object.keys(obj).forEach(function (k) {
+ copy[k] = obj[k];
+ });
+ return (copy);
+}
+
+
+function space(n) {
+ var s = '';
+ for (var i = 0; i < n; i++) {
+ s += ' ';
+ }
+ return s;
+}
+
+
+function makeIndent(arg, deflen, name) {
+ if (arg === null || arg === undefined)
+ return space(deflen);
+ else if (typeof (arg) === 'number')
+ return space(arg);
+ else if (typeof (arg) === 'string')
+ return arg;
+ else
+ assert.fail('invalid "' + name + '": not a string or number: ' + arg);
+}
+
+
+/**
+ * Return an array of lines wrapping the given text to the given width.
+ * This splits on whitespace. Single tokens longer than `width` are not
+ * broken up.
+ */
+function textwrap(s, width) {
+ var words = s.trim().split(/\s+/);
+ var lines = [];
+ var line = '';
+ words.forEach(function (w) {
+ var newLength = line.length + w.length;
+ if (line.length > 0)
+ newLength += 1;
+ if (newLength > width) {
+ lines.push(line);
+ line = '';
+ }
+ if (line.length > 0)
+ line += ' ';
+ line += w;
+ });
+ lines.push(line);
+ return lines;
+}
+
+
+/**
+ * Transform an option name to a "key" that is used as the field
+ * on the `opts` object returned from `<parser>.parse()`.
+ *
+ * Transformations:
+ * - '-' -> '_': This allow one to use hyphen in option names (common)
+ * but not have to do silly things like `opt["dry-run"]` to access the
+ * parsed results.
+ */
+function optionKeyFromName(name) {
+ return name.replace(/-/g, '_');
+}
+
+
+
+// ---- Option types
+
+function parseBool(option, optstr, arg) {
+ return Boolean(arg);
+}
+
+function parseString(option, optstr, arg) {
+ assert.string(arg, 'arg');
+ return arg;
+}
+
+function parseNumber(option, optstr, arg) {
+ assert.string(arg, 'arg');
+ var num = Number(arg);
+ if (isNaN(num)) {
+ throw new Error(format('arg for "%s" is not a number: "%s"',
+ optstr, arg));
+ }
+ return num;
+}
+
+function parseInteger(option, optstr, arg) {
+ assert.string(arg, 'arg');
+ var num = Number(arg);
+ if (!/^[0-9-]+$/.test(arg) || isNaN(num)) {
+ throw new Error(format('arg for "%s" is not an integer: "%s"',
+ optstr, arg));
+ }
+ return num;
+}
+
+function parsePositiveInteger(option, optstr, arg) {
+ assert.string(arg, 'arg');
+ var num = Number(arg);
+ if (!/^[0-9]+$/.test(arg) || isNaN(num) || num === 0) {
+ throw new Error(format('arg for "%s" is not a positive integer: "%s"',
+ optstr, arg));
+ }
+ return num;
+}
+
+/**
+ * Supported date args:
+ * - epoch second times (e.g. 1396031701)
+ * - ISO 8601 format: YYYY-MM-DD[THH:MM:SS[.sss][Z]]
+ * 2014-03-28T18:35:01.489Z
+ * 2014-03-28T18:35:01.489
+ * 2014-03-28T18:35:01Z
+ * 2014-03-28T18:35:01
+ * 2014-03-28
+ */
+function parseDate(option, optstr, arg) {
+ assert.string(arg, 'arg');
+ var date;
+ if (/^\d+$/.test(arg)) {
+ // epoch seconds
+ date = new Date(Number(arg) * 1000);
+ /* JSSTYLED */
+ } else if (/^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d+)?Z?)?$/i.test(arg)) {
+ // ISO 8601 format
+ date = new Date(arg);
+ } else {
+ throw new Error(format('arg for "%s" is not a valid date format: "%s"',
+ optstr, arg));
+ }
+ if (date.toString() === 'Invalid Date') {
+ throw new Error(format('arg for "%s" is an invalid date: "%s"',
+ optstr, arg));
+ }
+ return date;
+}
+
+var optionTypes = {
+ bool: {
+ takesArg: false,
+ parseArg: parseBool
+ },
+ string: {
+ takesArg: true,
+ helpArg: 'ARG',
+ parseArg: parseString
+ },
+ number: {
+ takesArg: true,
+ helpArg: 'NUM',
+ parseArg: parseNumber
+ },
+ integer: {
+ takesArg: true,
+ helpArg: 'INT',
+ parseArg: parseInteger
+ },
+ positiveInteger: {
+ takesArg: true,
+ helpArg: 'INT',
+ parseArg: parsePositiveInteger
+ },
+ date: {
+ takesArg: true,
+ helpArg: 'DATE',
+ parseArg: parseDate
+ },
+ arrayOfBool: {
+ takesArg: false,
+ array: true,
+ parseArg: parseBool
+ },
+ arrayOfString: {
+ takesArg: true,
+ helpArg: 'ARG',
+ array: true,
+ parseArg: parseString
+ },
+ arrayOfNumber: {
+ takesArg: true,
+ helpArg: 'NUM',
+ array: true,
+ parseArg: parseNumber
+ },
+ arrayOfInteger: {
+ takesArg: true,
+ helpArg: 'INT',
+ array: true,
+ parseArg: parseInteger
+ },
+ arrayOfPositiveInteger: {
+ takesArg: true,
+ helpArg: 'INT',
+ array: true,
+ parseArg: parsePositiveInteger
+ },
+ arrayOfDate: {
+ takesArg: true,
+ helpArg: 'INT',
+ array: true,
+ parseArg: parseDate
+ },
+};
+
+
+
+// ---- Parser
+
+/**
+ * Parser constructor.
+ *
+ * @param config {Object} The parser configuration
+ * - options {Array} Array of option specs. See the README for how to
+ * specify each option spec.
+ * - allowUnknown {Boolean} Default false. Whether to throw on unknown
+ * options. If false, then unknown args are included in the _args array.
+ * - interspersed {Boolean} Default true. Whether to allow interspersed
+ * arguments (non-options) and options. E.g.:
+ * node tool.js arg1 arg2 -v
+ * '-v' is after some args here. If `interspersed: false` then '-v'
+ * would not be parsed out. Note that regardless of `interspersed`
+ * the presence of '--' will stop option parsing, as all good
+ * option parsers should.
+ */
+function Parser(config) {
+ assert.object(config, 'config');
+ assert.arrayOfObject(config.options, 'config.options');
+ assert.optionalBool(config.interspersed, 'config.interspersed');
+ var self = this;
+
+ // Allow interspersed arguments (true by default).
+ this.interspersed = (config.interspersed !== undefined
+ ? config.interspersed : true);
+
+ // Don't allow unknown flags (true by default).
+ this.allowUnknown = (config.allowUnknown !== undefined
+ ? config.allowUnknown : false);
+
+ this.options = config.options.map(function (o) { return shallowCopy(o); });
+ this.optionFromName = {};
+ this.optionFromEnv = {};
+ for (var i = 0; i < this.options.length; i++) {
+ var o = this.options[i];
+ if (o.group !== undefined && o.group !== null) {
+ assert.optionalString(o.group,
+ format('config.options.%d.group', i));
+ continue;
+ }
+ assert.ok(optionTypes[o.type],
+ format('invalid config.options.%d.type: "%s" in %j',
+ i, o.type, o));
+ assert.optionalString(o.name, format('config.options.%d.name', i));
+ assert.optionalArrayOfString(o.names,
+ format('config.options.%d.names', i));
+ assert.ok((o.name || o.names) && !(o.name && o.names),
+ format('exactly one of "name" or "names" required: %j', o));
+ assert.optionalString(o.help, format('config.options.%d.help', i));
+ var env = o.env || [];
+ if (typeof (env) === 'string') {
+ env = [env];
+ }
+ assert.optionalArrayOfString(env, format('config.options.%d.env', i));
+ assert.optionalString(o.helpGroup,
+ format('config.options.%d.helpGroup', i));
+ assert.optionalBool(o.helpWrap,
+ format('config.options.%d.helpWrap', i));
+ assert.optionalBool(o.hidden, format('config.options.%d.hidden', i));
+
+ if (o.name) {
+ o.names = [o.name];
+ } else {
+ assert.string(o.names[0],
+ format('config.options.%d.names is empty', i));
+ }
+ o.key = optionKeyFromName(o.names[0]);
+ o.names.forEach(function (n) {
+ if (self.optionFromName[n]) {
+ throw new Error(format(
+ 'option name collision: "%s" used in %j and %j',
+ n, self.optionFromName[n], o));
+ }
+ self.optionFromName[n] = o;
+ });
+ env.forEach(function (n) {
+ if (self.optionFromEnv[n]) {
+ throw new Error(format(
+ 'option env collision: "%s" used in %j and %j',
+ n, self.optionFromEnv[n], o));
+ }
+ self.optionFromEnv[n] = o;
+ });
+ }
+}
+
+Parser.prototype.optionTakesArg = function optionTakesArg(option) {
+ return optionTypes[option.type].takesArg;
+};
+
+/**
+ * Parse options from the given argv.
+ *
+ * @param inputs {Object} Optional.
+ * - argv {Array} Optional. The argv to parse. Defaults to
+ * `process.argv`.
+ * - slice {Number} The index into argv at which options/args begin.
+ * Default is 2, as appropriate for `process.argv`.
+ * - env {Object} Optional. The env to use for 'env' entries in the
+ * option specs. Defaults to `process.env`.
+ * @returns {Object} Parsed `opts`. It has special keys `_args` (the
+ * remaining args from `argv`) and `_order` (gives the order that
+ * options were specified).
+ */
+Parser.prototype.parse = function parse(inputs) {
+ var self = this;
+
+ // Old API was `parse([argv, [slice]])`
+ if (Array.isArray(arguments[0])) {
+ inputs = {argv: arguments[0], slice: arguments[1]};
+ }
+
+ assert.optionalObject(inputs, 'inputs');
+ if (!inputs) {
+ inputs = {};
+ }
+ assert.optionalArrayOfString(inputs.argv, 'inputs.argv');
+ //assert.optionalNumber(slice, 'slice');
+ var argv = inputs.argv || process.argv;
+ var slice = inputs.slice !== undefined ? inputs.slice : 2;
+ var args = argv.slice(slice);
+ var env = inputs.env || process.env;
+ var opts = {};
+ var _order = [];
+
+ function addOpt(option, optstr, key, val, from) {
+ var type = optionTypes[option.type];
+ var parsedVal = type.parseArg(option, optstr, val);
+ if (type.array) {
+ if (!opts[key]) {
+ opts[key] = [];
+ }
+ if (type.arrayFlatten && Array.isArray(parsedVal)) {
+ for (var i = 0; i < parsedVal.length; i++) {
+ opts[key].push(parsedVal[i]);
+ }
+ } else {
+ opts[key].push(parsedVal);
+ }
+ } else {
+ opts[key] = parsedVal;
+ }
+ var item = { key: key, value: parsedVal, from: from };
+ _order.push(item);
+ }
+
+ // Parse args.
+ var _args = [];
+ var i = 0;
+ outer: while (i < args.length) {
+ var arg = args[i];
+
+ // End of options marker.
+ if (arg === '--') {
+ i++;
+ break;
+
+ // Long option
+ } else if (arg.slice(0, 2) === '--') {
+ var name = arg.slice(2);
+ var val = null;
+ var idx = name.indexOf('=');
+ if (idx !== -1) {
+ val = name.slice(idx + 1);
+ name = name.slice(0, idx);
+ }
+ var option = this.optionFromName[name];
+ if (!option) {
+ if (!this.allowUnknown)
+ throw new Error(format('unknown option: "--%s"', name));
+ else if (this.interspersed)
+ _args.push(arg);
+ else
+ break outer;
+ } else {
+ var takesArg = this.optionTakesArg(option);
+ if (val !== null && !takesArg) {
+ throw new Error(format('argument given to "--%s" option '
+ + 'that does not take one: "%s"', name, arg));
+ }
+ if (!takesArg) {
+ addOpt(option, '--'+name, option.key, true, 'argv');
+ } else if (val !== null) {
+ addOpt(option, '--'+name, option.key, val, 'argv');
+ } else if (i + 1 >= args.length) {
+ throw new Error(format('do not have enough args for "--%s" '
+ + 'option', name));
+ } else {
+ addOpt(option, '--'+name, option.key, args[i + 1], 'argv');
+ i++;
+ }
+ }
+
+ // Short option
+ } else if (arg[0] === '-' && arg.length > 1) {
+ var j = 1;
+ var allFound = true;
+ while (j < arg.length) {
+ var name = arg[j];
+ var option = this.optionFromName[name];
+ if (!option) {
+ allFound = false;
+ if (this.allowUnknown) {
+ if (this.interspersed) {
+ _args.push(arg);
+ break;
+ } else
+ break outer;
+ } else if (arg.length > 2) {
+ throw new Error(format(
+ 'unknown option: "-%s" in "%s" group',
+ name, arg));
+ } else {
+ throw new Error(format('unknown option: "-%s"', name));
+ }
+ } else if (this.optionTakesArg(option)) {
+ break;
+ }
+ j++;
+ }
+
+ j = 1;
+ while (allFound && j < arg.length) {
+ var name = arg[j];
+ var val = arg.slice(j + 1); // option val if it takes an arg
+ var option = this.optionFromName[name];
+ var takesArg = this.optionTakesArg(option);
+ if (!takesArg) {
+ addOpt(option, '-'+name, option.key, true, 'argv');
+ } else if (val) {
+ addOpt(option, '-'+name, option.key, val, 'argv');
+ break;
+ } else {
+ if (i + 1 >= args.length) {
+ throw new Error(format('do not have enough args '
+ + 'for "-%s" option', name));
+ }
+ addOpt(option, '-'+name, option.key, args[i + 1], 'argv');
+ i++;
+ break;
+ }
+ j++;
+ }
+
+ // An interspersed arg
+ } else if (this.interspersed) {
+ _args.push(arg);
+
+ // An arg and interspersed args are not allowed, so done options.
+ } else {
+ break outer;
+ }
+ i++;
+ }
+ _args = _args.concat(args.slice(i));
+
+ // Parse environment.
+ Object.keys(this.optionFromEnv).forEach(function (envname) {
+ var val = env[envname];
+ if (val === undefined)
+ return;
+ var option = self.optionFromEnv[envname];
+ if (opts[option.key] !== undefined)
+ return;
+ var takesArg = self.optionTakesArg(option);
+ if (takesArg) {
+ addOpt(option, envname, option.key, val, 'env');
+ } else if (val !== '') {
+ // Boolean envvar handling:
+ // - VAR=<empty-string> not set (as if the VAR was not set)
+ // - VAR=0 false
+ // - anything else true
+ addOpt(option, envname, option.key, (val !== '0'), 'env');
+ }
+ });
+
+ // Apply default values.
+ this.options.forEach(function (o) {
+ if (opts[o.key] === undefined) {
+ if (o.default !== undefined) {
+ opts[o.key] = o.default;
+ } else if (o.type && optionTypes[o.type].default !== undefined) {
+ opts[o.key] = optionTypes[o.type].default;
+ }
+ }
+ });
+
+ opts._order = _order;
+ opts._args = _args;
+ return opts;
+};
+
+
+/**
+ * Return help output for the current options.
+ *
+ * E.g.: if the current options are:
+ * [{names: ['help', 'h'], type: 'bool', help: 'Show help and exit.'}]
+ * then this would return:
+ * ' -h, --help Show help and exit.\n'
+ *
+ * @param config {Object} Config for controlling the option help output.
+ * - indent {Number|String} Default 4. An indent/prefix to use for
+ * each option line.
+ * - 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 long tokens in a help string
+ * can go past this.
+ * - helpCol {Number} Set to specify a specific column at which
+ * option help will be aligned. By default this is determined
+ * automatically.
+ * - minHelpCol {Number} Default 20.
+ * - maxHelpCol {Number} Default 40.
+ * - includeEnv {Boolean} Default false. If true, a note stating the `env`
+ * envvar (if specified for this option) will be appended to the help
+ * output.
+ * - includeDefault {Boolean} Default false. If true, a note stating
+ * the `default` for this option, if any, will be appended to the help
+ * output.
+ * - helpWrap {Boolean} Default true. Wrap help text in helpCol..maxCol
+ * bounds.
+ * @returns {String}
+ */
+Parser.prototype.help = function help(config) {
+ config = config || {};
+ assert.object(config, 'config');
+
+ var indent = makeIndent(config.indent, 4, 'config.indent');
+ var headingIndent = makeIndent(config.headingIndent,
+ Math.round(indent.length / 2), 'config.headingIndent');
+
+ assert.optionalString(config.nameSort, 'config.nameSort');
+ var nameSort = config.nameSort || 'length';
+ assert.ok(~['length', 'none'].indexOf(nameSort),
+ 'invalid "config.nameSort"');
+ assert.optionalNumber(config.maxCol, 'config.maxCol');
+ assert.optionalNumber(config.maxHelpCol, 'config.maxHelpCol');
+ assert.optionalNumber(config.minHelpCol, 'config.minHelpCol');
+ assert.optionalNumber(config.helpCol, 'config.helpCol');
+ assert.optionalBool(config.includeEnv, 'config.includeEnv');
+ assert.optionalBool(config.includeDefault, 'config.includeDefault');
+ assert.optionalBool(config.helpWrap, 'config.helpWrap');
+ var maxCol = config.maxCol || 80;
+ var minHelpCol = config.minHelpCol || 20;
+ var maxHelpCol = config.maxHelpCol || 40;
+
+ var lines = [];
+ var maxWidth = 0;
+ this.options.forEach(function (o) {
+ if (o.hidden) {
+ return;
+ }
+ if (o.group !== undefined && o.group !== null) {
+ // We deal with groups in the next pass
+ lines.push(null);
+ return;
+ }
+ var type = optionTypes[o.type];
+ var arg = o.helpArg || type.helpArg || 'ARG';
+ var line = '';
+ var names = o.names.slice();
+ if (nameSort === 'length') {
+ names.sort(function (a, b) {
+ if (a.length < b.length)
+ return -1;
+ else if (b.length < a.length)
+ return 1;
+ else
+ return 0;
+ })
+ }
+ names.forEach(function (name, i) {
+ if (i > 0)
+ line += ', ';
+ if (name.length === 1) {
+ line += '-' + name
+ if (type.takesArg)
+ line += ' ' + arg;
+ } else {
+ line += '--' + name
+ if (type.takesArg)
+ line += '=' + arg;
+ }
+ });
+ maxWidth = Math.max(maxWidth, line.length);
+ lines.push(line);
+ });
+
+ // Add help strings.
+ var helpCol = config.helpCol;
+ if (!helpCol) {
+ helpCol = maxWidth + indent.length + 2;
+ helpCol = Math.min(Math.max(helpCol, minHelpCol), maxHelpCol);
+ }
+ var i = -1;
+ this.options.forEach(function (o) {
+ if (o.hidden) {
+ return;
+ }
+ i++;
+
+ if (o.group !== undefined && o.group !== null) {
+ if (o.group === '') {
+ // Support a empty string "group" to have a blank line between
+ // sets of options.
+ lines[i] = '';
+ } else {
+ // Render the group heading with the heading-specific indent.
+ lines[i] = (i === 0 ? '' : '\n') + headingIndent +
+ o.group + ':';
+ }
+ return;
+ }
+
+ var helpDefault;
+ if (config.includeDefault) {
+ if (o.default !== undefined) {
+ helpDefault = format('Default: %j', o.default);
+ } else if (o.type && optionTypes[o.type].default !== undefined) {
+ helpDefault = format('Default: %j',
+ optionTypes[o.type].default);
+ }
+ }
+
+ var line = lines[i] = indent + lines[i];
+ if (!o.help && !(config.includeEnv && o.env) && !helpDefault) {
+ return;
+ }
+ var n = helpCol - line.length;
+ if (n >= 0) {
+ line += space(n);
+ } else {
+ line += '\n' + space(helpCol);
+ }
+
+ var helpEnv = '';
+ if (o.env && o.env.length && config.includeEnv) {
+ helpEnv += 'Environment: ';
+ var type = optionTypes[o.type];
+ var arg = o.helpArg || type.helpArg || 'ARG';
+ var envs = (Array.isArray(o.env) ? o.env : [o.env]).map(
+ function (e) {
+ if (type.takesArg) {
+ return e + '=' + arg;
+ } else {
+ return e + '=1';
+ }
+ }
+ );
+ helpEnv += envs.join(', ');
+ }
+ var help = (o.help || '').trim();
+ if (o.helpWrap !== false && config.helpWrap !== false) {
+ // Wrap help description normally.
+ if (help.length && !~'.!?"\''.indexOf(help.slice(-1))) {
+ help += '.';
+ }
+ if (help.length) {
+ help += ' ';
+ }
+ help += helpEnv;
+ if (helpDefault) {
+ if (helpEnv) {
+ help += '. ';
+ }
+ help += helpDefault;
+ }
+ line += textwrap(help, maxCol - helpCol).join(
+ '\n' + space(helpCol));
+ } else {
+ // Do not wrap help description, but indent newlines appropriately.
+ var helpLines = help.split('\n').filter(
+ function (ln) { return ln.length });
+ if (helpEnv !== '') {
+ helpLines.push(helpEnv);
+ }
+ if (helpDefault) {
+ helpLines.push(helpDefault);
+ }
+ line += helpLines.join('\n' + space(helpCol));
+ }
+
+ lines[i] = line;
+ });
+
+ var rv = '';
+ if (lines.length > 0) {
+ rv = lines.join('\n') + '\n';
+ }
+ return rv;
+};
+
+
+/**
+ * Return a string suitable for a Bash completion file for this tool.
+ *
+ * @param args.name {String} The tool name.
+ * @param args.specExtra {String} Optional. Extra Bash code content to add
+ * to the end of the "spec". Typically this is used to append Bash
+ * "complete_TYPE" functions for custom option types. See
+ * "examples/ddcompletion.js" for an example.
+ * @param args.argtypes {Array} Optional. Array of completion types for
+ * positional args (i.e. non-options). E.g.
+ * argtypes = ['fruit', 'veggie', 'file']
+ * will result in completion of fruits for the first arg, veggies for the
+ * second, and filenames for the third and subsequent positional args.
+ * If not given, positional args will use Bash's 'default' completion.
+ * See `specExtra` for providing Bash `complete_TYPE` functions, e.g.
+ * `complete_fruit` and `complete_veggie` in this example.
+ */
+Parser.prototype.bashCompletion = function bashCompletion(args) {
+ assert.object(args, 'args');
+ assert.string(args.name, 'args.name');
+ assert.optionalString(args.specExtra, 'args.specExtra');
+ assert.optionalArrayOfString(args.argtypes, 'args.argtypes');
+
+ return bashCompletionFromOptions({
+ name: args.name,
+ specExtra: args.specExtra,
+ argtypes: args.argtypes,
+ options: this.options
+ });
+};
+
+
+// ---- Bash completion
+
+const BASH_COMPLETION_TEMPLATE_PATH = path.join(
+ __dirname, '../etc/dashdash.bash_completion.in');
+
+/**
+ * Return the Bash completion "spec" (the string value for the "{{spec}}"
+ * var in the "dashdash.bash_completion.in" template) for this tool.
+ *
+ * The "spec" is Bash code that defines the CLI options and subcmds for
+ * the template's completion code. It looks something like this:
+ *
+ * local cmd_shortopts="-J ..."
+ * local cmd_longopts="--help ..."
+ * local cmd_optargs="-p=tritonprofile ..."
+ *
+ * @param args.options {Array} The array of dashdash option specs.
+ * @param args.context {String} Optional. A context string for the "local cmd*"
+ * vars in the spec. By default it is the empty string. When used to
+ * scope for completion on a *sub-command* (e.g. for "git log" on a "git"
+ * tool), then it would have a value (e.g. "__log"). See
+ * <http://github.com/trentm/node-cmdln> Bash completion for details.
+ * @param opts.includeHidden {Boolean} Optional. Default false. By default
+ * hidden options and subcmds are "excluded". Here excluded means they
+ * won't be offered as a completion, but if used, their argument type
+ * will be completed. "Hidden" options and subcmds are ones with the
+ * `hidden: true` attribute to exclude them from default help output.
+ * @param args.argtypes {Array} Optional. Array of completion types for
+ * positional args (i.e. non-options). E.g.
+ * argtypes = ['fruit', 'veggie', 'file']
+ * will result in completion of fruits for the first arg, veggies for the
+ * second, and filenames for the third and subsequent positional args.
+ * If not given, positional args will use Bash's 'default' completion.
+ * See `specExtra` for providing Bash `complete_TYPE` functions, e.g.
+ * `complete_fruit` and `complete_veggie` in this example.
+ */
+function bashCompletionSpecFromOptions(args) {
+ assert.object(args, 'args');
+ assert.object(args.options, 'args.options');
+ assert.optionalString(args.context, 'args.context');
+ assert.optionalBool(args.includeHidden, 'args.includeHidden');
+ assert.optionalArrayOfString(args.argtypes, 'args.argtypes');
+
+ var context = args.context || '';
+ var includeHidden = (args.includeHidden === undefined
+ ? false : args.includeHidden);
+
+ var spec = [];
+ var shortopts = [];
+ var longopts = [];
+ var optargs = [];
+ (args.options || []).forEach(function (o) {
+ if (o.group !== undefined && o.group !== null) {
+ // Skip group headers.
+ return;
+ }
+
+ var optNames = o.names || [o.name];
+ var optType = getOptionType(o.type);
+ if (optType.takesArg) {
+ var completionType = o.completionType ||
+ optType.completionType || o.type;
+ optNames.forEach(function (optName) {
+ if (optName.length === 1) {
+ if (includeHidden || !o.hidden) {
+ shortopts.push('-' + optName);
+ }
+ // Include even hidden options in `optargs` so that bash
+ // completion of its arg still works.
+ optargs.push('-' + optName + '=' + completionType);
+ } else {
+ if (includeHidden || !o.hidden) {
+ longopts.push('--' + optName);
+ }
+ optargs.push('--' + optName + '=' + completionType);
+ }
+ });
+ } else {
+ optNames.forEach(function (optName) {
+ if (includeHidden || !o.hidden) {
+ if (optName.length === 1) {
+ shortopts.push('-' + optName);
+ } else {
+ longopts.push('--' + optName);
+ }
+ }
+ });
+ }
+ });
+
+ spec.push(format('local cmd%s_shortopts="%s"',
+ context, shortopts.sort().join(' ')));
+ spec.push(format('local cmd%s_longopts="%s"',
+ context, longopts.sort().join(' ')));
+ spec.push(format('local cmd%s_optargs="%s"',
+ context, optargs.sort().join(' ')));
+ if (args.argtypes) {
+ spec.push(format('local cmd%s_argtypes="%s"',
+ context, args.argtypes.join(' ')));
+ }
+ return spec.join('\n');
+}
+
+
+/**
+ * Return a string suitable for a Bash completion file for this tool.
+ *
+ * @param args.name {String} The tool name.
+ * @param args.options {Array} The array of dashdash option specs.
+ * @param args.specExtra {String} Optional. Extra Bash code content to add
+ * to the end of the "spec". Typically this is used to append Bash
+ * "complete_TYPE" functions for custom option types. See
+ * "examples/ddcompletion.js" for an example.
+ * @param args.argtypes {Array} Optional. Array of completion types for
+ * positional args (i.e. non-options). E.g.
+ * argtypes = ['fruit', 'veggie', 'file']
+ * will result in completion of fruits for the first arg, veggies for the
+ * second, and filenames for the third and subsequent positional args.
+ * If not given, positional args will use Bash's 'default' completion.
+ * See `specExtra` for providing Bash `complete_TYPE` functions, e.g.
+ * `complete_fruit` and `complete_veggie` in this example.
+ */
+function bashCompletionFromOptions(args) {
+ assert.object(args, 'args');
+ assert.object(args.options, 'args.options');
+ assert.string(args.name, 'args.name');
+ assert.optionalString(args.specExtra, 'args.specExtra');
+ assert.optionalArrayOfString(args.argtypes, 'args.argtypes');
+
+ // Gather template data.
+ var data = {
+ name: args.name,
+ date: new Date(),
+ spec: bashCompletionSpecFromOptions({
+ options: args.options,
+ argtypes: args.argtypes
+ }),
+ };
+ if (args.specExtra) {
+ data.spec += '\n\n' + args.specExtra;
+ }
+
+ // Render template.
+ var template = fs.readFileSync(BASH_COMPLETION_TEMPLATE_PATH, 'utf8');
+ return renderTemplate(template, data);
+}
+
+
+
+// ---- exports
+
+function createParser(config) {
+ return new Parser(config);
+}
+
+/**
+ * Parse argv with the given options.
+ *
+ * @param config {Object} A merge of all the available fields from
+ * `dashdash.Parser` and `dashdash.Parser.parse`: options, interspersed,
+ * argv, env, slice.
+ */
+function parse(config) {
+ assert.object(config, 'config');
+ assert.optionalArrayOfString(config.argv, 'config.argv');
+ assert.optionalObject(config.env, 'config.env');
+ var config = shallowCopy(config);
+ var argv = config.argv;
+ delete config.argv;
+ var env = config.env;
+ delete config.env;
+
+ var parser = new Parser(config);
+ return parser.parse({argv: argv, env: env});
+}
+
+
+/**
+ * Add a new option type.
+ *
+ * @params optionType {Object}:
+ * - name {String} Required.
+ * - takesArg {Boolean} Required. Whether this type of option takes an
+ * argument on process.argv. Typically this is true for all but the
+ * "bool" type.
+ * - helpArg {String} Required iff `takesArg === true`. The string to
+ * show in generated help for options of this type.
+ * - parseArg {Function} Require. `function (option, optstr, arg)` parser
+ * that takes a string argument and returns an instance of the
+ * appropriate type, or throws an error if the arg is invalid.
+ * - array {Boolean} Optional. Set to true if this is an 'arrayOf' type
+ * that collects multiple usages of the option in process.argv and
+ * puts results in an array.
+ * - arrayFlatten {Boolean} Optional. XXX
+ * - default Optional. Default value for options of this type, if no
+ * default is specified in the option type usage.
+ */
+function addOptionType(optionType) {
+ assert.object(optionType, 'optionType');
+ assert.string(optionType.name, 'optionType.name');
+ assert.bool(optionType.takesArg, 'optionType.takesArg');
+ if (optionType.takesArg) {
+ assert.string(optionType.helpArg, 'optionType.helpArg');
+ }
+ assert.func(optionType.parseArg, 'optionType.parseArg');
+ assert.optionalBool(optionType.array, 'optionType.array');
+ assert.optionalBool(optionType.arrayFlatten, 'optionType.arrayFlatten');
+
+ optionTypes[optionType.name] = {
+ takesArg: optionType.takesArg,
+ helpArg: optionType.helpArg,
+ parseArg: optionType.parseArg,
+ array: optionType.array,
+ arrayFlatten: optionType.arrayFlatten,
+ default: optionType.default
+ }
+}
+
+
+function getOptionType(name) {
+ assert.string(name, 'name');
+ return optionTypes[name];
+}
+
+
+/**
+ * Return a synopsis string for the given option spec.
+ *
+ * Examples:
+ * > synopsisFromOpt({names: ['help', 'h'], type: 'bool'});
+ * '[ --help | -h ]'
+ * > synopsisFromOpt({name: 'file', type: 'string', helpArg: 'FILE'});
+ * '[ --file=FILE ]'
+ */
+function synopsisFromOpt(o) {
+ assert.object(o, 'o');
+
+ if (o.hasOwnProperty('group')) {
+ return null;
+ }
+ var names = o.names || [o.name];
+ // `type` here could be undefined if, for example, the command has a
+ // dashdash option spec with a bogus 'type'.
+ var type = getOptionType(o.type);
+ var helpArg = o.helpArg || (type && type.helpArg) || 'ARG';
+ var parts = [];
+ names.forEach(function (name) {
+ var part = (name.length === 1 ? '-' : '--') + name;
+ if (type && type.takesArg) {
+ part += (name.length === 1 ? ' ' + helpArg : '=' + helpArg);
+ }
+ parts.push(part);
+ });
+ return ('[ ' + parts.join(' | ') + ' ]');
+};
+
+
+module.exports = {
+ createParser: createParser,
+ Parser: Parser,
+ parse: parse,
+ addOptionType: addOptionType,
+ getOptionType: getOptionType,
+ synopsisFromOpt: synopsisFromOpt,
+
+ // Bash completion-related exports
+ BASH_COMPLETION_TEMPLATE_PATH: BASH_COMPLETION_TEMPLATE_PATH,
+ bashCompletionFromOptions: bashCompletionFromOptions,
+ bashCompletionSpecFromOptions: bashCompletionSpecFromOptions,
+
+ // Export the parseFoo parsers because they might be useful as primitives
+ // for custom option types.
+ parseBool: parseBool,
+ parseString: parseString,
+ parseNumber: parseNumber,
+ parseInteger: parseInteger,
+ parsePositiveInteger: parsePositiveInteger,
+ parseDate: parseDate
+};
diff --git a/node_modules/dashdash/package.json b/node_modules/dashdash/package.json
new file mode 100644
index 0000000..a11e1f5
--- /dev/null
+++ b/node_modules/dashdash/package.json
@@ -0,0 +1,26 @@
+{
+ "name": "dashdash",
+ "description": "A light, featureful and explicit option parsing library.",
+ "version": "1.14.1",
+ "author": "Trent Mick <trentm@gmail.com> (http://trentm.com)",
+ "keywords": ["option", "parser", "parsing", "cli", "command", "args",
+ "bash", "completion"],
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/trentm/node-dashdash.git"
+ },
+ "main": "./lib/dashdash.js",
+ "dependencies": {
+ "assert-plus": "^1.0.0"
+ },
+ "devDependencies": {
+ "nodeunit": "0.9.x"
+ },
+ "engines": {
+ "node": ">=0.10"
+ },
+ "scripts": {
+ "test": "nodeunit test/*.test.js"
+ },
+ "license": "MIT"
+}