1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2024-12-12 11:15:00 +02:00

Fix issue where active search inappropriately changed selected line (#3022)

This commit is contained in:
Jesse Duffield 2023-09-25 16:43:47 +10:00 committed by GitHub
commit 10fe872c71
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 185 additions and 55 deletions

4
go.mod
View File

@ -9,13 +9,13 @@ require (
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21 github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21
github.com/creack/pty v1.1.11 github.com/creack/pty v1.1.11
github.com/fsmiamoto/git-todo-parser v0.0.5 github.com/fsmiamoto/git-todo-parser v0.0.5
github.com/go-errors/errors v1.5.0 github.com/go-errors/errors v1.5.1
github.com/gookit/color v1.4.2 github.com/gookit/color v1.4.2
github.com/imdario/mergo v0.3.11 github.com/imdario/mergo v0.3.11
github.com/integrii/flaggy v1.4.0 github.com/integrii/flaggy v1.4.0
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68 github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d
github.com/jesseduffield/gocui v0.3.1-0.20230909074155-fc7119a39341 github.com/jesseduffield/gocui v0.3.1-0.20230925062444-7cd0d7e2a70a
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10 github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5
github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e

8
go.sum
View File

@ -88,8 +88,8 @@ github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs= github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
github.com/go-errors/errors v1.5.0 h1:/EuijeGOu7ckFxzhkj4CXJ8JaenxK7bKUxpPYqeLHqQ= github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk=
github.com/go-errors/errors v1.5.0/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
github.com/go-git/go-billy/v5 v5.0.0 h1:7NQHvd9FVid8VL4qVUMm8XifBK+2xCoZ2lSk0agRrHM= github.com/go-git/go-billy/v5 v5.0.0 h1:7NQHvd9FVid8VL4qVUMm8XifBK+2xCoZ2lSk0agRrHM=
@ -179,8 +179,8 @@ github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68 h1:EQP2Tv8T
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68/go.mod h1:+LLj9/WUPAP8LqCchs7P+7X0R98HiFujVFANdNaxhGk= github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68/go.mod h1:+LLj9/WUPAP8LqCchs7P+7X0R98HiFujVFANdNaxhGk=
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d h1:bO+OmbreIv91rCe8NmscRwhFSqkDJtzWCPV4Y+SQuXE= github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d h1:bO+OmbreIv91rCe8NmscRwhFSqkDJtzWCPV4Y+SQuXE=
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d/go.mod h1:nGNEErzf+NRznT+N2SWqmHnDnF9aLgANB1CUNEan09o= github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d/go.mod h1:nGNEErzf+NRznT+N2SWqmHnDnF9aLgANB1CUNEan09o=
github.com/jesseduffield/gocui v0.3.1-0.20230909074155-fc7119a39341 h1:COQ5uU+gFCQuE878cw0HcTSpKX+xLTu0/6lNTPJStG4= github.com/jesseduffield/gocui v0.3.1-0.20230925062444-7cd0d7e2a70a h1:/Ifbvq4BWY5VKoyPnHIW5oRLiy00S3ebFtVIY2MlJm0=
github.com/jesseduffield/gocui v0.3.1-0.20230909074155-fc7119a39341/go.mod h1:trXE7RRGL2hTsv+Ntk+SHLtRobg9JE138n3Ug/X2Cf4= github.com/jesseduffield/gocui v0.3.1-0.20230925062444-7cd0d7e2a70a/go.mod h1:trXE7RRGL2hTsv+Ntk+SHLtRobg9JE138n3Ug/X2Cf4=
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10 h1:jmpr7KpX2+2GRiE91zTgfq49QvgiqB0nbmlwZ8UnOx0= github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10 h1:jmpr7KpX2+2GRiE91zTgfq49QvgiqB0nbmlwZ8UnOx0=
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10/go.mod h1:aA97kHeNA+sj2Hbki0pvLslmE4CbDyhBeSSTUUnOuVo= github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10/go.mod h1:aA97kHeNA+sj2Hbki0pvLslmE4CbDyhBeSSTUUnOuVo=
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 h1:CDuQmfOjAtb1Gms6a1p5L2P8RhbLUq5t8aL7PiQd2uY= github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 h1:CDuQmfOjAtb1Gms6a1p5L2P8RhbLUq5t8aL7PiQd2uY=

View File

@ -37,20 +37,32 @@ func (self *SearchTrait) ClearSearchString() {
func (self *SearchTrait) IsSearchableContext() {} func (self *SearchTrait) IsSearchableContext() {}
func (self *SearchTrait) onSelectItemWrapper(innerFunc func(int) error) func(int, int, int) error { func (self *SearchTrait) onSelectItemWrapper(innerFunc func(int) error) func(int, int, int) error {
return func(selectedLineIdx int, index int, total int) error {
self.RenderSearchStatus(index, total)
if total != 0 {
if err := innerFunc(selectedLineIdx); err != nil {
return err
}
}
return nil
}
}
func (self *SearchTrait) RenderSearchStatus(index int, total int) {
keybindingConfig := self.c.UserConfig.Keybinding keybindingConfig := self.c.UserConfig.Keybinding
return func(y int, index int, total int) error { if total == 0 {
if total == 0 { self.c.SetViewContent(
self.c.SetViewContent( self.c.Views().Search,
self.c.Views().Search, fmt.Sprintf(
fmt.Sprintf( self.c.Tr.NoMatchesFor,
self.c.Tr.NoMatchesFor, self.searchString,
self.searchString, theme.OptionsFgColor.Sprintf(self.c.Tr.ExitSearchMode, keybindings.Label(keybindingConfig.Universal.Return)),
theme.OptionsFgColor.Sprintf(self.c.Tr.ExitSearchMode, keybindings.Label(keybindingConfig.Universal.Return)), ),
), )
) } else {
return nil
}
self.c.SetViewContent( self.c.SetViewContent(
self.c.Views().Search, self.c.Views().Search,
fmt.Sprintf( fmt.Sprintf(
@ -66,10 +78,6 @@ func (self *SearchTrait) onSelectItemWrapper(innerFunc func(int) error) func(int
), ),
), ),
) )
if err := innerFunc(y); err != nil {
return err
}
return nil
} }
} }

View File

@ -84,7 +84,8 @@ func (self *SearchHelper) DisplaySearchStatus(context types.ISearchableContext)
state.Context = context state.Context = context
self.searchPrefixView().SetContent(self.c.Tr.SearchPrefix) self.searchPrefixView().SetContent(self.c.Tr.SearchPrefix)
_ = context.GetView().SelectCurrentSearchResult() index, totalCount := context.GetView().GetSearchStatus()
context.RenderSearchStatus(index, totalCount)
} }
func (self *SearchHelper) searchState() *types.SearchState { func (self *SearchHelper) searchState() *types.SearchState {

View File

@ -115,6 +115,7 @@ type ISearchableContext interface {
ClearSearchString() ClearSearchString()
IsSearching() bool IsSearching() bool
IsSearchableContext() IsSearchableContext()
RenderSearchStatus(int, int)
} }
type DiffableContext interface { type DiffableContext interface {

View File

@ -0,0 +1,39 @@
package filter_and_search
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
// This is a regression test to ensure https://github.com/jesseduffield/lazygit/issues/2971
// doesn't happen again
var NewSearch = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Start a new search and verify the search begins from the current cursor position, not from the current search match",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
// need to create some branches, each with their own commits
shell.EmptyCommit("Add foo")
shell.EmptyCommit("Remove foo")
shell.EmptyCommit("Add bar")
shell.EmptyCommit("Remove bar")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Commits().
Focus().
Lines(
Contains(`Remove bar`).IsSelected(),
Contains(`Add bar`),
Contains(`Remove foo`),
Contains(`Add foo`),
).
FilterOrSearch("Add").
SelectedLine(Contains(`Add bar`)).
SelectPreviousItem().
SelectedLine(Contains(`Remove bar`)).
FilterOrSearch("Remove").
SelectedLine(Contains(`Remove bar`))
},
})

