1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2024-12-04 10:34:55 +02:00

Use fuzzy search when filtering a view

This adds fuzzy filtering instead of exact match filtering, which is more forgiving of typos
and allows more efficiency.
This commit is contained in:
Jesse Duffield 2023-07-22 13:04:39 +10:00
parent 084c0a19bc
commit b46623ebef
4 changed files with 64 additions and 12 deletions

View File

@ -1,7 +1,11 @@
package context
import (
"strings"
"github.com/jesseduffield/lazygit/pkg/utils"
"github.com/sahilm/fuzzy"
"github.com/samber/lo"
"github.com/sasha-s/go-deadlock"
)
@ -53,6 +57,21 @@ 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() {
self.mutex.Lock()
defer self.mutex.Unlock()
@ -60,20 +79,16 @@ func (self *FilteredList[T]) applyFilter() {
if self.filter == "" {
self.filteredIndices = nil
} else {
self.filteredIndices = []int{}
for i, item := range self.getList() {
for _, field := range self.getFilterFields(item) {
if self.match(field, self.filter) {
self.filteredIndices = append(self.filteredIndices, i)
break
}
}
}
}
source := &fuzzySource[T]{
list: self.getList(),
getFilterFields: self.getFilterFields,
}
func (self *FilteredList[T]) match(haystack string, needle string) bool {
return utils.CaseAwareContains(haystack, needle)
matches := fuzzy.FindFrom(self.filter, source)
self.filteredIndices = lo.Map(matches, func(match fuzzy.Match, _ int) int {
return match.Index
})
}
}
func (self *FilteredList[T]) UnfilteredIndex(index int) int {

View File

@ -539,6 +539,7 @@ func (self *ViewDriver) FilterOrSearch(text string) *ViewDriver {
self.Press(self.t.keys.Universal.StartSearch).
Tap(func() {
self.t.ExpectSearch().
Clear().
Type(text).
Confirm()

View File

@ -0,0 +1,35 @@
package filter_and_search
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var FilterFuzzy = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Verify that fuzzy filtering works (not just exact matches)",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shell.NewBranch("this-is-my-branch")
shell.EmptyCommit("first commit")
shell.NewBranch("other-branch")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Branches().
Focus().
Lines(
Contains(`other-branch`).IsSelected(),
Contains(`this-is-my-branch`),
).
FilterOrSearch("timb"). // using first letters of words
Lines(
Contains(`this-is-my-branch`).IsSelected(),
).
FilterOrSearch("brnch"). // allows missing letter
Lines(
Contains(`other-branch`).IsSelected(),
Contains(`this-is-my-branch`),
)
},
})

View File

@ -98,6 +98,7 @@ var tests = []*components.IntegrationTest{
file.RememberCommitMessageAfterFail,
filter_and_search.FilterCommitFiles,
filter_and_search.FilterFiles,
filter_and_search.FilterFuzzy,
filter_and_search.FilterMenu,
filter_and_search.FilterRemoteBranches,
filter_and_search.NestedFilter,