diff --git a/go.mod b/go.mod index 1e35a0ca2..76287c0e2 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/gookit/color v1.4.2 github.com/integrii/flaggy v1.4.0 github.com/jesseduffield/generics v0.0.0-20250517122708-b0b4a53a6f5c - github.com/jesseduffield/gocui v0.3.1-0.20260308162933-5e45e57b5564 + github.com/jesseduffield/gocui v0.3.1-0.20260327132312-944dab3bc980 github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 github.com/karimkhaleel/jsonschema v0.0.0-20231001195015-d933f0d94ea3 @@ -37,7 +37,7 @@ require ( github.com/stretchr/testify v1.10.0 github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 - golang.org/x/sync v0.19.0 + golang.org/x/sync v0.20.0 golang.org/x/sys v0.42.0 gopkg.in/ozeidan/fuzzy-patricia.v3 v3.0.0 gopkg.in/yaml.v3 v3.0.1 @@ -66,8 +66,8 @@ require ( github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect golang.org/x/net v0.47.0 // indirect - golang.org/x/term v0.40.0 // indirect - golang.org/x/text v0.34.0 // indirect + golang.org/x/term v0.41.0 // indirect + golang.org/x/text v0.35.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/fsnotify.v1 v1.4.7 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect diff --git a/go.sum b/go.sum index ca4fa7e66..996508bcf 100644 --- a/go.sum +++ b/go.sum @@ -159,8 +159,8 @@ github.com/invopop/jsonschema v0.10.0 h1:c1ktzNLBun3LyQQhyty5WE3lulbOdIIyOVlkmDL github.com/invopop/jsonschema v0.10.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= github.com/jesseduffield/generics v0.0.0-20250517122708-b0b4a53a6f5c h1:tC2PaiisXAC5sOjDPfMArSnbswDObtCssx+xn28edX4= github.com/jesseduffield/generics v0.0.0-20250517122708-b0b4a53a6f5c/go.mod h1:F2fEBk0ddf6ixrBrJjY7phfQ3hL9rXG0uSjvwYe50bE= -github.com/jesseduffield/gocui v0.3.1-0.20260308162933-5e45e57b5564 h1:aB/Ytu+OCEpjft/BehqbH8/PTdgLREqbCvjK1JXctoo= -github.com/jesseduffield/gocui v0.3.1-0.20260308162933-5e45e57b5564/go.mod h1:lQCd2TvvNXVKFBowy4A7xxZbUp+1KEiGs4j0Q5Zt9gQ= +github.com/jesseduffield/gocui v0.3.1-0.20260327132312-944dab3bc980 h1:LEZwOrBm9S+4lRlXpoz+RSzSvhOVE+6v/Rk+A7Kg00Q= +github.com/jesseduffield/gocui v0.3.1-0.20260327132312-944dab3bc980/go.mod h1:lQCd2TvvNXVKFBowy4A7xxZbUp+1KEiGs4j0Q5Zt9gQ= github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 h1:CDuQmfOjAtb1Gms6a1p5L2P8RhbLUq5t8aL7PiQd2uY= github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5/go.mod h1:qxN4mHOAyeIDLP7IK7defgPClM/z1Kze8VVQiaEjzsQ= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= @@ -366,8 +366,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= -golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20170407050850-f3918c30c5c2/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -419,8 +419,8 @@ golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg= -golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM= +golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU= +golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -431,8 +431,8 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= -golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= +golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= +golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/pkg/gui/context/local_commits_context.go b/pkg/gui/context/local_commits_context.go index a730d6530..55415c761 100644 --- a/pkg/gui/context/local_commits_context.go +++ b/pkg/gui/context/local_commits_context.go @@ -134,9 +134,6 @@ func NewLocalCommitsContext(c *ContextCommon) *LocalCommitsContext { }, } - ctx.GetView().SetRenderSearchStatus(ctx.SearchTrait.RenderSearchStatus) - ctx.GetView().SetOnSelectItem(ctx.OnSearchSelect) - return ctx } diff --git a/pkg/gui/context/main_context.go b/pkg/gui/context/main_context.go index 716f20bca..f749c4be2 100644 --- a/pkg/gui/context/main_context.go +++ b/pkg/gui/context/main_context.go @@ -31,12 +31,12 @@ func NewMainContext( SearchTrait: NewSearchTrait(c), } - ctx.GetView().SetRenderSearchStatus(ctx.SearchTrait.RenderSearchStatus) - ctx.GetView().SetOnSelectItem(func(int) {}) - return ctx } func (self *MainContext) ModelSearchResults(searchStr string, caseSensitive bool) []gocui.SearchPosition { return nil } + +func (self *MainContext) OnSearchSelect(int) { +} diff --git a/pkg/gui/context/patch_explorer_context.go b/pkg/gui/context/patch_explorer_context.go index 082800127..167bdb41f 100644 --- a/pkg/gui/context/patch_explorer_context.go +++ b/pkg/gui/context/patch_explorer_context.go @@ -53,15 +53,6 @@ func NewPatchExplorerContext( SearchTrait: NewSearchTrait(c), } - ctx.GetView().SetRenderSearchStatus(ctx.SearchTrait.RenderSearchStatus) - ctx.GetView().SetOnSelectItem(func(selectedLineIdx int) { - ctx.GetMutex().Lock() - defer ctx.GetMutex().Unlock() - ctx.inOnSelectItemCallback = true - ctx.NavigateTo(selectedLineIdx) - ctx.inOnSelectItemCallback = false - }) - ctx.SetHandleRenderFunc(ctx.OnViewWidthChanged) return ctx @@ -146,6 +137,14 @@ func (self *PatchExplorerContext) ModelSearchResults(searchStr string, caseSensi return nil } +func (self *PatchExplorerContext) OnSearchSelect(selectedLineIdx int) { + self.GetMutex().Lock() + defer self.GetMutex().Unlock() + self.inOnSelectItemCallback = true + self.NavigateTo(selectedLineIdx) + self.inOnSelectItemCallback = false +} + func (self *PatchExplorerContext) OnViewWidthChanged() { if state := self.GetState(); state != nil { state.OnViewWidthChanged(self.GetView()) diff --git a/pkg/gui/context/sub_commits_context.go b/pkg/gui/context/sub_commits_context.go index 7e9d9ccab..55a06f286 100644 --- a/pkg/gui/context/sub_commits_context.go +++ b/pkg/gui/context/sub_commits_context.go @@ -134,9 +134,6 @@ func NewSubCommitsContext( }, } - ctx.GetView().SetRenderSearchStatus(ctx.SearchTrait.RenderSearchStatus) - ctx.GetView().SetOnSelectItem(ctx.OnSearchSelect) - return ctx } diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index 34d388391..50176e013 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -398,6 +398,24 @@ func (gui *Gui) onNewRepo(startArgs appTypes.StartArgs, contextKey types.Context return nil }) + gui.g.SetOnSelectSearchResultFunc(func(v *gocui.View, selectedLineIdx int) { + ctx, ok := gui.helpers.View.ContextForView(v.Name()) + if ok { + if searchableContext, ok := ctx.(types.ISearchableContext); ok { + searchableContext.OnSearchSelect(selectedLineIdx) + } + } + }) + + gui.g.SetRenderSearchStatusFunc(func(v *gocui.View, index int, total int) { + ctx, ok := gui.helpers.View.ContextForView(v.Name()) + if ok { + if searchableContext, ok := ctx.(types.ISearchableContext); ok { + searchableContext.RenderSearchStatus(index, total) + } + } + }) + // if a context key has been given, push that instead, and set its index to 0 if contextKey != context.NO_CONTEXT { contextToPush = gui.c.ContextForKey(contextKey) diff --git a/pkg/gui/types/context.go b/pkg/gui/types/context.go index afc8e11eb..09ed94e5a 100644 --- a/pkg/gui/types/context.go +++ b/pkg/gui/types/context.go @@ -151,6 +151,7 @@ type ISearchableContext interface { // This must be implemented by each concrete context. Return nil if not searching the model. ModelSearchResults(searchStr string, caseSensitive bool) []gocui.SearchPosition + OnSearchSelect(selectedLineIdx int) } type DiffableContext interface { diff --git a/vendor/github.com/jesseduffield/gocui/gui.go b/vendor/github.com/jesseduffield/gocui/gui.go index 96c622b3a..0d97e280b 100644 --- a/vendor/github.com/jesseduffield/gocui/gui.go +++ b/vendor/github.com/jesseduffield/gocui/gui.go @@ -139,21 +139,23 @@ type Gui struct { ReplayedEvents replayedEvents playRecording bool - tabClickBindings []*tabClickBinding - viewMouseBindings []*ViewMouseBinding - lastClick *clickInfo - gEvents chan GocuiEvent - userEvents chan userEvent - views []*View - currentView *View - managers []Manager - keybindings []*keybinding - focusHandler func(bool) error - openHyperlink func(string, string) error - maxX, maxY int - outputMode OutputMode - stop chan struct{} - blacklist []Key + tabClickBindings []*tabClickBinding + viewMouseBindings []*ViewMouseBinding + lastClick *clickInfo + gEvents chan GocuiEvent + userEvents chan userEvent + views []*View + currentView *View + managers []Manager + keybindings []*keybinding + focusHandler func(bool) error + openHyperlink func(string, string) error + onSelectSearchResultFunc func(*View, int) + renderSearchStatusFunc func(*View, int, int) + maxX, maxY int + outputMode OutputMode + stop chan struct{} + blacklist []Key // BgColor and FgColor allow to configure the background and foreground // colors of the GUI. @@ -355,11 +357,26 @@ func (g *Gui) SetView(name string, x0, y0, x1, y1 int, overlaps byte) (*View, er v.Overlaps = overlaps g.views = append(g.views, v) + v.setOnSelectResult(g.onSelectSearchItem) + v.setRenderSearchStatus(g.renderSearchStatus) + g.Mutexes.ViewsMutex.Unlock() return v, errors.Wrap(ErrUnknownView, 0) } +func (g *Gui) onSelectSearchItem(v *View, selectedLineIdx int) { + if g.onSelectSearchResultFunc != nil { + g.onSelectSearchResultFunc(v, selectedLineIdx) + } +} + +func (g *Gui) renderSearchStatus(v *View, selected int, total int) { + if g.renderSearchStatusFunc != nil { + g.renderSearchStatusFunc(v, selected, total) + } +} + // SetViewBeneath sets a view stacked beneath another view func (g *Gui) SetViewBeneath(name string, aboveViewName string, height int) (*View, error) { aboveView, err := g.View(aboveViewName) @@ -643,6 +660,14 @@ func (g *Gui) SetOpenHyperlinkFunc(openHyperlinkFunc func(string, string) error) g.openHyperlink = openHyperlinkFunc } +func (g *Gui) SetOnSelectSearchResultFunc(onSelectSearchResultFunc func(*View, int)) { + g.onSelectSearchResultFunc = onSelectSearchResultFunc +} + +func (g *Gui) SetRenderSearchStatusFunc(renderSearchStatusFunc func(*View, int, int)) { + g.renderSearchStatusFunc = renderSearchStatusFunc +} + // getKey takes an empty interface with a key and returns the corresponding // typed Key or rune. func getKey(key any) (Key, rune, error) { diff --git a/vendor/github.com/jesseduffield/gocui/view.go b/vendor/github.com/jesseduffield/gocui/view.go index 9ba8b7efc..16da0a380 100644 --- a/vendor/github.com/jesseduffield/gocui/view.go +++ b/vendor/github.com/jesseduffield/gocui/view.go @@ -214,21 +214,21 @@ type searcher struct { searchPositions []SearchPosition modelSearchResults []SearchPosition currentSearchIndex int - onSelectItem func(int) - renderSearchStatus func(int, int) + onSelectItem func(*View, int) + renderSearchStatus func(*View, int, int) } -func (v *View) SetRenderSearchStatus(renderSearchStatus func(int, int)) { +func (v *View) setRenderSearchStatus(renderSearchStatus func(*View, int, int)) { v.searcher.renderSearchStatus = renderSearchStatus } -func (v *View) SetOnSelectItem(onSelectItem func(int)) { +func (v *View) setOnSelectResult(onSelectItem func(*View, int)) { v.searcher.onSelectItem = onSelectItem } func (v *View) renderSearchStatus(index int, itemCount int) { if v.searcher.renderSearchStatus != nil { - v.searcher.renderSearchStatus(index, itemCount) + v.searcher.renderSearchStatus(v, index, itemCount) } } @@ -286,7 +286,7 @@ func (v *View) SelectSearchResult(index int) { v.FocusPoint(v.ox, y, true) v.renderSearchStatus(index, itemCount) if v.searcher.onSelectItem != nil { - v.searcher.onSelectItem(y) + v.searcher.onSelectItem(v, y) } } diff --git a/vendor/modules.txt b/vendor/modules.txt index fce15cd50..222e83cfd 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -89,7 +89,7 @@ github.com/integrii/flaggy github.com/jesseduffield/generics/maps github.com/jesseduffield/generics/orderedset github.com/jesseduffield/generics/set -# github.com/jesseduffield/gocui v0.3.1-0.20260308162933-5e45e57b5564 +# github.com/jesseduffield/gocui v0.3.1-0.20260327132312-944dab3bc980 ## explicit; go 1.25 github.com/jesseduffield/gocui # github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 @@ -188,19 +188,19 @@ golang.org/x/exp/constraints golang.org/x/exp/slices # golang.org/x/net v0.47.0 ## explicit; go 1.24.0 -# golang.org/x/sync v0.19.0 -## explicit; go 1.24.0 +# golang.org/x/sync v0.20.0 +## explicit; go 1.25.0 golang.org/x/sync/errgroup # golang.org/x/sys v0.42.0 ## explicit; go 1.25.0 golang.org/x/sys/plan9 golang.org/x/sys/unix golang.org/x/sys/windows -# golang.org/x/term v0.40.0 -## explicit; go 1.24.0 +# golang.org/x/term v0.41.0 +## explicit; go 1.25.0 golang.org/x/term -# golang.org/x/text v0.34.0 -## explicit; go 1.24.0 +# golang.org/x/text v0.35.0 +## explicit; go 1.25.0 golang.org/x/text/encoding golang.org/x/text/encoding/internal/identifier golang.org/x/text/runes