mirror of
https://github.com/spf13/cobra
synced 2025-01-30 23:46:45 +00:00
Fix search for parent's suggest function and improve tests.
This commit is contained in:
parent
84b14d4e50
commit
90335672a9
2 changed files with 131 additions and 34 deletions
23
command.go
23
command.go
|
@ -485,12 +485,31 @@ func (c *Command) Help() error {
|
||||||
|
|
||||||
// SuggestFunc returns suggestions for the provided typedName using either
|
// SuggestFunc returns suggestions for the provided typedName using either
|
||||||
// the function set by SetSuggestFunc for this command, parent's or a default one.
|
// the function set by SetSuggestFunc for this command, parent's or a default one.
|
||||||
|
// When searching for a parent's function, it recursively checks towards the root
|
||||||
|
// and returns the first one found. If none found, uses direct parent's default.
|
||||||
func (c *Command) SuggestFunc(typedName string) string {
|
func (c *Command) SuggestFunc(typedName string) string {
|
||||||
if c.suggestFunc != nil && !c.DisableSuggestions {
|
if c.DisableSuggestions {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if c.suggestFunc != nil {
|
||||||
return c.suggestFunc(typedName)
|
return c.suggestFunc(typedName)
|
||||||
}
|
}
|
||||||
if c.HasParent() {
|
if c.HasParent() {
|
||||||
return c.Parent().SuggestFunc(typedName)
|
var getParentFunc func(*Command) func(string) string
|
||||||
|
getParentFunc = func(parent *Command) func(string) string {
|
||||||
|
if parent.suggestFunc != nil {
|
||||||
|
return parent.suggestFunc
|
||||||
|
}
|
||||||
|
if parent.HasParent() {
|
||||||
|
return getParentFunc(parent.Parent())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
parentFunc := getParentFunc(c.Parent())
|
||||||
|
if parentFunc != nil {
|
||||||
|
return parentFunc(typedName)
|
||||||
|
}
|
||||||
|
return c.Parent().findSuggestions(typedName)
|
||||||
}
|
}
|
||||||
return c.findSuggestions(typedName)
|
return c.findSuggestions(typedName)
|
||||||
}
|
}
|
||||||
|
|
132
command_test.go
132
command_test.go
|
@ -1394,44 +1394,122 @@ func TestSuggestions(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCustomSuggestions(t *testing.T) {
|
func TestCustomSuggestions(t *testing.T) {
|
||||||
templateWithCustomSuggestions := "Error: unknown command \"%s\" for \"root\"\nSome custom suggestion.\n\nRun 'root --help' for usage.\n"
|
|
||||||
templateWithDefaultSuggestions := "Error: unknown command \"%s\" for \"root\"\n\nDid you mean this?\n\t%s\n\nRun 'root --help' for usage.\n"
|
|
||||||
templateWithoutSuggestions := "Error: unknown command \"%s\" for \"root\"\nRun 'root --help' for usage.\n"
|
|
||||||
|
|
||||||
for typo, suggestion := range map[string]string{"time": "times", "timse": "times"} {
|
|
||||||
for _, suggestionsDisabled := range []bool{true, false} {
|
|
||||||
for _, setCustomSuggest := range []bool{true, false} {
|
|
||||||
rootCmd := &Command{Use: "root", Run: emptyRun}
|
rootCmd := &Command{Use: "root", Run: emptyRun}
|
||||||
timesCmd := &Command{
|
timesCmd := &Command{Use: "times", Run: emptyRun}
|
||||||
Use: "times",
|
|
||||||
Run: emptyRun,
|
|
||||||
}
|
|
||||||
rootCmd.AddCommand(timesCmd)
|
rootCmd.AddCommand(timesCmd)
|
||||||
|
|
||||||
rootCmd.DisableSuggestions = suggestionsDisabled
|
var expected, output string
|
||||||
|
|
||||||
if setCustomSuggest {
|
expected = ""
|
||||||
rootCmd.SetSuggestFunc(func(a string) string {
|
output, _ = executeCommand(rootCmd, "times")
|
||||||
|
if output != expected {
|
||||||
|
t.Errorf("\nExpected:\n %q\nGot:\n %q", expected, output)
|
||||||
|
}
|
||||||
|
|
||||||
|
expected = fmt.Sprintf("Error: unknown command \"%s\" for \"root\"\n\nDid you mean this?\n\t%s\n\nRun 'root --help' for usage.\n", "time", "times")
|
||||||
|
output, _ = executeCommand(rootCmd, "time")
|
||||||
|
if output != expected {
|
||||||
|
t.Errorf("\nExpected:\n %q\nGot:\n %q", expected, output)
|
||||||
|
}
|
||||||
|
|
||||||
|
rootCmd.DisableSuggestions = true
|
||||||
|
|
||||||
|
expected = fmt.Sprintf("Error: unknown command \"%s\" for \"root\"\nRun 'root --help' for usage.\n", "time")
|
||||||
|
output, _ = executeCommand(rootCmd, "time")
|
||||||
|
if output != expected {
|
||||||
|
t.Errorf("\nExpected:\n %q\nGot:\n %q", expected, output)
|
||||||
|
}
|
||||||
|
|
||||||
|
rootCmd.DisableSuggestions = false
|
||||||
|
rootCmd.SetSuggestFunc(func(typedName string) string {
|
||||||
return "\nSome custom suggestion.\n"
|
return "\nSome custom suggestion.\n"
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
|
||||||
var expected string
|
|
||||||
if suggestionsDisabled {
|
|
||||||
expected = fmt.Sprintf(templateWithoutSuggestions, typo)
|
|
||||||
} else if setCustomSuggest {
|
|
||||||
expected = fmt.Sprintf(templateWithCustomSuggestions, typo)
|
|
||||||
} else {
|
|
||||||
expected = fmt.Sprintf(templateWithDefaultSuggestions, typo, suggestion)
|
|
||||||
}
|
|
||||||
|
|
||||||
output, _ := executeCommand(rootCmd, typo)
|
|
||||||
|
|
||||||
|
expected = fmt.Sprintf("Error: unknown command \"%s\" for \"root\"\nSome custom suggestion.\n\nRun 'root --help' for usage.\n", "time")
|
||||||
|
output, _ = executeCommand(rootCmd, "time")
|
||||||
if output != expected {
|
if output != expected {
|
||||||
t.Errorf("Unexpected response.\nExpected:\n %q\nGot:\n %q\n", expected, output)
|
t.Errorf("\nExpected:\n %q\nGot:\n %q", expected, output)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCustomSuggestions_OnlyValidArgs(t *testing.T) {
|
||||||
|
validArgs := []string{"a"}
|
||||||
|
rootCmd := &Command{Use: "root", Args: OnlyValidArgs, Run: emptyRun, ValidArgs: validArgs}
|
||||||
|
grandparentCmd := &Command{Use: "grandparent", Args: OnlyValidArgs, Run: emptyRun, ValidArgs: validArgs}
|
||||||
|
parentCmd := &Command{Use: "parent", Args: OnlyValidArgs, Run: emptyRun, ValidArgs: validArgs}
|
||||||
|
timesCmd := &Command{Use: "times", Run: emptyRun}
|
||||||
|
parentCmd.AddCommand(timesCmd)
|
||||||
|
grandparentCmd.AddCommand(parentCmd)
|
||||||
|
rootCmd.AddCommand(grandparentCmd)
|
||||||
|
|
||||||
|
var expected, output string
|
||||||
|
|
||||||
|
// No typos.
|
||||||
|
expected = ""
|
||||||
|
output, _ = executeCommand(rootCmd, "grandparent")
|
||||||
|
if output != expected {
|
||||||
|
t.Errorf("\nExpected:\n %q\nGot:\n %q", expected, output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expected = ""
|
||||||
|
output, _ = executeCommand(rootCmd, "grandparent", "parent")
|
||||||
|
if output != expected {
|
||||||
|
t.Errorf("\nExpected:\n %q\nGot:\n %q", expected, output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expected = ""
|
||||||
|
output, _ = executeCommand(rootCmd, "grandparent", "parent", "times")
|
||||||
|
if output != expected {
|
||||||
|
t.Errorf("\nExpected:\n %q\nGot:\n %q", expected, output)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1st level typo.
|
||||||
|
expected = "Error: invalid argument \"grandparen\" for \"root\"\n\nDid you mean this?\n\tgrandparent\n\nUsage:\n root [flags]\n root [command]\n\nAvailable Commands:\n completion Generate the autocompletion script for the specified shell\n grandparent \n help Help about any command\n\nFlags:\n -h, --help help for root\n\nUse \"root [command] --help\" for more information about a command.\n\n"
|
||||||
|
output, _ = executeCommand(rootCmd, "grandparen")
|
||||||
|
if output != expected {
|
||||||
|
t.Errorf("\nExpected:\n %q\nGot:\n %q", expected, output)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2nd level typo.
|
||||||
|
expected = "Error: invalid argument \"paren\" for \"root grandparent\"\nUsage:\n root grandparent [flags]\n root grandparent [command]\n\nAvailable Commands:\n parent \n\nFlags:\n -h, --help help for grandparent\n\nUse \"root grandparent [command] --help\" for more information about a command.\n\n"
|
||||||
|
output, _ = executeCommand(rootCmd, "grandparent", "paren")
|
||||||
|
if output != expected {
|
||||||
|
t.Errorf("\nExpected:\n %q\nGot:\n %q", expected, output)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3rd level typo.
|
||||||
|
expected = "Error: invalid argument \"time\" for \"root grandparent parent\"\nUsage:\n root grandparent parent [flags]\n root grandparent parent [command]\n\nAvailable Commands:\n times \n\nFlags:\n -h, --help help for parent\n\nUse \"root grandparent parent [command] --help\" for more information about a command.\n\n"
|
||||||
|
output, _ = executeCommand(rootCmd, "grandparent", "parent", "time")
|
||||||
|
if output != expected {
|
||||||
|
t.Errorf("\nExpected:\n %q\nGot:\n %q", expected, output)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom suggestion on root function.
|
||||||
|
rootCmd.SetSuggestFunc(func(typedName string) string {
|
||||||
|
return "\nRoot custom suggestion.\n"
|
||||||
|
})
|
||||||
|
|
||||||
|
expected = "Error: invalid argument \"grandparen\" for \"root\"\nRoot custom suggestion.\n\nUsage:\n root [flags]\n root [command]\n\nAvailable Commands:\n completion Generate the autocompletion script for the specified shell\n grandparent \n help Help about any command\n\nFlags:\n -h, --help help for root\n\nUse \"root [command] --help\" for more information about a command.\n\n"
|
||||||
|
output, _ = executeCommand(rootCmd, "grandparen")
|
||||||
|
if output != expected {
|
||||||
|
t.Errorf("\nExpected:\n %q\nGot:\n %q", expected, output)
|
||||||
|
}
|
||||||
|
|
||||||
|
expected = "Error: invalid argument \"time\" for \"root grandparent parent\"\nRoot custom suggestion.\n\nUsage:\n root grandparent parent [flags]\n root grandparent parent [command]\n\nAvailable Commands:\n times \n\nFlags:\n -h, --help help for parent\n\nUse \"root grandparent parent [command] --help\" for more information about a command.\n\n"
|
||||||
|
output, _ = executeCommand(rootCmd, "grandparent", "parent", "time")
|
||||||
|
if output != expected {
|
||||||
|
t.Errorf("\nExpected:\n %q\nGot:\n %q", expected, output)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom suggestion on parent function (kept root's to make sure this one is prioritised).
|
||||||
|
parentCmd.SetSuggestFunc(func(typedName string) string {
|
||||||
|
return "\nParent custom suggestion.\n"
|
||||||
|
})
|
||||||
|
|
||||||
|
expected = "Error: invalid argument \"time\" for \"root grandparent parent\"\nParent custom suggestion.\n\nUsage:\n root grandparent parent [flags]\n root grandparent parent [command]\n\nAvailable Commands:\n times \n\nFlags:\n -h, --help help for parent\n\nUse \"root grandparent parent [command] --help\" for more information about a command.\n\n"
|
||||||
|
output, _ = executeCommand(rootCmd, "grandparent", "parent", "time")
|
||||||
|
if output != expected {
|
||||||
|
t.Errorf("\nExpected:\n %q\nGot:\n %q", expected, output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue