zsh-completion: added support for subcommand description.

Also make the template more elegant on the way...
This commit is contained in:
Haim Ashkenazi 2018-02-26 22:31:06 +02:00 committed by Steve Francia
parent f0508c8e76
commit 2662787697
2 changed files with 84 additions and 35 deletions

View file

@ -37,43 +37,50 @@ var (
{{/* should accept Command (that contains subcommands) as parameter */}} {{/* should accept Command (that contains subcommands) as parameter */}}
{{define "argumentsC" -}} {{define "argumentsC" -}}
function {{constructPath .}} { function {{constructPath .}} {
local line local -a commands
_arguments -C \ _arguments -C \{{- range extractFlags .}}
{{range extractFlags . -}} {{if simpleFlag .}}{{template "simpleFlag" .}}{{else}}{{template "complexFlag" .}}{{end}} \{{- end}}
{{" "}}{{if simpleFlag .}}{{template "simpleFlag" .}}{{else}}{{template "complexFlag" .}}{{end}} \ "1: :->cmnds" \
{{end}} "1: :({{subCmdList .}})" \
"*::arg:->args" "*::arg:->args"
case $line[1] in {{- range .Commands}}{{if not .Hidden}} case $state in
{{cmdName .}}) cmnds)
{{constructPath .}} commands=({{range .Commands}}{{if not .Hidden}}
;; "{{cmdName .}}:{{.Short}}"{{end}}{{end}}
{{end}}{{end}} esac )
_describe "command" commands
;;
esac
case "$words[1]" in {{- range .Commands}}{{if not .Hidden}}
{{cmdName .}})
{{constructPath .}}
;;{{end}}{{end}}
esac
} }
{{range .Commands}} {{range .Commands}}{{if not .Hidden}}
{{template "selectCmdTemplate" .}} {{template "selectCmdTemplate" .}}
{{- end}} {{- end}}{{end}}
{{- end}} {{- end}}
{{/* should accept Command without subcommands as parameter */}} {{/* should accept Command without subcommands as parameter */}}
{{define "arguments" -}} {{define "arguments" -}}
function {{constructPath .}} { function {{constructPath .}} {
{{with extractFlags . -}} {{" _arguments"}}{{range extractFlags .}} \
{{ " _arguments" -}}
{{range .}} \
{{if simpleFlag .}}{{template "simpleFlag" .}}{{else}}{{template "complexFlag" .}}{{end -}} {{if simpleFlag .}}{{template "simpleFlag" .}}{{else}}{{template "complexFlag" .}}{{end -}}
{{end}} {{end}}
{{end -}}
} }
{{- end}} {{end}}
{{/* dispatcher for commands with or without subcommands */}}
{{define "selectCmdTemplate" -}} {{define "selectCmdTemplate" -}}
{{if .Hidden}}{{/* ignore hidden*/}}{{else -}} {{if .Hidden}}{{/* ignore hidden*/}}{{else -}}
{{if .Commands}}{{template "argumentsC" .}}{{else}}{{template "arguments" .}}{{end}} {{if .Commands}}{{template "argumentsC" .}}{{else}}{{template "arguments" .}}{{end}}
{{- end}} {{- end}}
{{- end}} {{- end}}
{{/* template entry point */}}
{{define "Main" -}} {{define "Main" -}}
#compdef _{{cmdName .}} {{cmdName .}} #compdef _{{cmdName .}} {{cmdName .}}

View file

@ -70,7 +70,7 @@ func TestGenZshCompletion(t *testing.T) {
return r return r
}(), }(),
expectedExpressions: []string{ expectedExpressions: []string{
`\\\n\s+"1: :\(help subcmd1 subcmd2\)" \\\n`, `commands=\(\n\s+"help:.*\n\s+"subcmd1:.*\n\s+"subcmd2:.*\n\s+\)`,
`_arguments \\\n.*"--debug\[description]"`, `_arguments \\\n.*"--debug\[description]"`,
`_arguments -C \\\n.*"--debug\[description]"`, `_arguments -C \\\n.*"--debug\[description]"`,
`function _rootcmd_subcmd1 {`, `function _rootcmd_subcmd1 {`,
@ -185,24 +185,17 @@ func TestGenZshCompletionHidden(t *testing.T) {
} }
} }
func BenchmarkConstructPath(b *testing.B) { func BenchmarkMediumSizeConstruct(b *testing.B) {
c := &Command{ root := constructLargeCommandHeirarchy()
Use: "main", // if err := root.GenZshCompletionFile("_mycmd"); err != nil {
Long: "main long description which is very long", // b.Error(err)
Short: "main short description", // }
}
d := &Command{
Use: "hello",
}
e := &Command{
Use: "world",
}
c.AddCommand(d)
d.AddCommand(e)
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
res := constructPath(e) buf := new(bytes.Buffer)
if res != "_main_hello_world" { err := root.GenZshCompletion(buf)
b.Errorf("expeced path to be '_main_hello_world', got %s", res) if err != nil {
b.Error(err)
} }
} }
} }
@ -232,3 +225,52 @@ func TestExtractFlags(t *testing.T) {
t.Errorf("expected Command D to return 2 flags, got %d", len(resD)) t.Errorf("expected Command D to return 2 flags, got %d", len(resD))
} }
} }
func constructLargeCommandHeirarchy() *Command {
var config, st1, st2 string
var long, debug bool
var in1, in2 int
r := genTestCommand("mycmd", false)
r.PersistentFlags().StringVarP(&config, "config", "c", config, "config usage")
if err := r.MarkPersistentFlagFilename("config", "*"); err != nil {
panic(err)
}
s1 := genTestCommand("sub1", true)
s1.Flags().BoolVar(&long, "long", long, "long descriptin")
s2 := genTestCommand("sub2", true)
s2.PersistentFlags().BoolVar(&debug, "debug", debug, "debug description")
s3 := genTestCommand("sub3", true)
s3.Hidden = true
s1_1 := genTestCommand("sub1sub1", true)
s1_1.Flags().StringVar(&st1, "st1", st1, "st1 description")
s1_1.Flags().StringVar(&st2, "st2", st2, "st2 description")
s1_2 := genTestCommand("sub1sub2", true)
s1_3 := genTestCommand("sub1sub3", true)
s1_3.Flags().IntVar(&in1, "int1", in1, "int1 descriptionn")
s1_3.Flags().IntVar(&in2, "int2", in2, "int2 descriptionn")
s2_1 := genTestCommand("sub2sub1", true)
s2_2 := genTestCommand("sub2sub2", true)
s2_3 := genTestCommand("sub2sub3", true)
s2_4 := genTestCommand("sub2sub4", true)
s2_5 := genTestCommand("sub2sub5", true)
s1.AddCommand(s1_1, s1_2, s1_3)
s2.AddCommand(s2_1, s2_2, s2_3, s2_4, s2_5)
r.AddCommand(s1, s2, s3)
r.Execute()
return r
}
func genTestCommand(name string, withRun bool) *Command {
r := &Command{
Use: name,
Short: name + " short description",
Long: "Long description for " + name,
}
if withRun {
r.Run = emptyRun
}
return r
}