Skip to content

Commit 5a5cd84

Browse files
authored
Search the model instead of the view in the commits panel (#3642)
- **PR Description** This makes it possible to search the model data instead of the view when pressing `/`, and uses this for the commits view. This is mainly a preparation for #2533 which requires it, but it is also useful on its own, because it makes it possible to search for full commit hashes. It will highlight the abbreviated hash in that case. - **Please check if the PR fulfills these requirements** * [x] Cheatsheets are up-to-date (run `go generate ./...`) * [x] Code has been formatted (see [here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#code-formatting)) * [ ] Tests have been added/updated (see [here](https://github.com/jesseduffield/lazygit/blob/master/pkg/integration/README.md) for the integration test guide) * [ ] Text is internationalised (see [here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#internationalisation)) * [ ] Docs have been updated if necessary * [x] You've read through your own file changes for silly mistakes etc
2 parents 3af545d + 6a6316c commit 5a5cd84

File tree

78 files changed

+9228
-4342
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+9228
-4342
lines changed

go.mod

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ require (
1616
github.com/integrii/flaggy v1.4.0
1717
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68
1818
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d
19-
github.com/jesseduffield/gocui v0.3.1-0.20240418080333-8cd33929c513
19+
github.com/jesseduffield/gocui v0.3.1-0.20240623092910-a42926c14fc9
2020
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10
2121
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5
2222
github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e
@@ -75,8 +75,8 @@ require (
7575
github.com/xanzy/ssh-agent v0.2.1 // indirect
7676
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect
7777
golang.org/x/net v0.7.0 // indirect
78-
golang.org/x/sys v0.19.0 // indirect
79-
golang.org/x/term v0.19.0 // indirect
80-
golang.org/x/text v0.14.0 // indirect
78+
golang.org/x/sys v0.21.0 // indirect
79+
golang.org/x/term v0.21.0 // indirect
80+
golang.org/x/text v0.16.0 // indirect
8181
gopkg.in/warnings.v0 v0.1.2 // indirect
8282
)

go.sum

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,8 @@ github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68 h1:EQP2Tv8T
188188
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68/go.mod h1:+LLj9/WUPAP8LqCchs7P+7X0R98HiFujVFANdNaxhGk=
189189
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d h1:bO+OmbreIv91rCe8NmscRwhFSqkDJtzWCPV4Y+SQuXE=
190190
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d/go.mod h1:nGNEErzf+NRznT+N2SWqmHnDnF9aLgANB1CUNEan09o=
191-
github.com/jesseduffield/gocui v0.3.1-0.20240418080333-8cd33929c513 h1:Y1bw5iItrsDCumATc/rklIJ/6K+68ieiWZJedhrNuXo=
192-
github.com/jesseduffield/gocui v0.3.1-0.20240418080333-8cd33929c513/go.mod h1:XtEbqCbn45keRXEu+OMZkjN5gw6AEob59afsgHjokZ8=
191+
github.com/jesseduffield/gocui v0.3.1-0.20240623092910-a42926c14fc9 h1:JJ0DrXgAUpGBGV5w8nzrQLMWTgcTvf745IKAk08qjcM=
192+
github.com/jesseduffield/gocui v0.3.1-0.20240623092910-a42926c14fc9/go.mod h1:XtEbqCbn45keRXEu+OMZkjN5gw6AEob59afsgHjokZ8=
193193
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10 h1:jmpr7KpX2+2GRiE91zTgfq49QvgiqB0nbmlwZ8UnOx0=
194194
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10/go.mod h1:aA97kHeNA+sj2Hbki0pvLslmE4CbDyhBeSSTUUnOuVo=
195195
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 h1:CDuQmfOjAtb1Gms6a1p5L2P8RhbLUq5t8aL7PiQd2uY=
@@ -474,14 +474,14 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
474474
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
475475
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
476476
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
477-
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
478-
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
477+
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
478+
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
479479
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
480480
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
481481
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
482482
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
483-
golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
484-
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
483+
golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA=
484+
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
485485
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
486486
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
487487
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -491,8 +491,9 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
491491
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
492492
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
493493
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
494-
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
495494
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
495+
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
496+
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
496497
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
497498
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
498499
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=

pkg/gui/context/commit_files_context.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package context
22

33
import (
4+
"github.com/jesseduffield/gocui"
45
"github.com/jesseduffield/lazygit/pkg/commands/models"
56
"github.com/jesseduffield/lazygit/pkg/gui/filetree"
67
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
@@ -18,8 +19,9 @@ type CommitFilesContext struct {
1819
}
1920

2021
var (
21-
_ types.IListContext = (*CommitFilesContext)(nil)
22-
_ types.DiffableContext = (*CommitFilesContext)(nil)
22+
_ types.IListContext = (*CommitFilesContext)(nil)
23+
_ types.DiffableContext = (*CommitFilesContext)(nil)
24+
_ types.ISearchableContext = (*CommitFilesContext)(nil)
2325
)
2426

2527
func NewCommitFilesContext(c *ContextCommon) *CommitFilesContext {
@@ -64,14 +66,15 @@ func NewCommitFilesContext(c *ContextCommon) *CommitFilesContext {
6466
},
6567
}
6668

67-
ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(func(selectedLineIdx int) error {
68-
ctx.GetList().SetSelection(selectedLineIdx)
69-
return ctx.HandleFocus(types.OnFocusOpts{})
70-
}))
69+
ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(ctx.OnSearchSelect))
7170

7271
return ctx
7372
}
7473

