diff --git a/index.js b/index.js index 190429e..df6d531 100644 --- a/index.js +++ b/index.js @@ -1,7 +1,7 @@ 'use strict'; const path = require('path'); const buildMinimistOptions = require('minimist-options'); -const minimist = require('minimist'); +const yargs = require('yargs-parser'); const camelcaseKeys = require('camelcase-keys'); const decamelizeKeys = require('decamelize-keys'); const trimNewlines = require('trim-newlines'); @@ -32,12 +32,24 @@ module.exports = (helpMessage, opts) => { input: 'string', help: helpMessage, autoHelp: true, - autoVersion: true + autoVersion: true, + booleanDefault: false }, opts); + const minimistFlags = opts.flags && typeof opts.booleanDefault !== 'undefined' ? Object.keys(opts.flags).reduce( + (flags, flag) => { + if (flags[flag].type === 'boolean' && !Object.prototype.hasOwnProperty.call(flags[flag], 'default')) { + flags[flag].default = opts.booleanDefault; + } + + return flags; + }, + opts.flags + ) : opts.flags; + let minimistOpts = Object.assign({ arguments: opts.input - }, opts.flags); + }, minimistFlags); minimistOpts = decamelizeKeys(minimistOpts, '-', {exclude: ['stopEarly', '--']}); @@ -47,8 +59,12 @@ module.exports = (helpMessage, opts) => { minimistOpts = buildMinimistOptions(minimistOpts); + if (minimistOpts['--']) { + minimistOpts.configuration = Object.assign({}, minimistOpts.configuration, {'populate--': true}); + } + const pkg = opts.pkg; - const argv = minimist(opts.argv, minimistOpts); + const argv = yargs(opts.argv, minimistOpts); let help = redent(trimNewlines((opts.help || '').replace(/\t+\n*$/, '')), 2); normalizePackageData(pkg); diff --git a/package.json b/package.json index fc30352..0c28c77 100644 --- a/package.json +++ b/package.json @@ -41,12 +41,12 @@ "camelcase-keys": "^4.0.0", "decamelize-keys": "^1.0.0", "loud-rejection": "^1.0.0", - "minimist": "^1.1.3", "minimist-options": "^3.0.1", "normalize-package-data": "^2.3.4", "read-pkg-up": "^3.0.0", "redent": "^2.0.0", - "trim-newlines": "^2.0.0" + "trim-newlines": "^2.0.0", + "yargs-parser": "^10.0.0" }, "devDependencies": { "ava": "*", diff --git a/readme.md b/readme.md index 78f5a13..43970f7 100644 --- a/readme.md +++ b/readme.md @@ -173,6 +173,55 @@ Infer the argument type. By default, the argument `5` in `$ foo 5` becomes a string. Enabling this would infer it as a number. +##### booleanDefault + +Type: `boolean` `null` `undefined`
+Default: `false` + +Value of `boolean` flags not defined in `argv`. +If set to `undefined` the flags not defined in `argv` will be excluded from the result. +The `default` value set in `boolean` flags take precedence over `booleanDefault`. + +Example: + +```js +const cli = meow(` + Usage + $ foo + + Options + --rainbow, -r Include a rainbow + --unicorn, -r Include a unicorn + + Examples + $ foo + 🌈 unicorns 🌈 +`, { + booleanDefault: undefined, + flags: { + rainbow: { + type: 'boolean', + default: true + alias: 'r' + }, + unicorn: { + type: 'boolean', + default: false + alias: 'u' + }, + cake: { + type: 'boolean', + alias: 'c' + } + } +}); +/* +{ + flags: {rainbow: true, unicorn: false}, + … +} +*/ +``` ## Promises diff --git a/test.js b/test.js index 7d1e70a..161132f 100644 --- a/test.js +++ b/test.js @@ -106,8 +106,52 @@ test('type inference', t => { }).input[0], 5); }); +test('booleanDefault: undefined, filter out unset boolean args', t => { + t.deepEqual(m('help', { + argv: ['--foo'], + booleanDefault: undefined, + flags: { + foo: { + type: 'boolean' + }, + bar: { + type: 'boolean' + }, + baz: { + type: 'boolean', + default: false + } + } + }).flags, { + foo: true, + baz: false + }); +}); + +test('boolean args are false by default', t => { + t.deepEqual(m('help', { + argv: ['--foo'], + flags: { + foo: { + type: 'boolean' + }, + bar: { + type: 'boolean', + default: true + }, + baz: { + type: 'boolean' + } + } + }).flags, { + foo: true, + bar: true, + baz: false + }); +}); + test('enforces boolean flag type', t => { - const cli = m(``, { + const cli = m('', { argv: ['--cursor=false'], flags: { cursor: {type: 'boolean'}