mirror of
https://github.com/spf13/cobra
synced 2025-01-30 15:36:47 +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
|
||||
// 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 {
|
||||
if c.suggestFunc != nil && !c.DisableSuggestions {
|
||||
if c.DisableSuggestions {
|
||||
return ""
|
||||
}
|
||||
if c.suggestFunc != nil {
|
||||
return c.suggestFunc(typedName)
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
|
132
command_test.go
132
command_test.go
|
@ -1394,44 +1394,122 @@ func TestSuggestions(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}
|
||||
timesCmd := &Command{
|
||||
Use: "times",
|
||||
Run: emptyRun,
|
||||
}
|
||||
timesCmd := &Command{Use: "times", Run: emptyRun}
|
||||
rootCmd.AddCommand(timesCmd)
|
||||
|
||||
rootCmd.DisableSuggestions = suggestionsDisabled
|
||||
var expected, output string
|
||||
|
||||
if setCustomSuggest {
|
||||
rootCmd.SetSuggestFunc(func(a string) string {
|
||||
expected = ""
|
||||
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"
|
||||
})
|
||||
}
|
||||
|
||||
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 {
|
||||
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