Skip to content

Commit

Permalink
fix sindresorhus#80: add autoHelpFlags
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewadams committed Mar 16, 2018
1 parent 8c82a18 commit d55dfb4
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 2 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -1,2 +1,3 @@
node_modules
yarn.lock
.idea/
59 changes: 59 additions & 0 deletions index.js
Expand Up @@ -32,6 +32,7 @@ module.exports = (helpMessage, opts) => {
input: 'string',
help: helpMessage,
autoHelp: true,
autoHelpFlags: true,
autoVersion: true
}, opts);

Expand Down Expand Up @@ -62,6 +63,64 @@ module.exports = (helpMessage, opts) => {

help = (description ? `\n ${description}\n` : '') + (help ? `\n${help}\n` : '\n');

if (opts.autoHelpFlags && opts.flags) {
const options = Object.keys(opts.flags).reduce((accum, flag) => {
const o = opts.flags[flag];
if (Object.prototype.hasOwnProperty.call(o, 'default')) {
o.default = o.default.toString();
}

const option = {
flag: '',
value: '',
desc: ''
};

if (flag.length === 1) {
o.alias = o.alias || flag;
}

option.flag += o.alias ? `-${o.alias}, ` : ' '.repeat(4);
option.flag += `--${flag === '--' ? '' : flag}`;
accum.flagMaxLen = Math.max(accum.flagMaxLen, option.flag.length);

if (flag === '--') {
option.value = 'arg(s)';
} else if (o.type === 'boolean') {
option.value = '[true|false]';
} else {
option.value = `${o.default ? '[' : ''}<value>${o.default ? ']' : ''}`;
}
accum.valMaxLen = Math.max(accum.valMaxLen, option.value.length);

if (flag === '--') {
option.desc = 'option/arg separator';
} else {
if (o.description) {
option.desc += o.description;
}
if (o.default) {
option.desc += `${o.description ? '; ' : ''}default ${o.default}`;
}
}

accum.entries.push(option);
return accum;
}, {
flagMaxLen: 0,
valMaxLen: 0,
entries: []
});

if (options.entries.length > 0) {
help += redent(options.entries.map(it =>
`${it.flag}${' '.repeat(options.flagMaxLen - it.flag.length + 2)}` +
`${it.value}${' '.repeat(options.valMaxLen - it.value.length + 2)}` +
it.desc
).join('\n'), 2);
}
}

const showHelp = code => {
console.log(help);
process.exit(typeof code === 'number' ? code : 2);
Expand Down
11 changes: 10 additions & 1 deletion readme.md
Expand Up @@ -94,6 +94,7 @@ The key is the flag name and the value is an object with any of:
- `type`: Type of value. (Possible values: `string` `boolean`)
- `alias`: Usually used to define a short flag alias.
- `default`: Default value when the flag is not specified.
- `description`: Description to render when autogenerating flag help.

Example:

Expand All @@ -102,7 +103,8 @@ flags: {
unicorn: {
type: 'string',
alias: 'u',
default: 'rainbow'
default: 'rainbow',
description: 'Unicorn name'
}
}
```
Expand Down Expand Up @@ -148,6 +150,13 @@ Default: `true`

Automatically show the version text when the `--version` flag is present. Useful to set this value to `false` when a CLI manages child CLIs with their own version text.

##### autoHelpFlags

Type: `boolean`<br>
Default: `true`

Automatically show help on flags/switches.

##### pkg

Type: `Object`<br>
Expand Down
22 changes: 21 additions & 1 deletion test.js
Expand Up @@ -11,6 +11,7 @@ test('return object', t => {
Usage
foo <input>
`,
autoHelpFlags: false,
flags: {
unicorn: {alias: 'u'},
meow: {default: 'dog'},
Expand All @@ -27,6 +28,25 @@ test('return object', t => {
t.is(cli.help, indentString('\nCLI app helper\n\nUsage\n foo <input>\n', 2));
});

test('return object with arg help', t => {
const cli = m({
argv: ['foo', '--foo-bar', '-u', 'cat', '--', 'unicorn', 'cake'],
flags: {
unicorn: {alias: 'u', description: 'Unicorn name'},
meow: {default: 'dog', description: 'What to meow'},
'--': true
}
});

t.is(cli.input[0], 'foo');
t.true(cli.flags.fooBar);
t.is(cli.flags.meow, 'dog');
t.is(cli.flags.unicorn, 'cat');
t.deepEqual(cli.flags['--'], ['unicorn', 'cake']);
t.is(cli.pkg.name, 'meow');
t.is(cli.help, indentString('\nCLI app helper\n\n-u, --unicorn <value> Unicorn name\n --meow [<value>] What to meow; default dog\n -- arg(s) option/arg separator', 2));
});

test('support help shortcut', t => {
const cli = m(`
unicorn
Expand All @@ -47,7 +67,7 @@ test('spawn cli and not show version', async t => {

test('spawn cli and show help screen', async t => {
const {stdout} = await execa('./fixture.js', ['--help']);
t.is(stdout, indentString('\nCustom description\n\nUsage\n foo <input>\n\n', 2));
t.is(stdout, indentString('\nCustom description\n\nUsage\n foo <input>\n\n-u, --unicorn <value> \n --meow [<value>] default dog\n --camelCaseOption [<value>] default foo', 2));
});

test('spawn cli and not show help screen', async t => {
Expand Down

0 comments on commit d55dfb4

Please sign in to comment.