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:
parent
41ab7c44a0
commit
c74448f00d
4
go.mod
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
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 {
|
||||
|
39
pkg/integration/tests/filter_and_search/new_search.go
Normal file
39
pkg/integration/tests/filter_and_search/new_search.go
Normal 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`))
|
||||
},
|
||||
})
|
@ -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,
|
||||
|
1
vendor/github.com/go-errors/errors/README.md
generated
vendored
1
vendor/github.com/go-errors/errors/README.md
generated
vendored
@ -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)
|
||||
|
26
vendor/github.com/go-errors/errors/error_1_13.go
generated
vendored
26
vendor/github.com/go-errors/errors/error_1_13.go
generated
vendored
@ -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
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)
|
||||
}
|
71
vendor/github.com/go-errors/errors/join_unwrap_backward.go
generated
vendored
Normal file
71
vendor/github.com/go-errors/errors/join_unwrap_backward.go
generated
vendored
Normal 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()
|
||||
}
|
10
vendor/github.com/jesseduffield/gocui/view.go
generated
vendored
10
vendor/github.com/jesseduffield/gocui/view.go
generated
vendored
@ -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
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user