Merge pull request #257 from sttts/sttts-noun-aliases

Add noun aliases
This commit is contained in:
Eric Paris 2016-04-02 09:29:34 -05:00
commit 60267ae24d
4 changed files with 64 additions and 8 deletions

View file

@ -123,6 +123,10 @@ __handle_reply()
fi
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
declare -F __custom_func >/dev/null && __custom_func
fi
@ -189,7 +193,7 @@ __handle_noun()
if __contains_word "${words[c]}" "${must_have_one_noun[@]}"; then
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=()
fi
@ -460,7 +464,7 @@ func writeRequiredFlag(cmd *Command, w io.Writer) error {
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 {
return err
}
@ -473,6 +477,19 @@ func writeRequiredNoun(cmd *Command, w io.Writer) error {
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 {
for _, c := range cmd.Commands() {
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 {
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
}
if _, err := fmt.Fprintf(w, "}\n\n"); err != nil {

View file

@ -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:
```go
validArgs []string = { "pods", "nodes", "services", "replicationControllers" }
validArgs []string = { "pod", "node", "service", "replicationcontroller" }
cmd := &cobra.Command{
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
# 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
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.

View file

@ -43,9 +43,13 @@ func TestBashCompletions(t *testing.T) {
c.MarkFlagRequired("introot")
// valid nouns
validArgs := []string{"pods", "nodes", "services", "replicationControllers"}
validArgs := []string{"pod", "node", "service", "replicationcontroller"}
c.ValidArgs = validArgs
// noun aliases
argAliases := []string{"pods", "nodes", "services", "replicationcontrollers", "po", "no", "svc", "rc"}
c.ArgAliases = argAliases
// filename
var flagval string
c.Flags().StringVar(&flagval, "filename", "", "Enter a filename")
@ -88,7 +92,11 @@ func TestBashCompletions(t *testing.T) {
// check for custom completion function
check(t, str, `COMPREPLY=( "hello" )`)
// 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(t, str, `flags_completion+=("_filedir")`)
// check for filename extension flags

View file

@ -45,8 +45,11 @@ type Command struct {
Long string
// Examples of how to use the command
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
// 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
BashCompletionFunction string
// Is this command deprecated and should print this string when used?