Skip to content

Commit 65edd99

Browse files
committed
Update search position (match x of y) when changing the selection in a list view
or in the staging view.
1 parent 98bf8f8 commit 65edd99

File tree

3 files changed

+75
-0
lines changed

3 files changed

+75
-0
lines changed

pkg/gui/context/list_context_trait.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,21 @@ type ListContextTrait struct {
2424
// If renderOnlyVisibleLines is true, needRerenderVisibleLines indicates whether we need to
2525
// rerender the visible lines e.g. because the scroll position changed
2626
needRerenderVisibleLines bool
27+
28+
// true if we're inside the OnSearchSelect call; in that case we don't want to update the search
29+
// result index.
30+
inOnSearchSelect bool
2731
}
2832

2933
func (self *ListContextTrait) IsListContext() {}
3034

3135
func (self *ListContextTrait) FocusLine(scrollIntoView bool) {
3236
self.Context.FocusLine(scrollIntoView)
3337

38+
// Need to capture this in a local variable because by the time the AfterLayout function runs,
39+
// the field will have been reset to false already
40+
inOnSearchSelect := self.inOnSearchSelect
41+
3442
// Doing this at the end of the layout function because we need the view to be
3543
// resized before we focus the line, otherwise if we're in accordion mode
3644
// the view could be squashed and won't know how to adjust the cursor/origin.
@@ -40,6 +48,9 @@ func (self *ListContextTrait) FocusLine(scrollIntoView bool) {
4048

4149
self.GetViewTrait().FocusPoint(
4250
self.ModelIndexToViewIndex(self.list.GetSelectedLineIdx()), scrollIntoView)
51+
if !inOnSearchSelect {
52+
self.GetView().SetNearestSearchPosition()
53+
}
4354

4455
selectRangeIndex, isSelectingRange := self.list.GetRangeStartIdx()
4556
if isSelectingRange {
@@ -119,7 +130,9 @@ func (self *ListContextTrait) HandleRender() {
119130

120131
func (self *ListContextTrait) OnSearchSelect(selectedLineIdx int) {
121132
self.GetList().SetSelection(self.ViewIndexToModelIndex(selectedLineIdx))
133+
self.inOnSearchSelect = true
122134
self.HandleFocus(types.OnFocusOpts{})
135+
self.inOnSearchSelect = false
123136
}
124137

125138
func (self *ListContextTrait) IsItemVisible(item types.HasUrn) bool {

pkg/gui/context/patch_explorer_context.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ type PatchExplorerContext struct {
1616
getIncludedLineIndices func() []int
1717
c *ContextCommon
1818
mutex deadlock.Mutex
19+
20+
// true if we're inside the OnSelectItem callback; in that case we don't want to update the
21+
// search result index.
22+
inOnSelectItemCallback bool
1923
}
2024

2125
var (
@@ -53,7 +57,9 @@ func NewPatchExplorerContext(
5357
ctx.GetView().SetOnSelectItem(func(selectedLineIdx int) {
5458
ctx.GetMutex().Lock()
5559
defer ctx.GetMutex().Unlock()
60+
ctx.inOnSelectItemCallback = true
5661
ctx.NavigateTo(selectedLineIdx)
62+
ctx.inOnSelectItemCallback = false
5763
})
5864

5965
ctx.SetHandleRenderFunc(ctx.OnViewWidthChanged)
@@ -111,6 +117,10 @@ func (self *PatchExplorerContext) FocusSelection() {
111117
// As far as the view is concerned, we are always selecting a range
112118
view.SetRangeSelectStart(startIdx)
113119
view.SetCursorY(endIdx - newOriginY)
120+
121+
if !self.inOnSelectItemCallback {
122+
view.SetNearestSearchPosition()
123+
}
114124
}
115125

116126
func (self *PatchExplorerContext) GetContentToRender() string {

pkg/integration/tests/commit/search.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ var Search = NewIntegrationTest(NewIntegrationTestArgs{
1111
Skip: false,
1212
SetupConfig: func(config *config.AppConfig) {},
1313
SetupRepo: func(shell *Shell) {
14+
// Creating a branch avoids that searching for 't' will unexpectedly match the first commit
15+
// (since it finds it in the extra info line, which is "HEAD -> master")
16+
shell.NewBranch("branch")
17+
1418
shell.EmptyCommit("one")
1519
shell.EmptyCommit("two")
1620
shell.EmptyCommit("three")
@@ -103,6 +107,54 @@ var Search = NewIntegrationTest(NewIntegrationTestArgs{
103107
Contains("three"),
104108
Contains("two"),
105109
Contains("one").IsSelected(),
110+
).
111+
NavigateToLine(Contains("three")).
112+
Tap(func() {
113+
t.Views().Search().IsVisible().Content(Contains("matches for 'o' (1 of 3)"))
114+
}).
115+
Press("N").
116+
Tap(func() {
117+
t.Views().Search().IsVisible().Content(Contains("matches for 'o' (1 of 3)"))
118+
}).
119+
Lines(
120+
Contains("four").IsSelected(),
121+
Contains("three"),
122+
Contains("two"),
123+
Contains("one"),
124+
).
125+
Press(keys.Universal.StartSearch).
126+
Tap(func() {
127+
t.ExpectSearch().
128+
Type("t").
129+
Confirm()
130+
131+
t.Views().Search().IsVisible().Content(Contains("matches for 't' (1 of 2)"))
132+
}).
133+
Lines(
134+
Contains("four"),
135+
Contains("three").IsSelected(),
136+
Contains("two"),
137+
Contains("one"),
138+
).
139+
SelectPreviousItem().
140+
Tap(func() {
141+
t.Views().Search().IsVisible().Content(Contains("matches for 't' (1 of 2)"))
142+
}).
143+
Lines(
144+
Contains("four").IsSelected(),
145+
Contains("three"),
146+
Contains("two"),
147+
Contains("one"),
148+
).
149+
Press("n").
150+
Tap(func() {
151+
t.Views().Search().IsVisible().Content(Contains("matches for 't' (1 of 2)"))
152+
}).
153+
Lines(
154+
Contains("four"),
155+
Contains("three").IsSelected(),
156+
Contains("two"),
157+
Contains("one"),
106158
)
107159
},
108160
})

0 commit comments

Comments
 (0)