UNPKG

@clerc/plugin-completions

Version:
135 lines (124 loc) 4.24 kB
import { definePlugin } from '@clerc/core'; import { gracefulFlagName, kebabCase } from '@clerc/utils'; const generateCommandCompletion = (name) => ` ${name}) cmd+="__${name}" ;;`; function getBashCompletion(ctx) { const { cli } = ctx; const { _scriptName: name, _commands: commands } = cli; return `_${name}() { local i cur prev opts cmds COMPREPLY=() cur="\${COMP_WORDS[COMP_CWORD]}" prev="\${COMP_WORDS[COMP_CWORD-1]}" cmd="" opts="" for i in \${COMP_WORDS[@]} do case "\${i}" in "$1") cmd="${name}" ;; ${Object.keys(commands).map(generateCommandCompletion).join("")} *) ;; esac done } complete -F _${name} -o bashdefault -o default ${name} `; } const NO_DESCRIPTION = "(No Description)"; const getCompletionValue = (command) => `[CompletionResult]::new('${command.name}', '${command.name}', [CompletionResultType]::ParameterValue, '${command.description}')`; const getCompletionFlag = (command) => { var _a; return Object.entries((_a = command.flags) != null ? _a : {}).map(([flagName, flag]) => { const gen = [ `[CompletionResult]::new('${gracefulFlagName(flagName)}', '${kebabCase( flagName )}', [CompletionResultType]::ParameterName, '${command.flags[flagName].description || NO_DESCRIPTION}')` ]; if (flag == null ? void 0 : flag.alias) { gen.push( `[CompletionResult]::new('${gracefulFlagName(flag.alias)}', '${flag.alias}', [CompletionResultType]::ParameterName, '${command.flags[flagName].description || NO_DESCRIPTION}')` ); } return gen.join("\n "); }).join("\n "); }; function getPwshCompletion(ctx) { const { cli } = ctx; const { _scriptName: name, _commands: commands } = cli; return `using namespace System.Management.Automation using namespace System.Management.Automation.Language Register-ArgumentCompleter -Native -CommandName '${name}' -ScriptBlock { param($wordToComplete, $commandAst, $cursorPosition) $commandElements = $commandAst.CommandElements $command = @( '${name}' for ($i = 1; $i -lt $commandElements.Count; $i++) { $element = $commandElements[$i] if ($element -isnot [StringConstantExpressionAst] -or $element.StringConstantType -ne [StringConstantType]::BareWord -or $element.Value.StartsWith('-') -or $element.Value -eq $wordToComplete) { break } $element.Value }) -join ';' $completions = @(switch ($command) { '${name}' { ${Object.entries(commands).map(([_, command]) => getCompletionValue(command)).join("\n ")} break } ${Object.entries(commands).map( ([commandName, command]) => `'${name};${commandName.split(" ").join(";")}' { ${getCompletionFlag(command)} break }` ).join("\n ")} }) $completions.Where{ $_.CompletionText -like "$wordToComplete*" } | Sort-Object -Property ListItemText }`; } const completionMap = { bash: getBashCompletion, pwsh: getPwshCompletion }; const completionsPlugin = (options = {}) => definePlugin({ setup: (cli) => { const { command = true } = options; if (command) { cli = cli.command("completions", "Print shell completions to stdout", { flags: { shell: { description: "Shell type", type: String, default: "" } }, parameters: ["[shell]"] }).on("completions", (ctx) => { var _a; if (!cli._scriptName) { throw new Error("CLI name is not defined!"); } const shell = String((_a = ctx.parameters.shell) != null ? _a : ctx.flags.shell); if (!shell) { throw new Error("Missing shell name"); } if (shell in completionMap) { process.stdout.write( completionMap[shell](ctx) ); } else { throw new Error(`No such shell: ${shell}`); } }); } return cli; } }); export { completionsPlugin };