1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
|
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),
)
}
|