diff --git a/command.go b/command.go index e82b256..c42a169 100644 --- a/command.go +++ b/command.go @@ -46,6 +46,10 @@ func (c *Command) Root() *Command { return c.Parent.Root() } +func (c *Command) IsRoot() bool { + return c.isRoot +} + func (c *Command) CommandPath() string { if c.Parent == nil { return "" diff --git a/completions_bash.go b/completions_bash.go index 71a11c0..1331127 100644 --- a/completions_bash.go +++ b/completions_bash.go @@ -15,6 +15,7 @@ func WriteBashCompletions(out io.Writer, rootCmd *Command) error { } // TODO: Add --option|--other-option...) to return nothing for options that require a value +// TODO: Add descriptions to completions using https://stackoverflow.com/a/10130007 var bashTpl = template.Must(template.New("bash").Funcs(tplFuncs).Parse(` {{- $rootCmd := .RootCmd -}} {{- $progName := $rootCmd.Name -}} diff --git a/completions_zsh.go b/completions_zsh.go index 885ec41..50f0cf7 100644 --- a/completions_zsh.go +++ b/completions_zsh.go @@ -9,11 +9,61 @@ import ( func WriteZshCompletions(out io.Writer, rootCmd *Command) error { return zshTpl.Execute(out, map[string]any{ - "rootCmd": rootCmd, - "globalOpts": opt.Globals(), + "RootCmd": rootCmd, + "GlobalOpts": opt.Globals(), }) } -var zshTpl = template.Must(template.New("zsh").Parse(` - +// TODO: Fix indentation and other spacing +var zshTpl = template.Must(template.New("zsh").Funcs(tplFuncs).Parse(` +{{- $rootCmd := .RootCmd -}} +{{- $progName := $rootCmd.Name -}} +{{- $varName := under $rootCmd.Name -}} + +{{- define "cmd" }} +{{- $varPrefix := varPrefix .Cmd.CommandPath -}} +{{- if not .Cmd.IsRoot}} +{{ .Cmd.Name }}) +{{ end -}} + {{ if gt (len .Cmd.Subcommands) 0 -}} + local -a {{ $varPrefix }}commands + {{ $varPrefix }}commands=( + {{- range .Cmd.Subcommands}} + '{{ .Name }}:{{ .ShortDescription }}' + {{- end }} + ) + {{ end }} + + {{- if or (gt (len .Cmd.Opts) 0) (gt (len .Cmd.Subcommands) 0) -}} + _arguments + {{- end -}} + {{- range .Cmd.Opts -}} + {{ " " }}\ + '-{{ .ShortName }}[{{ .Description }}]' + {{- end }} + {{- if gt (len .Cmd.Subcommands) 0 -}} + {{ " " }}\ + '1: :{_describe 'command' {{ $varPrefix }}commands}' \ + '*:: :->args' + + case $state in + args) + case $words[1] in + {{- range .Cmd.Subcommands }} + {{ template "cmd" (map "Cmd" .) }} + {{- end }} + esac + ;; + esac + {{- end }} +{{- if not .Cmd.IsRoot}} + ;; +{{ end }} +{{ end -}} + +function _{{ $varName }} { + {{ template "cmd" (map "Cmd" .RootCmd) -}} +} + +compdef _{{ $varName }} {{ $progName }} `))