Skip to content

Commit

Permalink
feat: add command config to ignore option default value
Browse files Browse the repository at this point in the history
  • Loading branch information
egoist committed Nov 26, 2018
1 parent 13dab8e commit 09bbb54
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 29 deletions.
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
- [Projects Using CAC](#projects-using-cac)
- [References](#references)
- [CLI Instance](#cli-instance)
- [cli.command(name, description)](#clicommandname-description)
- [cli.command(name, description, config?)](#clicommandname-description-config)
- [cli.option(name, description, config?)](#clioptionname-description-config)
- [cli.parse(argv?)](#cliparseargv)
- [cli.version(version, customFlags?)](#cliversionversion-customflags)
Expand Down Expand Up @@ -236,19 +236,24 @@ const cac = require('cac')
const cli = cac()
```

#### cli.command(name, description)
#### cli.command(name, description, config?)

- Type: `(name: string, description: string) => Command`

Create a command instance.

The option also accepts a third argument `config` for addtional command config:

- `config.allowUnknownOptions`: `boolean` Allow unknown options in this command.
- `config.ignoreOptionDefaultValue`: `boolean` Don't use the options's default value in parsed options, only display them in help message.

#### cli.option(name, description, config?)

- Type: `(name: string, description: string, config?: OptionConfig) => CLI`

Add a global option.

The option also accepts a third argument `config` for addtional config:
The option also accepts a third argument `config` for addtional option config:

- `config.default`: Default value for the option.
- `config.coerce`: `(value: any) => newValue` A function to process the option value.
Expand Down
14 changes: 14 additions & 0 deletions examples/ignore-default-value.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
require('ts-node/register')
const cli = require('../src/index')()

cli
.command('build', 'Build project', {
ignoreOptionDefaultValue: true
})
.option('--type [type]', 'Choose a project type', {
default: 'node'
})

const parsed = cli.parse()

console.log(JSON.stringify(parsed, null, 2))
16 changes: 12 additions & 4 deletions src/Command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ interface HelpSection {

interface CommandConfig {
allowUnknownOptions?: boolean
ignoreOptionDefaultValue?: boolean
}

type HelpCallback = (sections: HelpSection[]) => void
Expand All @@ -37,16 +38,18 @@ export default class Command {
usageText?: string
versionNumber?: string
examples: CommandExample[]
config: CommandConfig
helpCallback?: HelpCallback

constructor(public rawName: string, public description: string) {
constructor(
public rawName: string,
public description: string,
public config: CommandConfig = {}
) {
this.options = []
this.aliasNames = []
this.name = removeBrackets(rawName)
this.args = findAllBrackets(rawName)
this.examples = []
this.config = {}
}

usage(text: string) {
Expand All @@ -59,6 +62,11 @@ export default class Command {
return this
}

ignoreOptionDefaultValue() {
this.config.ignoreOptionDefaultValue = true
return this
}

version(version: string, customFlags = '-v, --version') {
this.versionNumber = version
this.option(customFlags, 'Display version number')
Expand Down Expand Up @@ -240,4 +248,4 @@ export default class Command {
}
}

export { HelpCallback, CommandExample }
export { HelpCallback, CommandExample, CommandConfig }
9 changes: 9 additions & 0 deletions src/__test__/__snapshots__/index.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ Options:
-v, --version Display version number "
`;
exports[`ignore-default-value: ignore-default-value 1`] = `
"{
\\"args\\": [],
\\"options\\": {
\\"--\\": []
}
}"
`;
exports[`variadic-arguments: variadic-arguments 1`] = `
"a
[ 'b', 'c', 'd' ]
Expand Down
6 changes: 6 additions & 0 deletions src/__test__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,9 @@ snapshotOutput({
file: 'variadic-arguments.js',
args: ['--foo', 'build', 'a', 'b', 'c', 'd']
})

snapshotOutput({
title: 'ignore-default-value',
file: 'ignore-default-value.js',
args: ['build']
})
18 changes: 6 additions & 12 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { EventEmitter } from 'events'
import path from 'path'
import minimist, { Opts as MinimistOpts } from 'minimist'
import Command, { HelpCallback, CommandExample } from './Command'
import Command, { CommandConfig, HelpCallback, CommandExample } from './Command'
import { OptionConfig } from './Option'
import { getMinimistOptions, camelcase } from './utils'

Expand Down Expand Up @@ -57,8 +57,8 @@ class CAC extends EventEmitter {
return this
}

command(rawName: string, description: string) {
const command = new Command(rawName, description)
command(rawName: string, description: string, config?: CommandConfig) {
const command = new Command(rawName, description, config)
this.commands.push(command)
return command
}
Expand Down Expand Up @@ -117,10 +117,7 @@ class CAC extends EventEmitter {

// Search sub-commands
for (const command of this.commands) {
const minimistOptions = getMinimistOptions([
...this.globalCommand.options,
...command.options
])
const minimistOptions = getMinimistOptions(this.globalCommand, command)
const { args, options, originalOptions } = this.minimist(
argv.slice(2),
minimistOptions
Expand All @@ -143,10 +140,7 @@ class CAC extends EventEmitter {
// Search the default command
for (const command of this.commands) {
if (command.name === '') {
const minimistOptions = getMinimistOptions([
...this.globalCommand.options,
...command.options
])
const minimistOptions = getMinimistOptions(this.globalCommand, command)
const { args, options, originalOptions } = this.minimist(
argv.slice(2),
minimistOptions
Expand All @@ -164,7 +158,7 @@ class CAC extends EventEmitter {
}
}

const globalMinimistOptions = getMinimistOptions(this.globalCommand.options)
const globalMinimistOptions = getMinimistOptions(this.globalCommand)
const { args, options } = this.minimist(
argv.slice(2),
globalMinimistOptions
Expand Down
33 changes: 23 additions & 10 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Option from './Option'
import Command from './Command'

export const removeBrackets = (v: string) => v.replace(/[<[].+/, '').trim()

Expand Down Expand Up @@ -35,16 +35,29 @@ export const findAllBrackets = (v: string) => {
return res
}

export const getMinimistOptions = (options: Option[]) => {
export const getMinimistOptions = (
globalCommand: Command,
subCommand?: Command
) => {
const options = [
...globalCommand.options,
...(subCommand ? subCommand.options : [])
]
const ignoreDefault =
subCommand && subCommand.config.ignoreOptionDefaultValue
? subCommand.config.ignoreOptionDefaultValue
: globalCommand.config.ignoreOptionDefaultValue
return {
default: options.reduce((res: { [k: string]: any }, option) => {
if (option.config.default !== undefined) {
// Only need to set the default value of the first name
// Since minimist will automatically do the rest for alias names
res[option.names[0]] = option.config.default
}
return res
}, {}),
default: ignoreDefault
? {}
: options.reduce((res: { [k: string]: any }, option) => {
if (option.config.default !== undefined) {
// Only need to set the default value of the first name
// Since minimist will automatically do the rest for alias names
res[option.names[0]] = option.config.default
}
return res
}, {}),
boolean: options
.filter(option => option.isBoolean)
.reduce((res: string[], option) => {
Expand Down

0 comments on commit 09bbb54

Please sign in to comment.