View File

@ -134,6 +134,7 @@ var tests = []*components.IntegrationTest{
filter_and_search.FilterSearchHistory, filter_and_search.FilterSearchHistory,
filter_and_search.NestedFilter, filter_and_search.NestedFilter,
filter_and_search.NestedFilterTransient, filter_and_search.NestedFilterTransient,
filter_and_search.NewSearch,
filter_by_path.CliArg, filter_by_path.CliArg,
filter_by_path.SelectFile, filter_by_path.SelectFile,
filter_by_path.TypeFile, filter_by_path.TypeFile,

View File

@ -81,3 +81,4 @@ This package is licensed under the MIT license, see LICENSE.MIT for details.
* v1.4.1 no code change, but now without an unnecessary cover.out file. * v1.4.1 no code change, but now without an unnecessary cover.out file.
* v1.4.2 performance improvement to ErrorStack() to avoid unnecessary work https://github.com/go-errors/errors/pull/40 * v1.4.2 performance improvement to ErrorStack() to avoid unnecessary work https://github.com/go-errors/errors/pull/40
* v1.5.0 add errors.Join() and errors.Unwrap() copying the stdlib https://github.com/go-errors/errors/pull/40 * v1.5.0 add errors.Join() and errors.Unwrap() copying the stdlib https://github.com/go-errors/errors/pull/40
* v1.5.1 fix build on go1.13..go1.19 (broken by adding Join and Unwrap with wrong build constraints)

View File

@ -33,29 +33,3 @@ func Is(e error, original error) bool {
return false return false
} }
// Join returns an error that wraps the given errors.
// Any nil error values are discarded.
// Join returns nil if every value in errs is nil.
// The error formats as the concatenation of the strings obtained
// by calling the Error method of each element of errs, with a newline
// between each string.
//
// A non-nil error returned by Join implements the Unwrap() []error method.
//
// For more information see stdlib errors.Join.
func Join(errs ...error) error {
return baseErrors.Join(errs...)
}
// Unwrap returns the result of calling the Unwrap method on err, if err's
// type contains an Unwrap method returning error.
// Otherwise, Unwrap returns nil.
//
// Unwrap only calls a method of the form "Unwrap() error".
// In particular Unwrap does not unwrap errors returned by [Join].
//
// For more information see stdlib errors.Unwrap.
func Unwrap(err error) error {
return baseErrors.Unwrap(err)
}

