mirror of
https://github.com/spf13/cobra
synced 2024-11-24 14:47:12 +00:00
Remove plural handling and add aliases for nouns in completion
This commit is contained in:
parent
c678ff029e
commit
1a0a490d76
4 changed files with 64 additions and 8 deletions
|
@ -123,6 +123,10 @@ __handle_reply()
|
||||||
fi
|
fi
|
||||||
COMPREPLY=( $(compgen -W "${completions[*]}" -- "$cur") )
|
COMPREPLY=( $(compgen -W "${completions[*]}" -- "$cur") )
|
||||||
|
|
||||||
|
if [[ ${#COMPREPLY[@]} -eq 0 && ${#noun_aliases[@]} -gt 0 && ${#must_have_one_noun[@]} -ne 0 ]]; then
|
||||||
|
COMPREPLY=( $(compgen -W "${noun_aliases[*]}" -- "$cur") )
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ ${#COMPREPLY[@]} -eq 0 ]]; then
|
if [[ ${#COMPREPLY[@]} -eq 0 ]]; then
|
||||||
declare -F __custom_func >/dev/null && __custom_func
|
declare -F __custom_func >/dev/null && __custom_func
|
||||||
fi
|
fi
|
||||||
|
@ -189,7 +193,7 @@ __handle_noun()
|
||||||
|
|
||||||
if __contains_word "${words[c]}" "${must_have_one_noun[@]}"; then
|
if __contains_word "${words[c]}" "${must_have_one_noun[@]}"; then
|
||||||
must_have_one_noun=()
|
must_have_one_noun=()
|
||||||
elif __contains_word "${words[c]%s}" "${must_have_one_noun[@]}"; then
|
elif __contains_word "${words[c]}" "${noun_aliases[@]}"; then
|
||||||
must_have_one_noun=()
|
must_have_one_noun=()
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -460,7 +464,7 @@ func writeRequiredFlag(cmd *Command, w io.Writer) error {
|
||||||
return visitErr
|
return visitErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeRequiredNoun(cmd *Command, w io.Writer) error {
|
func writeRequiredNouns(cmd *Command, w io.Writer) error {
|
||||||
if _, err := fmt.Fprintf(w, " must_have_one_noun=()\n"); err != nil {
|
if _, err := fmt.Fprintf(w, " must_have_one_noun=()\n"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -473,6 +477,19 @@ func writeRequiredNoun(cmd *Command, w io.Writer) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func writeArgAliases(cmd *Command, w io.Writer) error {
|
||||||
|
if _, err := fmt.Fprintf(w, " noun_aliases=()\n"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
sort.Sort(sort.StringSlice(cmd.ArgAliases))
|
||||||
|
for _, value := range cmd.ArgAliases {
|
||||||
|
if _, err := fmt.Fprintf(w, " noun_aliases+=(%q)\n", value); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func gen(cmd *Command, w io.Writer) error {
|
func gen(cmd *Command, w io.Writer) error {
|
||||||
for _, c := range cmd.Commands() {
|
for _, c := range cmd.Commands() {
|
||||||
if !c.IsAvailableCommand() || c == cmd.helpCommand {
|
if !c.IsAvailableCommand() || c == cmd.helpCommand {
|
||||||
|
@ -500,7 +517,10 @@ func gen(cmd *Command, w io.Writer) error {
|
||||||
if err := writeRequiredFlag(cmd, w); err != nil {
|
if err := writeRequiredFlag(cmd, w); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := writeRequiredNoun(cmd, w); err != nil {
|
if err := writeRequiredNouns(cmd, w); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := writeArgAliases(cmd, w); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err := fmt.Fprintf(w, "}\n\n"); err != nil {
|
if _, err := fmt.Fprintf(w, "}\n\n"); err != nil {
|
||||||
|
|
|
@ -80,7 +80,7 @@ The `BashCompletionFunction` option is really only valid/useful on the root comm
|
||||||
In the above example "pod" was assumed to already be typed. But if you want `kubectl get [tab][tab]` to show a list of valid "nouns" you have to set them. Simplified code from `kubectl get` looks like:
|
In the above example "pod" was assumed to already be typed. But if you want `kubectl get [tab][tab]` to show a list of valid "nouns" you have to set them. Simplified code from `kubectl get` looks like:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
validArgs []string = { "pods", "nodes", "services", "replicationControllers" }
|
validArgs []string = { "pod", "node", "service", "replicationcontroller" }
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "get [(-o|--output=)json|yaml|template|...] (RESOURCE [NAME] | RESOURCE/NAME ...)",
|
Use: "get [(-o|--output=)json|yaml|template|...] (RESOURCE [NAME] | RESOURCE/NAME ...)",
|
||||||
|
@ -99,9 +99,34 @@ Notice we put the "ValidArgs" on the "get" subcommand. Doing so will give result
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# kubectl get [tab][tab]
|
# kubectl get [tab][tab]
|
||||||
nodes pods replicationControllers services
|
node pod replicationcontroller service
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Plural form and shortcuts for nouns
|
||||||
|
|
||||||
|
If your nouns have a number of aliases, you can define them alongside `ValidArgs` using `ArgAliases`:
|
||||||
|
|
||||||
|
```go`
|
||||||
|
argAliases []string = { "pods", "nodes", "services", "svc", "replicationcontrollers", "rc" }
|
||||||
|
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
...
|
||||||
|
ValidArgs: validArgs,
|
||||||
|
ArgAliases: argAliases
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The aliases are not shown to the user on tab completion, but they are accepted as valid nouns by
|
||||||
|
the completion aglorithm if entered manually, e.g. in:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# kubectl get rc [tab][tab]
|
||||||
|
backend frontend database
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that without declaring `rc` as an alias, the completion algorithm would show the list of nouns
|
||||||
|
in this example again instead of the replication controllers.
|
||||||
|
|
||||||
## Mark flags as required
|
## Mark flags as required
|
||||||
|
|
||||||
Most of the time completions will only show subcommands. But if a flag is required to make a subcommand work, you probably want it to show up when the user types [tab][tab]. Marking a flag as 'Required' is incredibly easy.
|
Most of the time completions will only show subcommands. But if a flag is required to make a subcommand work, you probably want it to show up when the user types [tab][tab]. Marking a flag as 'Required' is incredibly easy.
|
||||||
|
|
|
@ -43,9 +43,13 @@ func TestBashCompletions(t *testing.T) {
|
||||||
c.MarkFlagRequired("introot")
|
c.MarkFlagRequired("introot")
|
||||||
|
|
||||||
// valid nouns
|
// valid nouns
|
||||||
validArgs := []string{"pods", "nodes", "services", "replicationControllers"}
|
validArgs := []string{"pod", "node", "service", "replicationcontroller"}
|
||||||
c.ValidArgs = validArgs
|
c.ValidArgs = validArgs
|
||||||
|
|
||||||
|
// noun aliases
|
||||||
|
argAliases := []string{"pods", "nodes", "services", "replicationcontrollers", "po", "no", "svc", "rc"}
|
||||||
|
c.ArgAliases = argAliases
|
||||||
|
|
||||||
// filename
|
// filename
|
||||||
var flagval string
|
var flagval string
|
||||||
c.Flags().StringVar(&flagval, "filename", "", "Enter a filename")
|
c.Flags().StringVar(&flagval, "filename", "", "Enter a filename")
|
||||||
|
@ -88,7 +92,11 @@ func TestBashCompletions(t *testing.T) {
|
||||||
// check for custom completion function
|
// check for custom completion function
|
||||||
check(t, str, `COMPREPLY=( "hello" )`)
|
check(t, str, `COMPREPLY=( "hello" )`)
|
||||||
// check for required nouns
|
// check for required nouns
|
||||||
check(t, str, `must_have_one_noun+=("pods")`)
|
check(t, str, `must_have_one_noun+=("pod")`)
|
||||||
|
// check for noun aliases
|
||||||
|
check(t, str, `noun_aliases+=("pods")`)
|
||||||
|
check(t, str, `noun_aliases+=("rc")`)
|
||||||
|
checkOmit(t, str, `must_have_one_noun+=("pods")`)
|
||||||
// check for filename extension flags
|
// check for filename extension flags
|
||||||
check(t, str, `flags_completion+=("_filedir")`)
|
check(t, str, `flags_completion+=("_filedir")`)
|
||||||
// check for filename extension flags
|
// check for filename extension flags
|
||||||
|
|
|
@ -45,8 +45,11 @@ type Command struct {
|
||||||
Long string
|
Long string
|
||||||
// Examples of how to use the command
|
// Examples of how to use the command
|
||||||
Example string
|
Example string
|
||||||
// List of all valid non-flag arguments, used for bash completions *TODO* actually validate these
|
// List of all valid non-flag arguments that are accepted in bash completions
|
||||||
ValidArgs []string
|
ValidArgs []string
|
||||||
|
// List of aliases for ValidArgs. These are not suggested to the user in the bash
|
||||||
|
// completion, but accepted if entered manually.
|
||||||
|
ArgAliases []string
|
||||||
// Custom functions used by the bash autocompletion generator
|
// Custom functions used by the bash autocompletion generator
|
||||||
BashCompletionFunction string
|
BashCompletionFunction string
|
||||||
// Is this command deprecated and should print this string when used?
|
// Is this command deprecated and should print this string when used?
|
||||||
|
|
Loading…
Reference in a new issue