diff --git a/jslib b/jslib index 8438cafbd0..2858724f44 160000 --- a/jslib +++ b/jslib @@ -1 +1 @@ -Subproject commit 8438cafbd08c1c9b1440e0c5385e15e8fb5ac524 +Subproject commit 2858724f4431038be190fc0b748efe287dd1bae6 diff --git a/src/commands/completion.command.ts b/src/commands/completion.command.ts index 289377c608..88cbf28caa 100644 --- a/src/commands/completion.command.ts +++ b/src/commands/completion.command.ts @@ -1,55 +1,81 @@ -import * as program from "commander"; -import { Response } from "jslib/cli/models/response"; -import { MessageResponse } from "jslib/cli/models/response/messageResponse"; +import * as program from 'commander'; -type Option = { +import { Response } from 'jslib/cli/models/response'; +import { MessageResponse } from 'jslib/cli/models/response/messageResponse'; + +interface IOption { long: string; short: string; description: string; -}; +} -type Command = { - commands?: Command[]; - options?: Option[]; +interface ICommand { + commands?: ICommand[]; + options?: IOption[]; _name: string; _description: string; -}; +} -const zshCompletion = (rootName: string, rootCommand: Command) => { - const renderCommandBlock = (name: string, command: Command): string => { +const validShells = ['zsh']; + +export class CompletionCommand { + async run(cmd: program.Command) { + const shell: typeof validShells[number] = cmd.shell; + + if (!shell) { + return Response.badRequest('`shell` was not provided.'); + } + + if (!validShells.includes(shell)) { + return Response.badRequest('Unsupported shell.'); + } + + let content = ''; + + if (shell === 'zsh') { + content = this.zshCompletion('bw', cmd.parent).render(); + } + + const res = new MessageResponse(content, null); + return Response.success(res); + } + + private zshCompletion(rootName: string, rootCommand: ICommand) { + return { + render: () => { + return [ + `#compdef _${rootName} ${rootName}`, + '', + this.renderCommandBlock(rootName, rootCommand), + ].join('\n'); + }, + }; + } + + private renderCommandBlock(name: string, command: ICommand): string { const { commands = [], options = [] } = command; const hasOptions = options.length > 0; const hasCommands = commands.length > 0; - const _arguments = options + const args = options .map(({ long, short, description }) => { const aliases = [short, long].filter(Boolean); - - const OPTS = aliases.join(","); - - const DESCRIPTION = `[${description.replace("'", `'"'"'`)}]`; - - return aliases.length > 1 - ? `'(${aliases.join(" ")})'{${OPTS}}'${DESCRIPTION}'` - : `'${OPTS}${DESCRIPTION}'`; - }) - .concat( - `'(-h --help)'{-h,--help}'[output usage information]'`, + const opts = aliases.join(','); + const desc = `[${description.replace(`'`, `'"'"'`)}]`; + return aliases.length > 1 ? `'(${aliases.join(' ')})'{${opts}}'${desc}'` : `'${opts}${desc}'`; + }).concat(`'(-h --help)'{-h,--help}'[output usage information]'`, hasCommands ? '"1: :->cmnds"' : null, - '"*::arg:->args"' - ) - .filter(Boolean); + '"*::arg:->args"', + ).filter(Boolean); const commandBlockFunctionParts = []; if (hasCommands) { - commandBlockFunctionParts.push("local -a commands"); + commandBlockFunctionParts.push('local -a commands'); } if (hasOptions) { - commandBlockFunctionParts.push( - `_arguments -C \\\n ${_arguments.join(` \\\n `)}` - ); + commandBlockFunctionParts.push(`_arguments -C \\\n ${args.join(` \\\n `)}`); } if (hasCommands) { @@ -57,79 +83,28 @@ const zshCompletion = (rootName: string, rootCommand: Command) => { `case $state in cmnds) commands=( - ${commands - .map(({ _name, _description }) => `"${_name}:${_description}"`) - .join("\n ")} + ${commands.map(({ _name, _description }) => `"${_name}:${_description}"`).join('\n ')} ) _describe "command" commands ;; esac case "$words[1]" in - ${commands - .map(({ _name }) => - [`${_name})`, `_${name}_${_name}`, ";;"].join("\n ") - ) - .join("\n ")} - esac` + ${commands.map(({ _name }) => [`${_name})`, `_${name}_${_name}`, ';;'].join('\n ')).join('\n ')} + esac`, ); } const commandBlocParts = [ - `function _${name} {\n ${commandBlockFunctionParts.join( - "\n\n " - )}\n}`, + `function _${name} {\n ${commandBlockFunctionParts.join('\n\n ')}\n}`, ]; if (hasCommands) { commandBlocParts.push( - commands - .map((command) => - renderCommandBlock(`${name}_${command._name}`, command) - ) - .join("\n\n") + commands.map((c) => this.renderCommandBlock(`${name}_${c._name}`, c)).join('\n\n'), ); } - return commandBlocParts.join("\n\n"); - }; - - const render = () => { - return [ - `#compdef _${rootName} ${rootName}`, - "", - renderCommandBlock(rootName, rootCommand), - ].join("\n"); - }; - - return { - render, - }; -}; - -const validShells = ["zsh"]; - -export class CompletionCommand { - constructor() {} - - async run(cmd: program.Command) { - const shell: typeof validShells[number] = cmd.shell; - - if (!shell) { - return Response.badRequest("`shell` was not provided!"); - } - - if (!validShells.includes(shell)) { - return Response.badRequest(`Unsupported shell!`); - } - - let content = ""; - - if (shell === "zsh") { - content = zshCompletion("bw", cmd.parent).render(); - } - - const res = new MessageResponse(content, null); - return Response.success(res); + return commandBlocParts.join('\n\n'); } } diff --git a/src/program.ts b/src/program.ts index beb1d7791b..f9dbb5b842 100644 --- a/src/program.ts +++ b/src/program.ts @@ -669,7 +669,7 @@ export class Program extends BaseProgram { .on('--help', () => { writeLn('\n Notes:'); writeLn(''); - writeLn(' Valid shells are `zsh`.') + writeLn(' Valid shells are `zsh`.'); writeLn(''); writeLn(' Examples:'); writeLn(''); @@ -680,7 +680,7 @@ export class Program extends BaseProgram { const command = new CompletionCommand(); const response = await command.run(cmd); this.processResponse(response); - }) + }); program .parse(process.argv);