From bb7fa0314a79114493b6c2dfa4055228801c91a0 Mon Sep 17 00:00:00 2001 From: Mike Donnalley Date: Wed, 18 Aug 2021 08:53:49 -0600 Subject: [PATCH 1/2] fix: command name parsing when flag=value present --- src/help/util.ts | 2 +- test/help/util.test.ts | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/help/util.ts b/src/help/util.ts index 0c7c2fce1..1d9473743 100644 --- a/src/help/util.ts +++ b/src/help/util.ts @@ -43,7 +43,7 @@ function collateSpacedCmdIDFromArgs(argv: string[], config: IConfig): string[] { const findId = (argv: string[]): string | undefined => { const final: string[] = [] const idPresent = (id: string) => ids.includes(id) - const isFlag = (s: string) => s.startsWith('-') + const isFlag = (s: string) => s.startsWith('-') || s.includes('=') const finalizeId = (s?: string) => s ? [...final, s].join(':') : final.join(':') const hasSubCommandsWithArgs = () => { diff --git a/test/help/util.test.ts b/test/help/util.test.ts index 7c1e7914a..e52265eb4 100644 --- a/test/help/util.test.ts +++ b/test/help/util.test.ts @@ -102,5 +102,23 @@ describe('util', () => { const actual = standardizeIDFromArgv(['foo', 'bar', 'baz'], config) expect(actual).to.deep.equal(['foo:bar:baz']) }) + + test + .stub(Config.prototype, 'commandIDs', () => ['foo', 'foo:bar']) + .it('should return standardized id when topic separator is a space and has flags', () => { + config.topicSeparator = ' ' + config.commands.push({id: 'foo:bar'} as any) + const actual = standardizeIDFromArgv(['foo', 'bar', '--baz'], config) + expect(actual).to.deep.equal(['foo:bar', '--baz']) + }) + + test + .stub(Config.prototype, 'commandIDs', () => ['foo', 'foo:bar']) + .it('should return standardized id when topic separator is a space and has flags with =', () => { + config.topicSeparator = ' ' + config.commands.push({id: 'foo:bar'} as any) + const actual = standardizeIDFromArgv(['foo', 'bar', '--hello=world'], config) + expect(actual).to.deep.equal(['foo:bar', '--hello=world']) + }) }) }) From ca50b543c87f12604fb5638e4d4254c8626ee534 Mon Sep 17 00:00:00 2001 From: Mike Donnalley Date: Wed, 18 Aug 2021 09:19:28 -0600 Subject: [PATCH 2/2] fix: improve solution and add tests --- src/help/util.ts | 7 ++++--- test/help/util.test.ts | 42 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/src/help/util.ts b/src/help/util.ts index 1d9473743..be04d0f58 100644 --- a/src/help/util.ts +++ b/src/help/util.ts @@ -43,19 +43,20 @@ function collateSpacedCmdIDFromArgs(argv: string[], config: IConfig): string[] { const findId = (argv: string[]): string | undefined => { const final: string[] = [] const idPresent = (id: string) => ids.includes(id) - const isFlag = (s: string) => s.startsWith('-') || s.includes('=') + const isFlag = (s: string) => s.startsWith('-') + const isArgWithValue = (s: string) => s.includes('=') const finalizeId = (s?: string) => s ? [...final, s].join(':') : final.join(':') const hasSubCommandsWithArgs = () => { const subCommands = config.commands.filter(c => (c.id).startsWith(finalizeId())) - return Boolean(subCommands.find(cmd => cmd.strict === false || cmd.args.length > 0)) + return Boolean(subCommands.find(cmd => cmd.strict === false || cmd.args?.length > 0)) } for (const arg of argv) { if (idPresent(finalizeId(arg))) final.push(arg) // If the parent topic has a command that expects positional arguments, then we cannot // assume that any subsequent string could be part of the command name - else if (isFlag(arg) || hasSubCommandsWithArgs()) break + else if (isArgWithValue(arg) || isFlag(arg) || hasSubCommandsWithArgs()) break else final.push(arg) } diff --git a/test/help/util.test.ts b/test/help/util.test.ts index e52265eb4..914474ac7 100644 --- a/test/help/util.test.ts +++ b/test/help/util.test.ts @@ -90,6 +90,18 @@ describe('util', () => { expect(actual).to.deep.equal(['foo:bar', 'baz']) }) + test + .stub(Config.prototype, 'commandIDs', () => ['foo', 'foo:bar']) + .it('should return standardized id when topic separator is a space and has variable arguments and flags', () => { + config.topicSeparator = ' ' + config.commands.push({ + id: 'foo:bar', + strict: false, + } as any) + const actual = standardizeIDFromArgv(['foo', 'bar', 'baz', '--hello'], config) + expect(actual).to.deep.equal(['foo:bar', 'baz', '--hello']) + }) + test .stub(Config.prototype, 'commandIDs', () => ['foo', 'foo:bar']) .it('should return full id when topic separator is a space and does not have arguments', () => { @@ -103,6 +115,24 @@ describe('util', () => { expect(actual).to.deep.equal(['foo:bar:baz']) }) + test + .stub(Config.prototype, 'commandIDs', () => ['foo', 'foo:bar']) + .it('should return standardized id when topic separator is a space and has arg with value', () => { + config.topicSeparator = ' ' + config.commands.push({id: 'foo:bar'} as any) + const actual = standardizeIDFromArgv(['foo', 'bar', 'hello=world'], config) + expect(actual).to.deep.equal(['foo:bar', 'hello=world']) + }) + + test + .stub(Config.prototype, 'commandIDs', () => ['foo', 'foo:bar']) + .it('should return standardized id when topic separator is a space and has variable args with value', () => { + config.topicSeparator = ' ' + config.commands.push({id: 'foo:bar', strict: false} as any) + const actual = standardizeIDFromArgv(['foo', 'bar', 'hello=world', 'my-arg=value'], config) + expect(actual).to.deep.equal(['foo:bar', 'hello=world', 'my-arg=value']) + }) + test .stub(Config.prototype, 'commandIDs', () => ['foo', 'foo:bar']) .it('should return standardized id when topic separator is a space and has flags', () => { @@ -114,11 +144,15 @@ describe('util', () => { test .stub(Config.prototype, 'commandIDs', () => ['foo', 'foo:bar']) - .it('should return standardized id when topic separator is a space and has flags with =', () => { + .it('should return standardized id when topic separator is a space and has flags, arg, and arg with value', () => { config.topicSeparator = ' ' - config.commands.push({id: 'foo:bar'} as any) - const actual = standardizeIDFromArgv(['foo', 'bar', '--hello=world'], config) - expect(actual).to.deep.equal(['foo:bar', '--hello=world']) + config.commands.push({ + id: 'foo:bar', + args: [{name: 'my-arg'}], + strict: true, + } as any) + const actual = standardizeIDFromArgv(['foo', 'bar', 'my-arg', 'hello=world', '--baz'], config) + expect(actual).to.deep.equal(['foo:bar', 'my-arg', 'hello=world', '--baz']) }) }) })