1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-03-21 21:47:32 +02:00

Don't select current search result when showing search status

Previously there was no way to render a view's search status without also moving the cursor
to the current search match. This caused issues where we wanted to display the status
after leaving the view and coming back, or when beginning a new search from within the
view.

This commit separates the two use cases so we only move the cursor when we're actually
selecting the next search match
This commit is contained in:
Jesse Duffield 2023-09-25 15:34:15 +10:00
parent 41ab7c44a0
commit c74448f00d
13 changed files with 185 additions and 55 deletions
go.modgo.sum
pkg
gui
context
controllers/helpers
types
integration/tests
filter_and_search
test_list.go
vendor

4
go.mod

@ -9,13 +9,13 @@ require (
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21
github.com/creack/pty v1.1.11
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/imdario/mergo v0.3.11
github.com/integrii/flaggy v1.4.0
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68
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/lazycore v0.0.0-20221012050358-03d2e40243c5
github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e

8
go.sum

@ -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/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
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.0/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk=
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/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
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/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/gocui v0.3.1-0.20230909074155-fc7119a39341 h1:COQ5uU+gFCQuE878cw0HcTSpKX+xLTu0/6lNTPJStG4=
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 h1:/Ifbvq4BWY5VKoyPnHIW5oRLiy00S3ebFtVIY2MlJm0=
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/go.mod h1:aA97kHeNA+sj2Hbki0pvLslmE4CbDyhBeSSTUUnOuVo=
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 h1:CDuQmfOjAtb1Gms6a1p5L2P8RhbLUq5t8aL7PiQd2uY=

@ -37,20 +37,32 @@ func (self *SearchTrait) ClearSearchString() {
func (self *SearchTrait) IsSearchableContext() {}
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
return func(y int, index int, total int) error {
if total == 0 {
self.c.SetViewContent(
self.c.Views().Search,
fmt.Sprintf(
self.c.Tr.NoMatchesFor,
self.searchString,
theme.OptionsFgColor.Sprintf(self.c.Tr.ExitSearchMode, keybindings.Label(keybindingConfig.Universal.Return)),
),
)
return nil
}
if total == 0 {
self.c.SetViewContent(
self.c.Views().Search,
fmt.Sprintf(
self.c.Tr.NoMatchesFor,
self.searchString,
theme.OptionsFgColor.Sprintf(self.c.Tr.ExitSearchMode, keybindings.Label(keybindingConfig.Universal.Return)),
),
)
} else {
self.c.SetViewContent(
self.c.Views().Search,
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
}
}

@ -84,7 +84,8 @@ func (self *SearchHelper) DisplaySearchStatus(context types.ISearchableContext)
state.Context = context
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 {

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

@ -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`))
},
})

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

@ -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.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.1 fix build on go1.13..go1.19 (broken by adding Join and Unwrap with wrong build constraints)

@ -33,29 +33,3 @@ func Is(e error, original error) bool {
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

@ -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)
}

@ -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()
}

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

4
vendor/modules.txt vendored

@ -33,7 +33,7 @@ github.com/fsmiamoto/git-todo-parser/todo
# github.com/gdamore/encoding v1.0.0
## explicit; go 1.9
github.com/gdamore/encoding
# github.com/go-errors/errors v1.5.0
# github.com/go-errors/errors v1.5.1
## explicit; go 1.14
github.com/go-errors/errors
# 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/internal/frame
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
github.com/jesseduffield/gocui
# github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10