zsh-completion: two fixes for identifying flag usage:

Fixed after input from @eparis:
- Decide on option parameter by checking NoOptDefVal
- Slices also could be specified multiple times.
This commit is contained in:
Haim Ashkenazi 2018-02-28 21:52:35 +02:00 committed by Steve Francia
parent e9ee8f0446
commit df12a0a249
2 changed files with 26 additions and 4 deletions

View file

@ -131,7 +131,7 @@ func genFlagEntryForZshArguments(f *pflag.Flag) string {
func genFlagEntryForSingleOptionFlag(f *pflag.Flag) string { func genFlagEntryForSingleOptionFlag(f *pflag.Flag) string {
var option, multiMark, extras string var option, multiMark, extras string
if f.Value.Type() == "stringArray" { if flagCouldBeSpecifiedMoreThenOnce(f) {
multiMark = "*" multiMark = "*"
} }
@ -147,7 +147,7 @@ func genFlagEntryForSingleOptionFlag(f *pflag.Flag) string {
func genFlagEntryForMultiOptionFlag(f *pflag.Flag) string { func genFlagEntryForMultiOptionFlag(f *pflag.Flag) string {
var options, parenMultiMark, curlyMultiMark, extras string var options, parenMultiMark, curlyMultiMark, extras string
if f.Value.Type() == "stringArray" { if flagCouldBeSpecifiedMoreThenOnce(f) {
parenMultiMark = "*" parenMultiMark = "*"
curlyMultiMark = "\\*" curlyMultiMark = "\\*"
} }
@ -165,9 +165,14 @@ func genZshFlagEntryExtras(f *pflag.Flag) string {
_, pathSpecified := f.Annotations[BashCompFilenameExt] _, pathSpecified := f.Annotations[BashCompFilenameExt]
if pathSpecified { if pathSpecified {
extras = ":filename:_files" extras = ":filename:_files"
} else if !strings.HasPrefix(f.Value.Type(), "bool") { } else if f.NoOptDefVal == "" {
extras = ":" // allow option variable without assisting extras = ":" // allow option variable without assisting
} }
return extras return extras
} }
func flagCouldBeSpecifiedMoreThenOnce(f *pflag.Flag) bool {
return strings.Contains(f.Value.Type(), "Slice") ||
strings.Contains(f.Value.Type(), "Array")
}

View file

@ -15,6 +15,7 @@ func TestGenZshCompletion(t *testing.T) {
name string name string
root *Command root *Command
expectedExpressions []string expectedExpressions []string
skip string
}{ }{
{ {
name: "simple command", name: "simple command",
@ -99,7 +100,7 @@ func TestGenZshCompletion(t *testing.T) {
name: "repeated variables both with and without value", name: "repeated variables both with and without value",
root: func() *Command { root: func() *Command {
r := genTestCommand("mycmd", true) r := genTestCommand("mycmd", true)
_ = r.Flags().StringArrayP("debug", "d", []string{}, "debug usage") _ = r.Flags().BoolSliceP("debug", "d", []bool{}, "debug usage")
_ = r.Flags().StringArray("option", []string{}, "options") _ = r.Flags().StringArray("option", []string{}, "options")
return r return r
}(), }(),
@ -108,6 +109,18 @@ func TestGenZshCompletion(t *testing.T) {
`"\(\*-d \*--debug\)"{\\\*-d,\\\*--debug}`, `"\(\*-d \*--debug\)"{\\\*-d,\\\*--debug}`,
}, },
}, },
{
name: "boolSlice should not accept arguments",
root: func() *Command {
r := genTestCommand("mycmd", true)
r.Flags().BoolSlice("verbose", []bool{}, "verbosity level")
return r
}(),
expectedExpressions: []string{
`"\*--verbose\[verbosity level]"`,
},
skip: "BoolSlice behaves strangely both with NoOptDefVal and type (identifies as bool)",
},
} }
for _, tc := range tcs { for _, tc := range tcs {
@ -119,6 +132,10 @@ func TestGenZshCompletion(t *testing.T) {
} }
output := buf.Bytes() output := buf.Bytes()
if tc.skip != "" {
t.Skip("Skipping:", tc.skip)
}
for _, expr := range tc.expectedExpressions { for _, expr := range tc.expectedExpressions {
rgx, err := regexp.Compile(expr) rgx, err := regexp.Compile(expr)
if err != nil { if err != nil {