Allows command suggestions along with "unknown command" errors

This commit is contained in:
Fabiano Franz
2015-09-11 17:04:58 -03:00
parent 4b86c66ef2
commit b4087da7eb
4 changed files with 116 additions and 1 deletions

View File

@ -106,6 +106,11 @@ type Command struct {
helpCommand *Command // The help command
// The global normalization function that we can use on every pFlag set and children commands
globNormFunc func(f *flag.FlagSet, name string) flag.NormalizedName
// Disable the suggestions based on Levenshtein distance that go along with 'unknown command' messages
DisableSuggestions bool
// If displaying suggestions, allows to set the minimum levenshtein distance to display, must be > 0
SuggestionsMinimumDistance int
}
// os.Args[1:] by default, if desired, can be overridden
@ -419,9 +424,31 @@ func (c *Command) Find(args []string) (*Command, []string, error) {
if !commandFound.HasSubCommands() {
return commandFound, a, nil
}
// root command with subcommands, do subcommand checking
if commandFound == c && len(argsWOflags) > 0 {
return commandFound, a, fmt.Errorf("unknown command %q for %q", argsWOflags[0], commandFound.CommandPath())
suggestions := ""
if !c.DisableSuggestions {
if c.SuggestionsMinimumDistance <= 0 {
c.SuggestionsMinimumDistance = 2
}
similar := []string{}
for _, cmd := range c.commands {
if cmd.IsAvailableCommand() {
levenshtein := ld(argsWOflags[0], cmd.Name(), true)
if levenshtein <= c.SuggestionsMinimumDistance {
similar = append(similar, cmd.Name())
}
}
}
if len(similar) > 0 {
suggestions += "\n\nDid you mean this?\n"
for _, s := range similar {
suggestions += fmt.Sprintf("\t%v\n", s)
}
}
}
return commandFound, a, fmt.Errorf("unknown command %q for %q%s", argsWOflags[0], commandFound.CommandPath(), suggestions)
}
return commandFound, a, nil