diff options
Diffstat (limited to 'pkg/gui/filtering.go')
-rw-r--r-- | pkg/gui/filtering.go | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/pkg/gui/filtering.go b/pkg/gui/filtering.go index 1f5c5032a..17fd44e23 100644 --- a/pkg/gui/filtering.go +++ b/pkg/gui/filtering.go @@ -1,5 +1,14 @@ package gui +import ( + "os" + + "github.com/jesseduffield/lazygit/pkg/gui/types" + "github.com/jesseduffield/lazygit/pkg/utils" + "github.com/jesseduffield/minimal/gitignore" + "gopkg.in/ozeidan/fuzzy-patricia.v3/patricia" +) + func (gui *Gui) validateNotInFilterMode() (bool, error) { if gui.State.Modes.Filtering.Active() { err := gui.ask(askOpts{ @@ -40,3 +49,60 @@ func (gui *Gui) setFiltering(path string) error { gui.State.Contexts.BranchCommits.GetPanelState().SetSelectedLineIdx(0) }}) } + +// here we asynchronously fetch the latest set of paths in the repo and store in +// gui.State.FilesTrie. On the main thread we'll be doing a fuzzy search via +// gui.State.FilesTrie. So if we've looked for a file previously, we'll start with +// the old trie and eventually it'll be swapped out for the new one. +func (gui *Gui) getFindSuggestionsForFilterPath() func(string) []*types.Suggestion { + _ = gui.WithWaitingStatus(gui.Tr.LcLoadingFileSuggestions, func() error { + trie := patricia.NewTrie() + // load every non-gitignored file in the repo + ignore, err := gitignore.FromGit() + if err != nil { + return err + } + + err = ignore.Walk(".", + func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + trie.Insert(patricia.Prefix(path), path) + return nil + }) + // cache the trie for future use + gui.State.FilesTrie = trie + + // refresh the selections view + gui.suggestionsAsyncHandler.Do(func() func() { + // assuming here that the confirmation view is what we're typing into. + // This assumption may prove false over time + suggestions := gui.findSuggestions(gui.Views.Confirmation.TextArea.GetContent()) + return func() { gui.setSuggestions(suggestions) } + }) + + return err + }) + + return func(input string) []*types.Suggestion { + matchingNames := []string{} + _ = gui.State.FilesTrie.VisitFuzzy(patricia.Prefix(input), true, func(prefix patricia.Prefix, item patricia.Item, skipped int) error { + matchingNames = append(matchingNames, item.(string)) + return nil + }) + + // doing another fuzzy search for good measure + matchingNames = utils.FuzzySearch(input, matchingNames) + + suggestions := make([]*types.Suggestion, len(matchingNames)) + for i, name := range matchingNames { + suggestions[i] = &types.Suggestion{ + Value: name, + Label: name, + } + } + + return suggestions + } +} |