7574
func (self *CommitFilesContext) GetDiffTerminals() []string {
7675
return []string{self.GetRef().RefName()}
7776
}
77+
78+
func (self *CommitFilesContext) ModelSearchResults(searchStr string, caseSensitive bool) []gocui.SearchPosition {
79+
return nil
80+
}

pkg/gui/context/list_context_trait.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ func (self *ListContextTrait) HandleRender() error {
102102
}
103103

104104
func (self *ListContextTrait) OnSearchSelect(selectedLineIdx int) error {
105-
self.GetList().SetSelection(selectedLineIdx)
105+
self.GetList().SetSelection(self.ViewIndexToModelIndex(selectedLineIdx))
106106
return self.HandleFocus(types.OnFocusOpts{})
107107
}
108108

pkg/gui/context/list_renderer.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ type ListRenderer struct {
3535
numNonModelItems int
3636
viewIndicesByModelIndex []int
3737
modelIndicesByViewIndex []int
38+
columnPositions []int
3839
}
3940

4041
func (self *ListRenderer) GetList() types.IList {
@@ -59,6 +60,10 @@ func (self *ListRenderer) ViewIndexToModelIndex(viewIndex int) int {
5960
return viewIndex
6061
}
6162

63+
func (self *ListRenderer) ColumnPositions() []int {
64+
return self.columnPositions
65+
}
66+
6267
// startIdx and endIdx are view indices, not model indices. If you want to
6368
// render the whole list, pass -1 for both.
6469
func (self *ListRenderer) renderLines(startIdx int, endIdx int) string {
@@ -87,6 +92,7 @@ func (self *ListRenderer) renderLines(startIdx int, endIdx int) string {
8792
lines, columnPositions := utils.RenderDisplayStrings(
8893
self.getDisplayStrings(startModelIdx, endModelIdx),
8994
columnAlignments)
95+
self.columnPositions = columnPositions
9096
lines = self.insertNonModelItems(nonModelItems, endIdx, startIdx, lines, columnPositions)
9197
return strings.Join(lines, "\n")
9298
}

pkg/gui/context/local_commits_context.go

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ package context
22

33
import (
44
"log"
5+
"strings"
56
"time"
67

8+
"github.com/jesseduffield/gocui"
79
"github.com/jesseduffield/lazygit/pkg/commands/models"
810
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
911
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
@@ -18,8 +20,9 @@ type LocalCommitsContext struct {
1820
}
1921

2022
var (
21-
_ types.IListContext = (*LocalCommitsContext)(nil)
22-
_ types.DiffableContext = (*LocalCommitsContext)(nil)
23+
_ types.IListContext = (*LocalCommitsContext)(nil)
24+
_ types.DiffableContext = (*LocalCommitsContext)(nil)
25+
_ types.ISearchableContext = (*LocalCommitsContext)(nil)
2326
)
2427

2528
func NewLocalCommitsContext(c *ContextCommon) *LocalCommitsContext {
@@ -85,10 +88,7 @@ func NewLocalCommitsContext(c *ContextCommon) *LocalCommitsContext {
8588
},
8689
}
8790

88-
ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(func(selectedLineIdx int) error {
89-
ctx.GetList().SetSelection(selectedLineIdx)
90-
return ctx.HandleFocus(types.OnFocusOpts{})
91-
}))
91+
ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(ctx.OnSearchSelect))
9292

9393
return ctx
9494
}
@@ -155,6 +155,10 @@ func (self *LocalCommitsContext) GetDiffTerminals() []string {
155155
return []string{itemId}
156156
}
157157

