From b58b5bc2cda7fc15acf559ae4a6a0eda0be06044 Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Wed, 23 Mar 2022 20:33:58 +0100 Subject: [PATCH] fix(completion): don't show positional args choices with option choices (#2148) --- lib/completion.ts | 17 ++++++++++++----- test/completion.cjs | 30 ++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/lib/completion.ts b/lib/completion.ts index 42f4c2d49..c93405bcc 100644 --- a/lib/completion.ts +++ b/lib/completion.ts @@ -147,7 +147,7 @@ export class Completion implements CompletionInstance { if (this.previousArgHasChoices(args)) { const choices = this.getPreviousArgChoices(args); if (choices && choices.length > 0) { - completions.push(...choices); + completions.push(...choices.map(c => c.replace(/:/g, '\\:'))); } } } @@ -158,6 +158,14 @@ export class Completion implements CompletionInstance { argv: Arguments, current: string ) { + if ( + current === '' && + completions.length > 0 && + this.previousArgHasChoices(args) + ) { + return; + } + const positionalKeys = this.yargs.getGroups()[this.usage.getPositionalGroupName()] || []; const offset = Math.max( @@ -165,17 +173,16 @@ export class Completion implements CompletionInstance { this.yargs.getInternalMethods().getContext().commands.length + /* name of the script is first param */ 1 ); - const positionalValues = argv._.slice(offset); - - const positionalKey = positionalKeys[positionalValues.length - 1]; + const positionalKey = positionalKeys[argv._.length - offset - 1]; if (!positionalKey) { return; } + const choices = this.yargs.getOptions().choices[positionalKey] || []; for (const choice of choices) { if (choice.startsWith(current)) { - completions.push(choice); + completions.push(choice.replace(/:/g, '\\:')); } } } diff --git a/test/completion.cjs b/test/completion.cjs index 6dc6868ee..9c5e032a2 100644 --- a/test/completion.cjs +++ b/test/completion.cjs @@ -426,6 +426,36 @@ describe('Completion', () => { r.logs.should.include('--amount'); }); + it('options choices should not be display with positional choices', () => { + process.env.SHELL = '/bin/bash'; + const r = checkUsage( + () => + yargs([ + ...firstArguments, + './completion', + 'cmd', + 'apple', + '--foo', + '', + ]) + .help(false) + .version(false) + .command('cmd [fruit]', 'command', subYargs => { + subYargs + .positional('fruit', {choices: ['apple', 'banana', 'pear']}) + .options('foo', { + choices: ['bar', 'buz'], + }) + .options({amount: {describe: 'amount', type: 'number'}}); + }).argv + ); + + r.logs.should.have.length(2); + r.logs.should.include('bar'); + r.logs.should.include('buz'); + r.logs.should.not.include('apple'); + }); + it('completes choices for positional with prefix', () => { process.env.SHELL = '/bin/bash'; const r = checkUsage(