Add custom bash flag completion

This commit is contained in:
Dr. Stefan Schimanski 2016-03-20 21:05:18 +01:00
parent 7d556a0974
commit 8092588fb8
3 changed files with 66 additions and 0 deletions

View File

@ -12,6 +12,7 @@ import (
const ( const (
BashCompFilenameExt = "cobra_annotation_bash_completion_filename_extentions" BashCompFilenameExt = "cobra_annotation_bash_completion_filename_extentions"
BashCompCustom = "cobra_annotation_bash_completion_custom"
BashCompOneRequiredFlag = "cobra_annotation_bash_completion_one_required_flag" BashCompOneRequiredFlag = "cobra_annotation_bash_completion_one_required_flag"
BashCompSubdirsInDir = "cobra_annotation_bash_completion_subdirs_in_dir" BashCompSubdirsInDir = "cobra_annotation_bash_completion_subdirs_in_dir"
) )
@ -318,6 +319,20 @@ func writeFlagHandler(name string, annotations map[string][]string, w io.Writer)
if err != nil { if err != nil {
return err return err
} }
case BashCompCustom:
_, err := fmt.Fprintf(w, " flags_with_completion+=(%q)\n", name)
if err != nil {
return err
}
if len(value) > 0 {
handlers := strings.Join(value, "; ")
_, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", handlers)
} else {
_, err = fmt.Fprintf(w, " flags_completion+=(:)\n")
}
if err != nil {
return err
}
case BashCompSubdirsInDir: case BashCompSubdirsInDir:
_, err := fmt.Fprintf(w, " flags_with_completion+=(%q)\n", name) _, err := fmt.Fprintf(w, " flags_with_completion+=(%q)\n", name)
@ -538,6 +553,12 @@ func (cmd *Command) MarkFlagFilename(name string, extensions ...string) error {
return MarkFlagFilename(cmd.Flags(), name, extensions...) return MarkFlagFilename(cmd.Flags(), name, extensions...)
} }
// MarkFlagCustom adds the BashCompCustom annotation to the named flag, if it exists.
// Generated bash autocompletion will call the bash function f for the flag.
func (cmd *Command) MarkFlagCustom(name string, f string) error {
return MarkFlagCustom(cmd.Flags(), name, f)
}
// MarkPersistentFlagFilename adds the BashCompFilenameExt annotation to the named persistent flag, if it exists. // MarkPersistentFlagFilename adds the BashCompFilenameExt annotation to the named persistent flag, if it exists.
// Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided. // Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided.
func (cmd *Command) MarkPersistentFlagFilename(name string, extensions ...string) error { func (cmd *Command) MarkPersistentFlagFilename(name string, extensions ...string) error {
@ -549,3 +570,9 @@ func (cmd *Command) MarkPersistentFlagFilename(name string, extensions ...string
func MarkFlagFilename(flags *pflag.FlagSet, name string, extensions ...string) error { func MarkFlagFilename(flags *pflag.FlagSet, name string, extensions ...string) error {
return flags.SetAnnotation(name, BashCompFilenameExt, extensions) return flags.SetAnnotation(name, BashCompFilenameExt, extensions)
} }
// MarkFlagCustom adds the BashCompCustom annotation to the named flag in the flag set, if it exists.
// Generated bash autocompletion will call the bash function f for the flag.
func MarkFlagCustom(flags *pflag.FlagSet, name string, f string) error {
return flags.SetAnnotation(name, BashCompCustom, []string{f})
}

View File

@ -147,3 +147,35 @@ hello.yml test.json
``` ```
So while there are many other files in the CWD it only shows me subdirs and those with valid extensions. So while there are many other files in the CWD it only shows me subdirs and those with valid extensions.
# Specifiy custom flag completion
Similar to the filename completion and filtering usingn cobra.BashCompFilenameExt, you can specifiy
a custom flag completion function with cobra.BashCompCustom:
```go
annotation := make(map[string][]string)
annotation[cobra.BashCompFilenameExt] = []string{"__kubectl_get_namespaces"}
flag := &pflag.Flag{
Name: "namespace",
Usage: usage,
Annotations: annotation,
}
cmd.Flags().AddFlag(flag)
```
In addition add the `__handle_namespace_flag` implementation in the `BashCompletionFunction`
value, e.g.:
```bash
__kubectl_get_namespaces()
{
local template
template="{{ range .items }}{{ .metadata.name }} {{ end }}"
local kubectl_out
if kubectl_out=$(kubectl get -o template --template="${template}" namespace 2>/dev/null); then
COMPREPLY=( $( compgen -W "${kubectl_out}[*]" -- "$cur" ) )
fi
}
```

View File

@ -62,6 +62,11 @@ func TestBashCompletions(t *testing.T) {
c.Flags().StringVar(&flagvalExt, "filename-ext", "", "Enter a filename (extension limited)") c.Flags().StringVar(&flagvalExt, "filename-ext", "", "Enter a filename (extension limited)")
c.MarkFlagFilename("filename-ext") c.MarkFlagFilename("filename-ext")
// filename extensions
var flagvalCustom string
c.Flags().StringVar(&flagvalCustom, "custom", "", "Enter a filename (extension limited)")
c.MarkFlagCustom("custom", "__complete_custom")
// subdirectories in a given directory // subdirectories in a given directory
var flagvalTheme string var flagvalTheme string
c.Flags().StringVar(&flagvalTheme, "theme", "", "theme to use (located in /themes/THEMENAME/)") c.Flags().StringVar(&flagvalTheme, "theme", "", "theme to use (located in /themes/THEMENAME/)")
@ -88,6 +93,8 @@ func TestBashCompletions(t *testing.T) {
check(t, str, `flags_completion+=("_filedir")`) check(t, str, `flags_completion+=("_filedir")`)
// check for filename extension flags // check for filename extension flags
check(t, str, `flags_completion+=("__handle_filename_extension_flag json|yaml|yml")`) check(t, str, `flags_completion+=("__handle_filename_extension_flag json|yaml|yml")`)
// check for custom flags
check(t, str, `flags_completion+=("__complete_custom")`)
// check for subdirs_in_dir flags // check for subdirs_in_dir flags
check(t, str, `flags_completion+=("__handle_subdirs_in_dir_flag themes")`) check(t, str, `flags_completion+=("__handle_subdirs_in_dir_flag themes")`)