diff --git a/examples/versions.js b/examples/versions.js new file mode 100644 index 00000000..3edbfe02 --- /dev/null +++ b/examples/versions.js @@ -0,0 +1,24 @@ +require('ts-node/register') +const cli = require('../src/index').cac() + +cli + .command('build [...files]', 'build files') + .option('--type [type]', 'build type', { default: 'node' }) + .option('--target [target]', 'build target') + .action((files, options, type) => { + console.log(files, options) + }) + .version('1.0.0') + +cli + .command('set [...files]', 'build files') + .option('--type [type]', 'build type', { default: 'node' }) + .option('--target [target]', 'build target') + .action((files, options, type) => { + console.log(files, options) + }) + .version('1.0.1') + +cli.version('1.0.2') +cli.help() +cli.parse() diff --git a/src/CAC.ts b/src/CAC.ts index 7a3df11a..d8033006 100644 --- a/src/CAC.ts +++ b/src/CAC.ts @@ -96,6 +96,11 @@ class CAC extends EventEmitter { */ help(callback?: HelpCallback) { this.globalCommand.option('-h, --help', 'Display this message') + + for (const command of this.commands) { + command.option('-h, --help', 'Display this message') + } + this.globalCommand.helpCallback = callback this.showHelpOnExit = true return this @@ -140,7 +145,11 @@ class CAC extends EventEmitter { * */ outputVersion() { - this.globalCommand.outputVersion() + if (this.matchedCommand) { + this.matchedCommand.outputVersion() + } else { + this.globalCommand.outputVersion() + } } private setParsedInfo( @@ -220,7 +229,7 @@ class CAC extends EventEmitter { this.unsetMatchedCommand() } - if (this.options.version && this.showVersionOnExit && this.matchedCommandName == null) { + if (this.options.version && this.showVersionOnExit) { this.outputVersion() run = false this.unsetMatchedCommand() diff --git a/src/Command.ts b/src/Command.ts index 93027972..610414f7 100644 --- a/src/Command.ts +++ b/src/Command.ts @@ -119,6 +119,10 @@ class Command { return this instanceof GlobalCommand } + get isGlobalOrDefaultCommand(): boolean { + return this.isDefaultCommand || this.isGlobalCommand + } + /** * Check if an option is registered in this command * @param name Option name @@ -132,15 +136,11 @@ class Command { outputHelp() { const { name, commands } = this.cli - const { - versionNumber, - options: globalOptions, - helpCallback, - } = this.cli.globalCommand + const { options: globalOptions, helpCallback } = this.cli.globalCommand let sections: HelpSection[] = [ { - body: `${name}${versionNumber ? `/${versionNumber}` : ''}`, + body: this.getVersionOutput(), }, ] @@ -149,8 +149,7 @@ class Command { body: ` $ ${name} ${this.usageText || this.rawName}`, }) - const showCommands = - (this.isGlobalCommand || this.isDefaultCommand) && commands.length > 0 + const showCommands = this.isGlobalOrDefaultCommand && commands.length > 0 if (showCommands) { const longestCommandName = findLongest( @@ -180,12 +179,9 @@ class Command { }) } - let options = this.isGlobalCommand + let options = this.isGlobalOrDefaultCommand ? globalOptions - : [...this.options, ...(globalOptions || [])] - if (!this.isGlobalCommand && !this.isDefaultCommand) { - options = options.filter((option) => option.name !== 'version') - } + : [...this.options] if (options.length > 0) { const longestOptionName = findLongest( options.map((option) => option.rawName) @@ -235,11 +231,21 @@ class Command { ) } - outputVersion() { + private getVersionOutput(): string { const { name } = this.cli - const { versionNumber } = this.cli.globalCommand - if (versionNumber) { - console.log(`${name}/${versionNumber} ${platformInfo}`) + const commandVersion = this.versionNumber + const globalVersion = this.cli.globalCommand.versionNumber + + if (!this.isGlobalOrDefaultCommand && commandVersion) { + return `${name} ${this.name}/${commandVersion} ${platformInfo}` + } else { + return `${name}/${globalVersion} ${platformInfo}` + } + } + outputVersion() { + const versionText = this.getVersionOutput() + if (versionText) { + console.log(versionText) } } diff --git a/src/__test__/index.test.ts b/src/__test__/index.test.ts index 6cb84069..dee43ab9 100644 --- a/src/__test__/index.test.ts +++ b/src/__test__/index.test.ts @@ -176,3 +176,34 @@ describe('--version in help message', () => { expect(output).toContain(`--version`) }) }) + +describe('cli version and sub-command version', () => { + test('global command version', async () => { + const output = await getOutput('versions.js', ['-v']) + expect(output).toContain('1.0.2') + }) + + test('sub command version', async () => { + const output1 = await getOutput('versions.js', ['build', '-v']) + expect(output1).toContain('1.0.0') + + const output2 = await getOutput('versions.js', ['set', '-v']) + expect(output2).toContain('1.0.1') + + //help message + const output_help = await getOutput('versions.js', ['set', '--help']) + expect(output_help).toContain('--version') + }) + + test('without sub-command version', async () => { + const default_command_output = await getOutput('help.js', ['-v']) + expect(default_command_output).toContain('0.0.0') + + const sub_command_output = await getOutput('help.js', ['lint', '-v']) + expect(sub_command_output).toEqual(default_command_output) // fall back to default + + //help message + const sub_command_help = await getOutput('help.js', ['lint', '-h']) + expect(sub_command_help).not.toContain('--version') + }) +})