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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
package context
import (
"strings"
"github.com/jesseduffield/lazygit/pkg/utils"
"github.com/sahilm/fuzzy"
"github.com/samber/lo"
"github.com/sasha-s/go-deadlock"
)
type FilteredList[T any] struct {
filteredIndices []int // if nil, we are not filtering
getList func() []T
getFilterFields func(T) []string
filter string
mutex *deadlock.Mutex
}
func NewFilteredList[T any](getList func() []T, getFilterFields func(T) []string) *FilteredList[T] {
return &FilteredList[T]{
getList: getList,
getFilterFields: getFilterFields,
mutex: &deadlock.Mutex{},
}
}
func (self *FilteredList[T]) GetFilter() string {
return self.filter
}
func (self *FilteredList[T]) SetFilter(filter string, useFuzzySearch bool) {
self.filter = filter
self.applyFilter(useFuzzySearch)
}
func (self *FilteredList[T]) ClearFilter() {
self.SetFilter("", false)
}
func (self *FilteredList[T]) ReApplyFilter(useFuzzySearch bool) {
self.applyFilter(useFuzzySearch)
}
func (self *FilteredList[T]) IsFiltering() bool {
return self.filter != ""
}
func (self *FilteredList[T]) GetFilteredList() []T {
if self.filteredIndices == nil {
return self.getList()
}
return utils.ValuesAtIndices(self.getList(), self.filteredIndices)
}
// TODO: update to just 'Len'
func (self *FilteredList[T]) UnfilteredLen() int {
return len(self.getList())
}
type fuzzySource[T any] struct {
list []T
getFilterFields func(T) []string
}
var _ fuzzy.Source = &fuzzySource[string]{}
func (self *fuzzySource[T]) String(i int) string {
return strings.Join(self.getFilterFields(self.list[i]), " ")
}
func (self *fuzzySource[T]) Len() int {
return len(self.list)
}
func (self *FilteredList[T]) applyFilter(useFuzzySearch bool) {
self.mutex.Lock()
defer self.mutex.Unlock()
if self.filter == "" {
self.filteredIndices = nil
} else {
source := &fuzzySource[T]{
list: self.getList(),
getFilterFields: self.getFilterFields,
}
matches := utils.FindFrom(self.filter, source, useFuzzySearch)
self.filteredIndices = lo.Map(matches, func(match fuzzy.Match, _ int) int {
return match.Index
})
}
}
func (self *FilteredList[T]) UnfilteredIndex(index int) int {
self.mutex.Lock()
defer self.mutex.Unlock()
if self.filteredIndices == nil {
return index
}
// we use -1 when there are no items
if index == -1 {
return -1
}
return self.filteredIndices[index]
}
|