52 lines
1.1 KiB
Go
52 lines
1.1 KiB
Go
package config
|
|
|
|
import (
|
|
"reflect"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// Suggest only a unique, nearby declared field. Input values are never used.
|
|
func unknownFieldReason(name string, fields map[string]reflect.StructField) string {
|
|
if len(name) < 3 || len(name) > 128 {
|
|
return "unknown field"
|
|
}
|
|
best, match, tied := 3, "", false
|
|
for candidate := range fields {
|
|
if len(candidate) > 128 {
|
|
continue
|
|
}
|
|
d := fieldDistance(strings.ToLower(name), strings.ToLower(candidate))
|
|
if d < best {
|
|
best, match, tied = d, candidate, false
|
|
} else if d == best {
|
|
tied = true
|
|
}
|
|
}
|
|
if match != "" && !tied && best <= 2 {
|
|
return "unknown field; did you mean " + strconv.Quote(match) + "?"
|
|
}
|
|
return "unknown field"
|
|
}
|
|
func fieldDistance(a, b string) int {
|
|
prev := make([]int, len(b)+1)
|
|
for i := range prev {
|
|
prev[i] = i
|
|
}
|
|
for i := 0; i < len(a); i++ {
|
|
left, diagonal := i+1, prev[0]
|
|
prev[0] = left
|
|
for j := 0; j < len(b); j++ {
|
|
cost := 0
|
|
if a[i] != b[j] {
|
|
cost = 1
|
|
}
|
|
old := prev[j+1]
|
|
left = min(left+1, old+1, diagonal+cost)
|
|
prev[j+1] = left
|
|
diagonal = old
|
|
}
|
|
}
|
|
return prev[len(b)]
|
|
}
|