32
vendor/github.com/go-errors/errors/join_unwrap_1_20.go generated vendored Normal file
View File

@ -0,0 +1,32 @@
//go:build go1.20
// +build go1.20
package errors
import baseErrors "errors"
// Join returns an error that wraps the given errors.
// Any nil error values are discarded.
// Join returns nil if every value in errs is nil.
// The error formats as the concatenation of the strings obtained
// by calling the Error method of each element of errs, with a newline
// between each string.
//
// A non-nil error returned by Join implements the Unwrap() []error method.
//
// For more information see stdlib errors.Join.
func Join(errs ...error) error {
return baseErrors.Join(errs...)
}
// Unwrap returns the result of calling the Unwrap method on err, if err's
// type contains an Unwrap method returning error.
// Otherwise, Unwrap returns nil.
//
// Unwrap only calls a method of the form "Unwrap() error".
// In particular Unwrap does not unwrap errors returned by [Join].
//
// For more information see stdlib errors.Unwrap.
func Unwrap(err error) error {
return baseErrors.Unwrap(err)
}

View File

@ -0,0 +1,71 @@
//go:build !go1.20
// +build !go1.20
package errors
// Disclaimer: functions Join and Unwrap are copied from the stdlib errors
// package v1.21.0.
// Join returns an error that wraps the given errors.
// Any nil error values are discarded.
// Join returns nil if every value in errs is nil.
// The error formats as the concatenation of the strings obtained
// by calling the Error method of each element of errs, with a newline
// between each string.
//
// A non-nil error returned by Join implements the Unwrap() []error method.
func Join(errs ...error) error {
n := 0
for _, err := range errs {
if err != nil {
n++
}
}
if n == 0 {
return nil
}
e := &joinError{
errs: make([]error, 0, n),
}
for _, err := range errs {
if err != nil {
e.errs = append(e.errs, err)
}
}
return e
}
type joinError struct {
errs []error
}
func (e *joinError) Error() string {
var b []byte
for i, err := range e.errs {
if i > 0 {
b = append(b, '\n')
}
b = append(b, err.Error()...)
}
return string(b)
}
func (e *joinError) Unwrap() []error {
return e.errs
}
// Unwrap returns the result of calling the Unwrap method on err, if err's
// type contains an Unwrap method returning error.
// Otherwise, Unwrap returns nil.
//
// Unwrap only calls a method of the form "Unwrap() error".
// In particular Unwrap does not unwrap errors returned by [Join].
func Unwrap(err error) error {
u, ok := err.(interface {
Unwrap() error
})
if !ok {
return nil
}
return u.Unwrap()
}