158+
func (self *LocalCommitsContext) ModelSearchResults(searchStr string, caseSensitive bool) []gocui.SearchPosition {
159+
return searchModelCommits(caseSensitive, self.GetCommits(), self.ColumnPositions(), searchStr)
160+
}
161+
158162
func (self *LocalCommitsViewModel) SetLimitCommits(value bool) {
159163
self.limitCommits = value
160164
}
@@ -194,3 +198,18 @@ func shouldShowGraph(c *ContextCommon) bool {
194198
log.Fatalf("Unknown value for git.log.showGraph: %s. Expected one of: 'always', 'never', 'when-maximised'", value)
195199
return false
196200
}
201+
202+
func searchModelCommits(caseSensitive bool, commits []*models.Commit, columnPositions []int, searchStr string) []gocui.SearchPosition {
203+
normalize := lo.Ternary(caseSensitive, func(s string) string { return s }, strings.ToLower)
204+
return lo.FilterMap(commits, func(commit *models.Commit, idx int) (gocui.SearchPosition, bool) {
205+
// The XStart and XEnd values are only used if the search string can't
206+
// be found in the view. This can really only happen if the user is
207+
// searching for a commit hash that is longer than the truncated hash
208+
// that we render. So we just set the XStart and XEnd values to the
209+
// start and end of the commit hash column, which is the second one.
210+
result := gocui.SearchPosition{XStart: columnPositions[1], XEnd: columnPositions[2] - 1, Y: idx}
211+
return result, strings.Contains(normalize(commit.Hash), searchStr) ||
212+
strings.Contains(normalize(commit.Name), searchStr) ||
213+
strings.Contains(normalize(commit.ExtraInfo), searchStr) // allow searching for tags
214+
})
215+
}

pkg/gui/context/patch_explorer_context.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ type PatchExplorerContext struct {
1818
mutex *deadlock.Mutex
1919
}
2020

21-
var _ types.IPatchExplorerContext = (*PatchExplorerContext)(nil)
21+
var (
22+
_ types.IPatchExplorerContext = (*PatchExplorerContext)(nil)
23+
_ types.ISearchableContext = (*PatchExplorerContext)(nil)
24+
)
2225

