cmd/completions_fish.go

101 lines
2.8 KiB
Go

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 }}
`))