import type { CommandFlag, CommandSpec } from 'lib/commands/spec.js' import { describeForShell } from './describe.js' export const renderFishCompletion = (spec: CommandSpec): string => `${[ header, helpers, ['complete -c seam -f', ...subcommandCompletions(spec)].join('\n'), flagCompletions(spec).join('\n'), globalFlagCompletions(spec).join('\n'), ].join('\n\n')}\n` const header = `# fish completion for the seam command. # # Generated by @seamapi/cli from the Seam API schema. # Do not edit: regenerate with 'seam completion fish'. # # Install it with # # seam completion fish > ~/.config/fish/completions/seam.fish` const helpers = `function __seam_command --description 'Print the seam command path on the command-line' set -l tokens (commandline -opc) set -l command if test (count $tokens) -gt 1 # The command path is the run of words before the first flag. for token in $tokens[2..-1] if string match -q -- '-*' $token break end set -a command $token end end string join ' ' -- $command end function __seam_using --description 'Test whether the command-line names the given seam command' set -l command (__seam_command) test "$command" = "$argv[1]" end` const subcommandCompletions = (spec: CommandSpec): string[] => spec.groups.flatMap((group) => group.subcommands.map(({ name, description }) => complete([ `-n '__seam_using "${group.path.join(' ')}"'`, `-a '${name}'`, describe(description), ]), ), ) const flagCompletions = (spec: CommandSpec): string[] => spec.commands.flatMap((command) => command.flags.map((flag) => complete([ `-n '__seam_using "${command.path.join(' ')}"'`, ...flagOptions(flag), ]), ), ) const globalFlagCompletions = (spec: CommandSpec): string[] => spec.globalFlags.map((flag) => complete(flagOptions(flag))) const flagOptions = (flag: CommandFlag): string[] => [ ...(flag.short == null ? [] : [`-s ${flag.short}`]), ...(flag.long == null ? [] : [`-l ${flag.long}`]), ...(flag.takesValue ? ['-r'] : []), ...(flag.values.length === 0 ? [] : [`-a '${flag.values.join(' ')}'`]), describe(flag.description), ] const describe = (description: string): string => { const summary = describeForShell(description) return summary === '' ? '' : `-d '${summary}'` } const complete = (options: string[]): string => ['complete -c seam', ...options.filter((option) => option !== '')].join(' ')