mirror of
https://github.com/spf13/cobra
synced 2024-11-24 22:57:12 +00:00
zsh-completion: added support for filename globbing.
This commit is contained in:
parent
bda855a1a0
commit
50f385938e
3 changed files with 21 additions and 17 deletions
|
@ -137,7 +137,7 @@ func genFlagEntryForSingleOptionFlag(f *pflag.Flag) string {
|
||||||
}
|
}
|
||||||
extras = genZshFlagEntryExtras(f)
|
extras = genZshFlagEntryExtras(f)
|
||||||
|
|
||||||
return fmt.Sprintf(`"%s%s[%s]%s"`, multiMark, option, f.Usage, extras)
|
return fmt.Sprintf(`'%s%s[%s]%s'`, multiMark, option, f.Usage, extras)
|
||||||
}
|
}
|
||||||
|
|
||||||
func genFlagEntryForMultiOptionFlag(f *pflag.Flag) string {
|
func genFlagEntryForMultiOptionFlag(f *pflag.Flag) string {
|
||||||
|
@ -148,19 +148,22 @@ func genFlagEntryForMultiOptionFlag(f *pflag.Flag) string {
|
||||||
curlyMultiMark = "\\*"
|
curlyMultiMark = "\\*"
|
||||||
}
|
}
|
||||||
|
|
||||||
options = fmt.Sprintf(`"(%s-%s %s--%s)"{%s-%s,%s--%s}`,
|
options = fmt.Sprintf(`'(%s-%s %s--%s)'{%s-%s,%s--%s}`,
|
||||||
parenMultiMark, f.Shorthand, parenMultiMark, f.Name, curlyMultiMark, f.Shorthand, curlyMultiMark, f.Name)
|
parenMultiMark, f.Shorthand, parenMultiMark, f.Name, curlyMultiMark, f.Shorthand, curlyMultiMark, f.Name)
|
||||||
extras = genZshFlagEntryExtras(f)
|
extras = genZshFlagEntryExtras(f)
|
||||||
|
|
||||||
return fmt.Sprintf(`%s"[%s]%s"`, options, f.Usage, extras)
|
return fmt.Sprintf(`%s'[%s]%s'`, options, f.Usage, extras)
|
||||||
}
|
}
|
||||||
|
|
||||||
func genZshFlagEntryExtras(f *pflag.Flag) string {
|
func genZshFlagEntryExtras(f *pflag.Flag) string {
|
||||||
var extras string
|
var extras string
|
||||||
|
|
||||||
_, pathSpecified := f.Annotations[BashCompFilenameExt]
|
globs, pathSpecified := f.Annotations[BashCompFilenameExt]
|
||||||
if pathSpecified {
|
if pathSpecified {
|
||||||
extras = ":filename:_files"
|
extras = ":filename:_files"
|
||||||
|
for _, g := range globs {
|
||||||
|
extras = extras + fmt.Sprintf(` -g "%s"`, g)
|
||||||
|
}
|
||||||
} else if f.NoOptDefVal == "" {
|
} else if f.NoOptDefVal == "" {
|
||||||
extras = ":" // allow option variable without assisting
|
extras = ":" // allow option variable without assisting
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,7 @@ The generated completion script should be put somewhere in your `$fpath` named
|
||||||
* Completion for all non-hidden subcommands using their `.Short` description.
|
* Completion for all non-hidden subcommands using their `.Short` description.
|
||||||
* Completion for all non-hidden flags using the following rules:
|
* Completion for all non-hidden flags using the following rules:
|
||||||
* Filename completion works by marking the flag with `cmd.MarkFlagFilename...`
|
* Filename completion works by marking the flag with `cmd.MarkFlagFilename...`
|
||||||
family of commands. However, it will ignore specific extensions requested by
|
family of commands.
|
||||||
this command (see about what's not supported yet below).
|
|
||||||
* The requirement for argument to the flag is decided by the `.NoOptDefVal`
|
* The requirement for argument to the flag is decided by the `.NoOptDefVal`
|
||||||
flag value - if it's empty then completion will expect an argument.
|
flag value - if it's empty then completion will expect an argument.
|
||||||
* Flags of one of the various `*Arrary` and `*Slice` types supports multiple
|
* Flags of one of the various `*Arrary` and `*Slice` types supports multiple
|
||||||
|
@ -19,7 +18,6 @@ The generated completion script should be put somewhere in your `$fpath` named
|
||||||
### What's not yet Supported
|
### What's not yet Supported
|
||||||
|
|
||||||
* Positional argument completion are not supported yet.
|
* Positional argument completion are not supported yet.
|
||||||
* Filename completion ignores extension specification.
|
|
||||||
* Custom completion scripts are not supported yet (We should probably create zsh
|
* Custom completion scripts are not supported yet (We should probably create zsh
|
||||||
specific one, doesn't make sense to re-use the bash one as the functions will
|
specific one, doesn't make sense to re-use the bash one as the functions will
|
||||||
be different).
|
be different).
|
||||||
|
|
|
@ -29,7 +29,7 @@ func TestGenZshCompletion(t *testing.T) {
|
||||||
return r
|
return r
|
||||||
}(),
|
}(),
|
||||||
expectedExpressions: []string{
|
expectedExpressions: []string{
|
||||||
`(?s)function _mycommand {\s+_arguments \\\s+"--debug\[description\]".*--help.*}`,
|
`(?s)function _mycommand {\s+_arguments \\\s+'--debug\[description\]'.*--help.*}`,
|
||||||
"#compdef _mycommand mycommand",
|
"#compdef _mycommand mycommand",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -45,7 +45,7 @@ func TestGenZshCompletion(t *testing.T) {
|
||||||
return r
|
return r
|
||||||
}(),
|
}(),
|
||||||
expectedExpressions: []string{
|
expectedExpressions: []string{
|
||||||
`"\(-d --debug\)"{-d,--debug}"\[debug description\]"`,
|
`'\(-d --debug\)'{-d,--debug}'\[debug description\]'`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -72,15 +72,15 @@ func TestGenZshCompletion(t *testing.T) {
|
||||||
}(),
|
}(),
|
||||||
expectedExpressions: []string{
|
expectedExpressions: []string{
|
||||||
`commands=\(\n\s+"help:.*\n\s+"subcmd1:.*\n\s+"subcmd2:.*\n\s+\)`,
|
`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 {`,
|
||||||
`function _rootcmd_subcmd1 {`,
|
`function _rootcmd_subcmd1 {`,
|
||||||
`_arguments \\\n.*"\(-o --option\)"{-o,--option}"\[option description]:" \\\n`,
|
`_arguments \\\n.*'\(-o --option\)'{-o,--option}'\[option description]:' \\\n`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "filename completion",
|
name: "filename completion with and without globs",
|
||||||
root: func() *Command {
|
root: func() *Command {
|
||||||
var file string
|
var file string
|
||||||
r := &Command{
|
r := &Command{
|
||||||
|
@ -90,10 +90,13 @@ func TestGenZshCompletion(t *testing.T) {
|
||||||
}
|
}
|
||||||
r.Flags().StringVarP(&file, "config", "c", file, "config file")
|
r.Flags().StringVarP(&file, "config", "c", file, "config file")
|
||||||
r.MarkFlagFilename("config")
|
r.MarkFlagFilename("config")
|
||||||
|
r.Flags().String("output", "", "output file")
|
||||||
|
r.MarkFlagFilename("output", "*.log", "*.txt")
|
||||||
return r
|
return r
|
||||||
}(),
|
}(),
|
||||||
expectedExpressions: []string{
|
expectedExpressions: []string{
|
||||||
`\n +"\(-c --config\)"{-c,--config}"\[config file]:filename:_files"`,
|
`\n +'\(-c --config\)'{-c,--config}'\[config file]:filename:_files'`,
|
||||||
|
`:_files -g "\*.log" -g "\*.txt"`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -105,8 +108,8 @@ func TestGenZshCompletion(t *testing.T) {
|
||||||
return r
|
return r
|
||||||
}(),
|
}(),
|
||||||
expectedExpressions: []string{
|
expectedExpressions: []string{
|
||||||
`"\*--option\[options]`,
|
`'\*--option\[options]`,
|
||||||
`"\(\*-d \*--debug\)"{\\\*-d,\\\*--debug}`,
|
`'\(\*-d \*--debug\)'{\\\*-d,\\\*--debug}`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -117,7 +120,7 @@ func TestGenZshCompletion(t *testing.T) {
|
||||||
return r
|
return r
|
||||||
}(),
|
}(),
|
||||||
expectedExpressions: []string{
|
expectedExpressions: []string{
|
||||||
`"\*--verbose\[verbosity level]"`,
|
`'\*--verbose\[verbosity level]'`,
|
||||||
},
|
},
|
||||||
skip: "BoolSlice behaves strangely both with NoOptDefVal and type (identifies as bool)",
|
skip: "BoolSlice behaves strangely both with NoOptDefVal and type (identifies as bool)",
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue