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
|
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{
title: gui.Tr.MustExitFilterModeTitle,
prompt: gui.Tr.MustExitFilterModePrompt,
handleConfirm: gui.exitFilterMode,
})
return false, err
}
return true, nil
}
func (gui *Gui) exitFilterMode() error {
return gui.clearFiltering()
}
func (gui *Gui) clearFiltering() error {
gui.State.Modes.Filtering.Reset()
if gui.State.ScreenMode == SCREEN_HALF {
gui.State.ScreenMode = SCREEN_NORMAL
}
return gui.refreshSidePanels(refreshOptions{scope: []RefreshableView{COMMITS}})
}
func (gui *Gui) setFiltering(path string) error {
gui.State.Modes.Filtering.SetPath(path)
if gui.State.ScreenMode == SCREEN_NORMAL {
gui.State.ScreenMode = SCREEN_HALF
}
if err := gui.pushContext(gui.State.Contexts.BranchCommits); err != nil {
return err
}
return gui.refreshSidePanels(refreshOptions{scope: []RefreshableView{COMMITS}, then: func() {
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
}
}
|