github.phpd.cn/thought-machine/please@v12.2.0+incompatible/src/utils/suggest.go (about) 1 package utils 2 3 import ( 4 "sort" 5 6 "github.com/texttheater/golang-levenshtein/levenshtein" 7 ) 8 9 // Suggest implements levenshtein-based suggestions on a sequence of items. 10 func Suggest(needle string, haystack []string, maxSuggestionDistance int) []string { 11 r := []rune(needle) 12 options := make(suggestions, 0, len(haystack)) 13 for _, straw := range haystack { 14 distance := levenshtein.DistanceForStrings(r, []rune(straw), levenshtein.DefaultOptions) 15 if len(straw) > 0 && distance <= maxSuggestionDistance { 16 options = append(options, suggestion{s: straw, dist: distance}) 17 } 18 } 19 sort.Sort(options) 20 ret := make([]string, len(options)) 21 for i, o := range options { 22 ret[i] = o.s 23 } 24 return ret 25 } 26 27 // PrettyPrintSuggestion implements levenshtein-based suggestions on a sequence of items and 28 // produces a single message from them. 29 func PrettyPrintSuggestion(needle string, haystack []string, maxSuggestionDistance int) string { 30 options := Suggest(needle, haystack, maxSuggestionDistance) 31 if len(options) == 0 { 32 return "" 33 } 34 // Obviously there's now more code to pretty-print the suggestions than to do the calculation... 35 msg := "\nMaybe you meant " 36 for i, o := range options { 37 if i > 0 { 38 if i < len(options)-1 { 39 msg += " , " // Leave a space before the comma so you can select them without getting the question mark 40 } else { 41 msg += " or " 42 } 43 } 44 msg += o 45 } 46 return msg + " ?" // Leave a space so you can select them without getting the question mark 47 } 48 49 type suggestion struct { 50 s string 51 dist int 52 } 53 type suggestions []suggestion 54 55 func (s suggestions) Len() int { return len(s) } 56 func (s suggestions) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 57 func (s suggestions) Less(i, j int) bool { return s[i].dist < s[j].dist }