72 lines
1.2 KiB
Go
72 lines
1.2 KiB
Go
package suggest
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/agext/levenshtein"
|
|
)
|
|
|
|
// WrapError wraps error with a suggestion for fixing it
|
|
func WrapError(err error, val string, options []string, caseSensitive bool) error {
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
orig := val
|
|
if !caseSensitive {
|
|
val = strings.ToLower(val)
|
|
}
|
|
var match string
|
|
mindist := 3 // same as hcl
|
|
for _, opt := range options {
|
|
if !caseSensitive {
|
|
opt = strings.ToLower(opt)
|
|
}
|
|
if val == opt {
|
|
// exact match means error was unrelated to the value
|
|
return err
|
|
}
|
|
dist := levenshtein.Distance(val, opt, nil)
|
|
if dist < mindist {
|
|
if !caseSensitive {
|
|
match = matchCase(opt, orig)
|
|
} else {
|
|
match = opt
|
|
}
|
|
mindist = dist
|
|
}
|
|
}
|
|
|
|
if match == "" {
|
|
return err
|
|
}
|
|
|
|
return &suggestError{
|
|
err: err,
|
|
match: match,
|
|
}
|
|
}
|
|
|
|
type suggestError struct {
|
|
err error
|
|
match string
|
|
}
|
|
|
|
func (e *suggestError) Error() string {
|
|
return e.err.Error() + " (did you mean " + e.match + "?)"
|
|
}
|
|
|
|
// Unwrap returns the underlying error.
|
|
func (e *suggestError) Unwrap() error {
|
|
return e.err
|
|
}
|
|
|
|
func matchCase(val, orig string) string {
|
|
if orig == strings.ToLower(orig) {
|
|
return strings.ToLower(val)
|
|
}
|
|
if orig == strings.ToUpper(orig) {
|
|
return strings.ToUpper(val)
|
|
}
|
|
return val
|
|
}
|