package cmd import ( "io" "text/template" "go.fifitido.net/cmd/opt" ) func WriteFishCompletions(out io.Writer, rootCmd *Command) error { return fishTpl.Execute(out, map[string]any{ "RootCmd": rootCmd, "GlobalOpts": opt.Globals(), }) } // TODO: Fix fish infinitely completing last command at the end of the command chain var fishTpl = template.Must(template.New("fish").Funcs(tplFuncs).Parse(` {{- $rootCmd := .RootCmd -}} {{- $progName := $rootCmd.Name -}} {{- $varName := under $rootCmd.Name -}} set -l commands {{ join $rootCmd.Subcommands.Names " " }} function __fish_{{ $varName }}_needs_command set -l cmd (commandline -opc) if test (count $cmd) -eq 1 return 0 end return 1 end function __fish_{{ $varName }}_using_command set -l cmd (commandline -opc) set -l cnt (count $argv) if test (count $cmd) -gt $cnt for i in (seq 1 $cnt); if test $argv[$i] != $cmd[(math $i + 1)] return 1 end end return 0 end return 1 end {{/* Option template */ -}} {{ define "opt" }} {{ $progName := .ProgName -}} {{- $varName := .VarName -}} complete -c {{ $progName }} {{- if ne .Opt.ShortName "" }} -s {{ .Opt.ShortName }} {{ end -}} {{- if ne .Opt.Name "" }} -l {{ .Opt.Name }} {{ end -}} {{- if .Cmd }} {{- if ne .Cmd.CommandPath "" -}} -n "__fish_{{ $varName }}_using_command {{.Cmd.CommandPath}}" {{ else -}} -n "__fish_{{ $varName }}_needs_command" {{ end -}}{{- end -}} -d '{{ .Opt.Description }}' {{- end }} {{- /* Command template */ -}} {{ define "cmd" }} {{ $progName := .ProgName -}} {{- $varName := .VarName -}} {{- $cmd := .Cmd -}} {{- $parentVarPrefix := varPrefix .Cmd.Parent.CommandPath -}} {{- $varPrefix := varPrefix .Cmd.CommandPath -}} {{- if eq .Cmd.Parent.CommandPath "" -}} complete -f -c {{ $progName }} -n "__fish_{{ $varName }}_needs_command" -a {{ .Cmd.Name }} -d "{{ .Cmd.ShortDescription }}" {{- else -}} complete -f -c {{ $progName }} -n "__fish_{{ $varName }}_using_command {{.Cmd.Parent.CommandPath}}" -a {{ .Cmd.Name }} -d "{{ .Cmd.ShortDescription }}" {{- end -}} {{- range .Cmd.Opts }} {{- template "opt" (map "Opt" . "ProgName" $progName "VarName" $varName "Cmd" $cmd) -}} {{ end -}} {{ if gt (len .Cmd.Subcommands) 0 }} set -l {{ $varPrefix }}commands {{ join .Cmd.Subcommands.Names " " }} {{ $cmdName := .Cmd.Name }} {{- range .Cmd.Subcommands }} {{- template "cmd" (map "Cmd" . "ProgName" $progName "VarName" $varName) -}} {{ end -}} {{- end -}} {{ end }} {{- /* Top-level commands */ -}} {{ range $rootCmd.Subcommands }} {{- template "cmd" (map "Cmd" . "ProgName" $progName "VarName" $varName) -}} {{ end }} {{- /* Root command options */ -}} {{ range $rootCmd.Opts }} {{- template "opt" (map "Opt" . "ProgName" $progName "VarName" $varName "Cmd" $rootCmd) -}} {{ end }} {{- /* Global options */ -}} {{ range .GlobalOpts }} {{- template "opt" (map "Opt" . "ProgName" $progName "VarName" $varName) -}} {{ end }} `))