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(), }) } var fishTpl = template.Must(template.New("fish").Funcs(tplFuncs).Parse(` set -l progName {{ .RootCmd.Name }} set -l commands {{- range .RootCmd.Subcommands }} {{ .Name }}{{ end }} {{- /* Option template */ -}} {{ define "opt" }} complete -c $progName {{- if ne .Opt.ShortName "" }} -s {{ .Opt.ShortName }} {{ end -}} {{- if ne .Opt.Name "" }} -l {{ .Opt.Name }} {{ end -}} {{- if .Cond }} -n "{{ .Cond }}" {{ end -}} -d '{{ .Opt.Description }}' {{- end }} {{- /* Command template */ -}} {{ define "cmd" }} {{ $parentVarPrefix := "" -}} {{- $varPrefix := join .Cmd.Name "_" -}} {{- if .VarPrefix -}} {{- $varPrefix = join .VarPrefix $varPrefix -}} {{- $parentVarPrefix = .VarPrefix -}} {{- end -}} {{ $parentCond := "" }} {{- $cond := join "__fish_seen_subcommand_from " .Cmd.Name }} {{- if .Prefix -}} {{- $cond = join .Prefix $cond -}} {{- $parentCond = .Prefix -}} {{- end -}} set -l {{ $varPrefix }}commands {{- range .Cmd.Subcommands }} {{ .Name }}{{ end }} complete -f -c $progName -n "{{ $parentCond }}not __fish_seen_subcommand_from ${{ $parentVarPrefix }}commands" -a {{ .Cmd.Name }} -d "{{ .Cmd.ShortDescription }}" {{- range .Cmd.Opts }} {{- template "opt" (map "Opt" . "Cond" $cond) -}} {{ end -}} {{ $cmdName := .Cmd.Name }} {{- range .Cmd.Subcommands }} {{- template "cmd" (map "Cmd" . "Prefix" (join $cond "; ") "VarPrefix" $varPrefix) -}} {{ end -}} {{ end }} {{- /* Top-level commands */ -}} {{ range .RootCmd.Subcommands }} {{- template "cmd" (map "Cmd" .) -}} {{ end }} {{- /* Root command options */ -}} {{ range .RootCmd.Opts }} {{- template "opt" (map "Opt" . "Cond" "not __fish_seen_subcommand_from $commands") -}} {{ end }} {{- /* Global options */ -}} {{ range .GlobalOpts }} {{- template "opt" (map "Opt" .) -}} {{ end }} `))