| //go:build !urfave_cli_no_suggest |
| // +build !urfave_cli_no_suggest |
| |
| package cli |
| |
| import ( |
| "fmt" |
| |
| "github.com/xrash/smetrics" |
| ) |
| |
| func init() { |
| SuggestFlag = suggestFlag |
| SuggestCommand = suggestCommand |
| } |
| |
| func jaroWinkler(a, b string) float64 { |
| // magic values are from https://github.com/xrash/smetrics/blob/039620a656736e6ad994090895784a7af15e0b80/jaro-winkler.go#L8 |
| const ( |
| boostThreshold = 0.7 |
| prefixSize = 4 |
| ) |
| return smetrics.JaroWinkler(a, b, boostThreshold, prefixSize) |
| } |
| |
| func suggestFlag(flags []Flag, provided string, hideHelp bool) string { |
| distance := 0.0 |
| suggestion := "" |
| |
| for _, flag := range flags { |
| flagNames := flag.Names() |
| if !hideHelp && HelpFlag != nil { |
| flagNames = append(flagNames, HelpFlag.Names()...) |
| } |
| for _, name := range flagNames { |
| newDistance := jaroWinkler(name, provided) |
| if newDistance > distance { |
| distance = newDistance |
| suggestion = name |
| } |
| } |
| } |
| |
| if len(suggestion) == 1 { |
| suggestion = "-" + suggestion |
| } else if len(suggestion) > 1 { |
| suggestion = "--" + suggestion |
| } |
| |
| return suggestion |
| } |
| |
| // suggestCommand takes a list of commands and a provided string to suggest a |
| // command name |
| func suggestCommand(commands []*Command, provided string) (suggestion string) { |
| distance := 0.0 |
| for _, command := range commands { |
| for _, name := range append(command.Names(), helpName, helpAlias) { |
| newDistance := jaroWinkler(name, provided) |
| if newDistance > distance { |
| distance = newDistance |
| suggestion = name |
| } |
| } |
| } |
| |
| return fmt.Sprintf(SuggestDidYouMeanTemplate, suggestion) |
| } |