Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ require (
github.com/integrii/flaggy v1.4.0
github.com/jesseduffield/generics v0.0.0-20250517122708-b0b4a53a6f5c
github.com/jesseduffield/go-git/v5 v5.14.1-0.20250407170251-e1a013310ccd
github.com/jesseduffield/gocui v0.3.1-0.20251214132308-02ab34c1c624
github.com/jesseduffield/gocui v0.3.1-0.20251223143206-950739ccd44a
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
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,8 @@ github.com/jesseduffield/generics v0.0.0-20250517122708-b0b4a53a6f5c h1:tC2Paiis
github.com/jesseduffield/generics v0.0.0-20250517122708-b0b4a53a6f5c/go.mod h1:F2fEBk0ddf6ixrBrJjY7phfQ3hL9rXG0uSjvwYe50bE=
github.com/jesseduffield/go-git/v5 v5.14.1-0.20250407170251-e1a013310ccd h1:ViKj6qth8FgcIWizn9KiACWwPemWSymx62OPN0tHT+Q=
github.com/jesseduffield/go-git/v5 v5.14.1-0.20250407170251-e1a013310ccd/go.mod h1:lRhCiBr6XjQrvcQVa+UYsy/99d3wMXn/a0nSQlhnhlA=
github.com/jesseduffield/gocui v0.3.1-0.20251214132308-02ab34c1c624 h1:30mIX4f52zrO4fWfZQKHJG29t2apcSOtR/sbd3BNsVE=
github.com/jesseduffield/gocui v0.3.1-0.20251214132308-02ab34c1c624/go.mod h1:sLIyZ2J42R6idGdtemZzsiR3xY5EF0KsvYEGh3dQv3s=
github.com/jesseduffield/gocui v0.3.1-0.20251223143206-950739ccd44a h1:XRsyqrSljes4TlaPczQViIAA4xqdnB0fKEEpZdqWWTA=
github.com/jesseduffield/gocui v0.3.1-0.20251223143206-950739ccd44a/go.mod h1:sLIyZ2J42R6idGdtemZzsiR3xY5EF0KsvYEGh3dQv3s=
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=
Expand Down
8 changes: 4 additions & 4 deletions pkg/gui/context/list_context_trait.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ type ListContextTrait struct {

func (self *ListContextTrait) IsListContext() {}

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

// Doing this at the end of the layout function because we need the view to be
// resized before we focus the line, otherwise if we're in accordion mode
Expand All @@ -36,7 +36,7 @@ func (self *ListContextTrait) FocusLine() {
oldOrigin, _ := self.GetViewTrait().ViewPortYBounds()

self.GetViewTrait().FocusPoint(
self.ModelIndexToViewIndex(self.list.GetSelectedLineIdx()))
self.ModelIndexToViewIndex(self.list.GetSelectedLineIdx()), scrollIntoView)

selectRangeIndex, isSelectingRange := self.list.GetRangeStartIdx()
if isSelectingRange {
Expand Down Expand Up @@ -75,7 +75,7 @@ func formatListFooter(selectedLineIdx int, length int) string {
}

func (self *ListContextTrait) HandleFocus(opts types.OnFocusOpts) {
self.FocusLine()
self.FocusLine(opts.ScrollSelectionIntoView)

self.GetViewTrait().SetHighlight(self.list.Len() > 0)

Expand Down
2 changes: 1 addition & 1 deletion pkg/gui/context/simple_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func (self *SimpleContext) HandleFocusLost(opts types.OnFocusLostOpts) {
}
}

func (self *SimpleContext) FocusLine() {
func (self *SimpleContext) FocusLine(scrollIntoView bool) {
}

func (self *SimpleContext) HandleRender() {
Expand Down
4 changes: 2 additions & 2 deletions pkg/gui/context/view_trait.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ func NewViewTrait(view *gocui.View) *ViewTrait {
return &ViewTrait{view: view}
}

func (self *ViewTrait) FocusPoint(yIdx int) {
self.view.FocusPoint(self.view.OriginX(), yIdx)
func (self *ViewTrait) FocusPoint(yIdx int, scrollIntoView bool) {
self.view.FocusPoint(self.view.OriginX(), yIdx, scrollIntoView)
}

func (self *ViewTrait) SetRangeSelectStart(yIdx int) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/gui/controllers/branches_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ func (self *BranchesController) createNewBranchWithName(newBranchName string) er
return err
}

self.context().SetSelection(0)
self.c.Helpers().Refs.SelectFirstBranchAndFirstCommit()
self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, KeepBranchSelectionIndex: true})
return nil
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/gui/controllers/helpers/cherry_pick_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func (self *CherryPickHelper) Paste() error {
// below the selection.
if commit := self.c.Contexts().LocalCommits.GetSelected(); commit != nil && !commit.IsTODO() {
self.c.Contexts().LocalCommits.MoveSelection(len(cherryPickedCommits))
self.c.Contexts().LocalCommits.FocusLine()
self.c.Contexts().LocalCommits.FocusLine(true)
}

// If we're in the cherry-picking state at this point, it must
Expand Down
23 changes: 14 additions & 9 deletions pkg/gui/controllers/helpers/refs_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ func NewRefsHelper(
}
}

func (self *RefsHelper) SelectFirstBranchAndFirstCommit() {
self.c.Contexts().Branches.SetSelection(0)
self.c.Contexts().ReflogCommits.SetSelection(0)
self.c.Contexts().LocalCommits.SetSelection(0)
self.c.Contexts().Branches.GetView().SetOriginY(0)
self.c.Contexts().ReflogCommits.GetView().SetOriginY(0)
self.c.Contexts().LocalCommits.GetView().SetOriginY(0)
}

func (self *RefsHelper) CheckoutRef(ref string, options types.CheckoutRefOptions) error {
waitingStatus := options.WaitingStatus
if waitingStatus == "" {
Expand All @@ -40,9 +49,8 @@ func (self *RefsHelper) CheckoutRef(ref string, options types.CheckoutRefOptions
cmdOptions := git_commands.CheckoutOptions{Force: false, EnvVars: options.EnvVars}

refresh := func() {
self.c.Contexts().Branches.SetSelection(0)
self.c.Contexts().ReflogCommits.SetSelection(0)
self.c.Contexts().LocalCommits.SetSelection(0)
self.SelectFirstBranchAndFirstCommit()

// loading a heap of commits is slow so we limit them whenever doing a reset
self.c.Contexts().LocalCommits.SetLimitCommits(true)

Expand Down Expand Up @@ -348,8 +356,7 @@ func (self *RefsHelper) NewBranch(from string, fromFormattedName string, suggest
self.c.Context().Push(self.c.Contexts().Branches, types.OnFocusOpts{})
}

self.c.Contexts().LocalCommits.SetSelection(0)
self.c.Contexts().Branches.SetSelection(0)
self.SelectFirstBranchAndFirstCommit()

self.c.Refresh(types.RefreshOptions{Mode: types.BLOCK_UI, KeepBranchSelectionIndex: true})
}
Expand Down Expand Up @@ -504,8 +511,7 @@ func (self *RefsHelper) moveCommitsToNewBranchStackedOnCurrentBranch(newBranchNa
}
}

self.c.Contexts().LocalCommits.SetSelection(0)
self.c.Contexts().Branches.SetSelection(0)
self.SelectFirstBranchAndFirstCommit()

self.c.Refresh(types.RefreshOptions{Mode: types.BLOCK_UI, KeepBranchSelectionIndex: true})
return nil
Expand Down Expand Up @@ -543,8 +549,7 @@ func (self *RefsHelper) moveCommitsToNewBranchOffOfMainBranch(newBranchName stri
}
}

self.c.Contexts().LocalCommits.SetSelection(0)
self.c.Contexts().Branches.SetSelection(0)
self.SelectFirstBranchAndFirstCommit()

self.c.Refresh(types.RefreshOptions{Mode: types.BLOCK_UI, KeepBranchSelectionIndex: true})
return nil
Expand Down
9 changes: 8 additions & 1 deletion pkg/gui/controllers/list_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,12 @@ func (self *ListController) handleLineChangeAux(f func(int), change int) error {
}

if cursorMoved || rangeBefore != rangeAfter {
self.context.HandleFocus(types.OnFocusOpts{})
self.context.HandleFocus(types.OnFocusOpts{ScrollSelectionIntoView: true})
} else {
// If the selection did not change (because, for example, we are at the top of the list and
// press up), we still want to ensure that the selection is visible. This is useful after
// scrolling the selection out of view with the mouse.
self.context.FocusLine(true)
}

return nil
Expand Down Expand Up @@ -173,6 +178,8 @@ func (self *ListController) handlePageChange(delta int) error {
}
}

// Since we are maintaining the scroll position ourselves above, there's no point in passing
// ScrollSelectionIntoView=true here.
self.context.HandleFocus(types.OnFocusOpts{})

return nil
Expand Down
2 changes: 1 addition & 1 deletion pkg/gui/controllers/local_commits_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -869,7 +869,7 @@ func (self *LocalCommitsController) revert(commits []*models.Commit, start, end
return err
}
self.context().MoveSelection(len(commits))
self.context().HandleFocus(types.OnFocusOpts{})
self.context().HandleFocus(types.OnFocusOpts{ScrollSelectionIntoView: true})

if mustStash {
if err := self.c.Git().Stash.Pop(0); err != nil {
Expand Down
2 changes: 1 addition & 1 deletion pkg/gui/controllers/remotes_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ func (self *RemotesController) fetchAndCheckout(remote *models.Remote, branchNam
err = self.c.Git().Branch.New(branchName, remote.Name+"/"+branchName)
if err == nil {
self.c.Context().Push(self.c.Contexts().Branches, types.OnFocusOpts{})
self.c.Contexts().Branches.SetSelection(0)
self.c.Helpers().Refs.SelectFirstBranchAndFirstCommit()
refreshOptions.KeepBranchSelectionIndex = true
}
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/gui/controllers/stash_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ func (self *StashController) handleRenameStashEntry(stashEntry *models.StashEntr
return err
}
self.context().SetSelection(0) // Select the renamed stash
self.context().FocusLine()
self.context().FocusLine(true)
self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.STASH}})
return nil
},
Expand Down
9 changes: 5 additions & 4 deletions pkg/gui/types/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ type Context interface {

HandleFocus(opts OnFocusOpts)
HandleFocusLost(opts OnFocusLostOpts)
FocusLine()
FocusLine(scrollIntoView bool)
HandleRender()
HandleRenderToMain()
}
Expand Down Expand Up @@ -201,7 +201,7 @@ type IPatchExplorerContext interface {
}

type IViewTrait interface {
FocusPoint(yIdx int)
FocusPoint(yIdx int, scrollIntoView bool)
SetRangeSelectStart(yIdx int)
CancelRangeSelect()
SetViewPortContent(content string)
Expand All @@ -221,8 +221,9 @@ type IViewTrait interface {
}

type OnFocusOpts struct {
ClickedWindowName string
ClickedViewLineIdx int
ClickedWindowName string
ClickedViewLineIdx int
ScrollSelectionIntoView bool
}

type OnFocusLostOpts struct {
Expand Down
2 changes: 1 addition & 1 deletion pkg/gui/view_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ func (gui *Gui) postRefreshUpdate(c types.Context) {
// non-focused views to ensure that an inactive selection is painted
// correctly, and that integration tests see the up to date selection
// state.
c.FocusLine()
c.FocusLine(false)

currentCtx := gui.State.ContextMgr.Current()
if currentCtx.GetKey() == context.NORMAL_MAIN_CONTEXT_KEY || currentCtx.GetKey() == context.NORMAL_SECONDARY_CONTEXT_KEY {
Expand Down
4 changes: 2 additions & 2 deletions pkg/integration/clients/tui.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func RunTUI(raceDetector bool) {
if err != nil {
return err
}
listView.FocusPoint(0, app.itemIdx)
listView.FocusPoint(0, app.itemIdx, true)
return nil
}); err != nil {
log.Panicln(err)
Expand All @@ -66,7 +66,7 @@ func RunTUI(raceDetector bool) {
if err != nil {
return err
}
listView.FocusPoint(0, app.itemIdx)
listView.FocusPoint(0, app.itemIdx, true)
return nil
}); err != nil {
log.Panicln(err)
Expand Down
11 changes: 7 additions & 4 deletions vendor/github.com/jesseduffield/gocui/view.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion vendor/modules.txt
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ 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/sync
github.com/jesseduffield/go-git/v5/utils/trace
# github.com/jesseduffield/gocui v0.3.1-0.20251214132308-02ab34c1c624
# github.com/jesseduffield/gocui v0.3.1-0.20251223143206-950739ccd44a
## explicit; go 1.12
github.com/jesseduffield/gocui
# github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5
Expand Down