2326
func NewPatchExplorerContext(
2427
view *gocui.View,
@@ -139,3 +142,7 @@ func (self *PatchExplorerContext) NavigateTo(isFocused bool, selectedLineIdx int
139142
func (self *PatchExplorerContext) GetMutex() *deadlock.Mutex {
140143
return self.mutex
141144
}
145+
146+
func (self *PatchExplorerContext) ModelSearchResults(searchStr string, caseSensitive bool) []gocui.SearchPosition {
147+
return nil
148+
}

pkg/gui/context/sub_commits_context.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"time"
66

7+
"github.com/jesseduffield/gocui"
78
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
89
"github.com/jesseduffield/lazygit/pkg/commands/models"
910
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
@@ -21,8 +22,9 @@ type SubCommitsContext struct {
2122
}
2223

2324
var (
24-
_ types.IListContext = (*SubCommitsContext)(nil)
25-
_ types.DiffableContext = (*SubCommitsContext)(nil)
25+
_ types.IListContext = (*SubCommitsContext)(nil)
26+
_ types.DiffableContext = (*SubCommitsContext)(nil)
27+
_ types.ISearchableContext = (*SubCommitsContext)(nil)
2628
)
2729

2830
func NewSubCommitsContext(
@@ -73,8 +75,6 @@ func NewSubCommitsContext(
7375
selectedCommitHash,
7476
startIdx,
7577
endIdx,
76-
// Don't show the graph in the left/right view; we'd like to, but
77-
// it's too complicated:
7878
shouldShowGraph(c),
7979
git_commands.NewNullBisectInfo(),
8080
false,
@@ -133,10 +133,7 @@ func NewSubCommitsContext(
133133
},
134134
}
135135

136-
ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(func(selectedLineIdx int) error {
137-
ctx.GetList().SetSelection(selectedLineIdx)
138-
return ctx.HandleFocus(types.OnFocusOpts{})
139-
}))
136+
ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(ctx.OnSearchSelect))
140137

141138
return ctx
142139
}
@@ -204,3 +201,7 @@ func (self *SubCommitsContext) GetDiffTerminals() []string {
204201

205202
return []string{itemId}
206203
}
204+
205+
func (self *SubCommitsContext) ModelSearchResults(searchStr string, caseSensitive bool) []gocui.SearchPosition {
206+
return searchModelCommits(caseSensitive, self.GetCommits(), self.ColumnPositions(), searchStr)
207+
}

pkg/gui/context/working_tree_context.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package context
22

33
import (
4+
"github.com/jesseduffield/gocui"
45
"github.com/jesseduffield/lazygit/pkg/commands/models"
56
"github.com/jesseduffield/lazygit/pkg/gui/filetree"
67
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
@@ -15,7 +16,10 @@ type WorkingTreeContext struct {
1516
*SearchTrait
1617
}
1718

18-
var _ types.IListContext = (*WorkingTreeContext)(nil)
19+
var (
20+
_ types.IListContext = (*WorkingTreeContext)(nil)
21+
_ types.ISearchableContext = (*WorkingTreeContext)(nil)
22+
)
1923

2024
func NewWorkingTreeContext(c *ContextCommon) *WorkingTreeContext {
2125
viewModel := filetree.NewFileTreeViewModel(
@@ -51,10 +55,11 @@ func NewWorkingTreeContext(c *ContextCommon) *WorkingTreeContext {
5155
},
5256
}
5357

54-
ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(func(selectedLineIdx int) error {
55-
ctx.GetList().SetSelection(selectedLineIdx)
56-
return ctx.HandleFocus(types.OnFocusOpts{})
57-
}))
58+
ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(ctx.OnSearchSelect))
5859

5960
return ctx
6061
}
62+
63+
func (self *WorkingTreeContext) ModelSearchResults(searchStr string, caseSensitive bool) []gocui.SearchPosition {
64+
return nil
65+
}

pkg/gui/controllers/helpers/refresh_helper.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -759,6 +759,14 @@ func (self *RefreshHelper) refForLog() string {
759759
}
760760

761761
func (self *RefreshHelper) refreshView(context types.Context) error {
762+
// Re-applying the filter must be done before re-rendering the view, so that
763+
// the filtered list model is up to date for rendering.
762764
self.searchHelper.ReApplyFilter(context)
763-
return self.c.PostRefreshUpdate(context)
765+
766+
err := self.c.PostRefreshUpdate(context)
767+
768+
// Re-applying the search must be done after re-rendering the view though,
769+
// so that the "x of y" status is shown correctly.
770+
self.searchHelper.ReApplySearch(context)
771+
return err
764772
}

0 commit comments

Comments
 (0)