package utils import ( "strings" "github.com/sahilm/fuzzy" "github.com/samber/lo" ) func FilterStrings(needle string, haystack []string, useFuzzySearch bool) []string { if needle == "" { return []string{} } matches := Find(needle, haystack, useFuzzySearch) return lo.Map(matches, func(match fuzzy.Match, _ int) string { return match.Str }) } // Duplicated from the fuzzy package because it's private there type stringSource []string func (ss stringSource) String(i int) string { return ss[i] } func (ss stringSource) Len() int { return len(ss) } // Drop-in replacement for fuzzy.Find (except that it doesn't fill out // MatchedIndexes or Score, but we are not using these) func FindSubstrings(pattern string, data []string) fuzzy.Matches { return FindSubstringsFrom(pattern, stringSource(data)) } // Drop-in replacement for fuzzy.FindFrom (except that it doesn't fill out // MatchedIndexes or Score, but we are not using these) func FindSubstringsFrom(pattern string, data fuzzy.Source) fuzzy.Matches { substrings := strings.Fields(pattern) result := fuzzy.Matches{} outer: for i := 0; i < data.Len(); i++ { s := data.String(i) for _, sub := range substrings { if !CaseAwareContains(s, sub) { continue outer } } result = append(result, fuzzy.Match{Str: s, Index: i}) } return result } func Find(pattern string, data []string, useFuzzySearch bool) fuzzy.Matches { if useFuzzySearch { return fuzzy.Find(pattern, data) } return FindSubstrings(pattern, data) } func FindFrom(pattern string, data fuzzy.Source, useFuzzySearch bool) fuzzy.Matches { if useFuzzySearch { return fuzzy.FindFrom(pattern, data) } return FindSubstringsFrom(pattern, data) } func CaseAwareContains(haystack, needle string) bool { // if needle contains an uppercase letter, we'll do a case sensitive search if ContainsUppercase(needle) { return strings.Contains(haystack, needle) } return CaseInsensitiveContains(haystack, needle) } func ContainsUppercase(s string) bool { for _, r := range s { if r >= 'A' && r <= 'Z' { return true } } return false } func CaseInsensitiveContains(haystack, needle string) bool { return strings.Contains( strings.ToLower(haystack), strings.ToLower(needle), ) }