Skip to content

Commit

Permalink
feature(completion): takes negated flags into account when boolean-ne…
Browse files Browse the repository at this point in the history
…gation is set
  • Loading branch information
Mael LE GUEN committed Dec 18, 2019
1 parent 222c8fe commit 822a200
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 9 deletions.
27 changes: 18 additions & 9 deletions lib/completion.js
Expand Up @@ -76,18 +76,27 @@ module.exports = function completion (yargs, usage, command) {

if (current.match(/^-/) || (current === '' && completions.length === 0)) {
const descs = usage.getDescriptions()
Object.keys(yargs.getOptions().key).forEach((key) => {
const options = yargs.getOptions()
Object.keys(options.key).forEach((key) => {
const negable = !!options.configuration['boolean-negation'] && options.boolean.includes(key)
// If the key and its aliases aren't in 'args', add the key to 'completions'
const keyAndAliases = [key].concat(aliases[key] || [])
const notInArgs = keyAndAliases.every(val => args.indexOf(`--${val}`) === -1)
if (notInArgs) {
if (!zshShell) {
completions.push(`--${key}`)
} else {
const desc = descs[key] || ''
completions.push(`--${key.replace(/:/g, '\\:')}:${desc.replace('__yargsString__:', '')}`)
let keyAndAliases = [key].concat(aliases[key] || [])
if (negable) keyAndAliases = keyAndAliases.concat(keyAndAliases.map(key => `no-${key}`))

function completeOptionKey (key) {
const notInArgs = keyAndAliases.every(val => args.indexOf(`--${val}`) === -1)
if (notInArgs) {
if (!zshShell) {
completions.push(`--${key}`)
} else {
const desc = descs[key] || ''
completions.push(`--${key.replace(/:/g, '\\:')}:${desc.replace('__yargsString__:', '')}`)
}
}
}

completeOptionKey(key)
if (negable && !!options.default[key]) completeOptionKey(`no-${key}`)
})
}

Expand Down
49 changes: 49 additions & 0 deletions test/completion.js
Expand Up @@ -58,6 +58,55 @@ describe('Completion', () => {
r.logs.should.not.include('--foo')
})

it('completes with no- prefix flags defaulting to true when boolean-negation is set', () => {
const r = checkUsage(() => yargs(['./completion', '--get-yargs-completions', './completion', ''])
.options({
foo: { describe: 'foo flag', type: 'boolean', default: true },
bar: { describe: 'bar flag', type: 'boolean' }
})
.parserConfiguration({ 'boolean-negation': true })
.argv
)

r.logs.should.include('--no-foo')
r.logs.should.include('--foo')
r.logs.should.not.include('--no-bar')
r.logs.should.include('--bar')
})

it('avoids repeating flags whose negated counterparts are already included', () => {
const r = checkUsage(() => yargs(['./completion', '--get-yargs-completions', './completion', '--no-foo', '--no-bar', ''])
.options({
foo: { describe: 'foo flag', type: 'boolean', default: true },
bar: { describe: 'bar flag', type: 'boolean' },
baz: { describe: 'bar flag', type: 'boolean' }
})
.parserConfiguration({ 'boolean-negation': true })
.argv
)

r.logs.should.not.include('--no-foo')
r.logs.should.not.include('--foo')
r.logs.should.not.include('--no-bar')
r.logs.should.not.include('--bar')
r.logs.should.include('--baz')
})

it('ignores no- prefix flags when boolean-negation is not set', () => {
const r = checkUsage(() => yargs(['./completion', '--get-yargs-completions', './completion', '--no-bar', ''])
.options({
foo: { describe: 'foo flag', type: 'boolean', default: true },
bar: { describe: 'bar flag', type: 'boolean' }
})
.argv
)

r.logs.should.not.include('--no-foo')
r.logs.should.include('--foo')
r.logs.should.not.include('--no-bar')
r.logs.should.include('--bar')
})

it('completes options for the correct command', () => {
process.env.SHELL = '/bin/bash'
const r = checkUsage(() => yargs(['./completion', '--get-yargs-completions', 'cmd2', '--o'])
Expand Down

0 comments on commit 822a200

Please sign in to comment.