1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
|
package cmd
import (
"flag"
"fmt"
"strings"
"unicode/utf8"
"github.com/agnivade/levenshtein"
)
const flagProvidedButNotDefinedErr = "flag provided but not defined: -"
func formatFlag(name string) string {
if len(name) == 1 {
return "-" + name
}
return "--" + name
}
func (cli *CLI) getAlternativeFlag(unknownFlag string) string {
var closestDistance int = 10000
var closestFlag string
cli.flags.VisitAll(func(f *flag.Flag) {
distance := levenshtein.ComputeDistance(f.Name, unknownFlag)
if distance < closestDistance {
closestDistance = distance
closestFlag = f.Name
}
})
if closestDistance >= utf8.RuneCountInString(unknownFlag) {
return ""
}
if closestDistance > 4 {
return ""
}
return closestFlag
}
func (cli *CLI) categorizeFlagError(err error) error {
if err == nil {
return nil
}
message := err.Error()
if strings.HasPrefix(message, flagProvidedButNotDefinedErr) {
flagName := strings.TrimPrefix(message, flagProvidedButNotDefinedErr)
err := fmt.Errorf("unknown flag: %s", formatFlag(flagName))
alternative := cli.getAlternativeFlag(flagName)
if alternative == "" {
return NewCLIError(err)
}
return NewCLIError(
err,
Paragraph(fmt.Sprintf("Did you mean %s instead?", formatFlag(alternative))),
)
}
return err
}
|