View File

@ -211,10 +211,6 @@ func (v *View) gotoPreviousMatch() error {
return v.SelectSearchResult(v.searcher.currentSearchIndex) return v.SelectSearchResult(v.searcher.currentSearchIndex)
} }
func (v *View) SelectCurrentSearchResult() error {
return v.SelectSearchResult(v.searcher.currentSearchIndex)
}
func (v *View) SelectSearchResult(index int) error { func (v *View) SelectSearchResult(index int) error {
itemCount := len(v.searcher.searchPositions) itemCount := len(v.searcher.searchPositions)
if itemCount == 0 { if itemCount == 0 {
@ -225,6 +221,7 @@ func (v *View) SelectSearchResult(index int) error {
} }
y := v.searcher.searchPositions[index].y y := v.searcher.searchPositions[index].y
v.FocusPoint(v.ox, y) v.FocusPoint(v.ox, y)
if v.searcher.onSelectItem != nil { if v.searcher.onSelectItem != nil {
return v.searcher.onSelectItem(y, index, itemCount) return v.searcher.onSelectItem(y, index, itemCount)
@ -232,6 +229,11 @@ func (v *View) SelectSearchResult(index int) error {
return nil return nil
} }
// Returns <current match index>, <total matches>
func (v *View) GetSearchStatus() (int, int) {
return v.searcher.currentSearchIndex, len(v.searcher.searchPositions)
}
func (v *View) Search(str string) error { func (v *View) Search(str string) error {
v.writeMutex.Lock() v.writeMutex.Lock()
v.searcher.search(str) v.searcher.search(str)

4
vendor/modules.txt vendored
View File

@ -33,7 +33,7 @@ github.com/fsmiamoto/git-todo-parser/todo
# github.com/gdamore/encoding v1.0.0 # github.com/gdamore/encoding v1.0.0
## explicit; go 1.9 ## explicit; go 1.9
github.com/gdamore/encoding github.com/gdamore/encoding
# github.com/go-errors/errors v1.5.0 # github.com/go-errors/errors v1.5.1
## explicit; go 1.14 ## explicit; go 1.14
github.com/go-errors/errors github.com/go-errors/errors
# github.com/go-git/gcfg v1.5.0 # github.com/go-git/gcfg v1.5.0
@ -124,7 +124,7 @@ github.com/jesseduffield/go-git/v5/utils/merkletrie/filesystem
github.com/jesseduffield/go-git/v5/utils/merkletrie/index github.com/jesseduffield/go-git/v5/utils/merkletrie/index
github.com/jesseduffield/go-git/v5/utils/merkletrie/internal/frame github.com/jesseduffield/go-git/v5/utils/merkletrie/internal/frame
github.com/jesseduffield/go-git/v5/utils/merkletrie/noder github.com/jesseduffield/go-git/v5/utils/merkletrie/noder
# github.com/jesseduffield/gocui v0.3.1-0.20230909074155-fc7119a39341 # github.com/jesseduffield/gocui v0.3.1-0.20230925062444-7cd0d7e2a70a
## explicit; go 1.12 ## explicit; go 1.12
github.com/jesseduffield/gocui github.com/jesseduffield/gocui
# github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10 # github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10