diff --git a/NodeApp/src/commander/completion/subcommands/CompletionGetCommand.ts b/NodeApp/src/commander/completion/subcommands/CompletionGetCommand.ts new file mode 100644 index 0000000000000000000000000000000000000000..f57aa7059a1b1459f7d6c0cc9b4d560ed5a0cd44 --- /dev/null +++ b/NodeApp/src/commander/completion/subcommands/CompletionGetCommand.ts @@ -0,0 +1,69 @@ +import CommanderCommand from '../../CommanderCommand'; +import { Command, CommandOptions, Option } from 'commander'; +import * as AutoCompletionHelper from '../../../helpers/AutoCompletionHelper'; + + +type CompletionProposal = { name: string, description: string }; + + +class CompletionGetCommand extends CommanderCommand { + protected commandName: string = 'get'; + protected options: CommandOptions = { + hidden: true + }; + + protected defineCommand() { + this.command.description('generate completion options for a given command') + .addOption(new Option('-s, --shell <shell>', 'shell completion result format').choices([ 'bash', 'zsh' ])) + .argument('<commands...>', 'command chain to complete') + .action(this.commandAction.bind(this)); + } + + private completion(commandsChain: Array<string>, displayFunction: (completionProposals: Array<CompletionProposal>) => void) { + const command = AutoCompletionHelper.getCommandFromChain(AutoCompletionHelper.getRoot(this.command), commandsChain.slice(1)); + + if ( command ) { + const commands = command.commands.filter(cmd => !(cmd as Command & { _hidden: boolean })._hidden); + const options = command.options.filter(option => !option.hidden); + + displayFunction([ ...commands.flatMap(cmd => [ { + name : cmd.name(), + description: cmd.description() + }, ...cmd.aliases().map(alias => ({ + name : alias, + description: cmd.description() + })) ]), ...options.flatMap(option => [ { + name : option.long, + description: option.description + }, { + name : option.short, + description: option.description + } ]) ].filter(proposal => proposal.name) as Array<CompletionProposal>); + } + } + + private bashCompletion(commandsChain: Array<string>) { + this.completion(commandsChain, (completionProposals: Array<CompletionProposal>) => console.log(completionProposals.map(proposal => proposal.name).join(' '))); + } + + private zshCompletion(commandsChain: Array<string>) { + this.completion(commandsChain, (completionProposals: Array<CompletionProposal>) => completionProposals.forEach(proposal => console.log(`${ proposal.name }:${ proposal.description }`))); + } + + protected async commandAction(commandsChain: Array<string>, options: { shell: 'bash' | 'zsh' }): Promise<void> { + switch ( options.shell ) { + case 'bash': + this.bashCompletion(commandsChain); + break; + case 'zsh': + this.zshCompletion(commandsChain); + break; + default: + console.error('Unsupported shell completion format'); + break; + } + } +} + + +export default new CompletionGetCommand(); \ No newline at end of file