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 }