1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-11-23 22:24:51 +02:00

Keep cursor at top/bottom when navigating by page (#5019)

When pressing '.' (next page) or ',' (previous page), the selection now
stays at the bottom or top of the viewport respectively, instead of
being centered which caused items to scroll off. (If the selection is
not already on the last/first line of the view, '.'/',' moves it there
without scrolling.)

This implements a special case for page navigation as suggested by the
maintainer in issue #5017, keeping the cursor position consistent with
user expectations for page-based navigation.

Fixes #5017
This commit is contained in:
Stefan Haller
2025-11-09 19:43:48 +01:00
committed by GitHub

View File

@@ -101,10 +101,6 @@ func (self *ListController) handleLineChangeAux(f func(int), change int) error {
rangeAfter := list.IsSelectingRange() rangeAfter := list.IsSelectingRange()
after := list.GetSelectedLineIdx() after := list.GetSelectedLineIdx()
if err := self.pushContextIfNotFocused(); err != nil {
return err
}
// doing this check so that if we're holding the up key at the start of the list // doing this check so that if we're holding the up key at the start of the list
// we're not constantly re-rendering the main view. // we're not constantly re-rendering the main view.
cursorMoved := before != after cursorMoved := before != after
@@ -127,11 +123,59 @@ func (self *ListController) handleLineChangeAux(f func(int), change int) error {
} }
func (self *ListController) HandlePrevPage() error { func (self *ListController) HandlePrevPage() error {
return self.handleLineChange(-self.context.GetViewTrait().PageDelta()) return self.handlePageChange(-self.context.GetViewTrait().PageDelta())
} }
func (self *ListController) HandleNextPage() error { func (self *ListController) HandleNextPage() error {
return self.handleLineChange(self.context.GetViewTrait().PageDelta()) return self.handlePageChange(self.context.GetViewTrait().PageDelta())
}
func (self *ListController) handlePageChange(delta int) error {
list := self.context.GetList()
view := self.context.GetViewTrait()
before := list.GetSelectedLineIdx()
viewPortStart, viewPortHeight := view.ViewPortYBounds()
beforeViewIdx := self.context.ModelIndexToViewIndex(before)
afterViewIdx := beforeViewIdx + delta
newModelIndex := self.context.ViewIndexToModelIndex(afterViewIdx)
if delta < 0 {
// Previous page: keep selection at top of viewport
indexAtTopOfPage := self.context.ViewIndexToModelIndex(viewPortStart)
if before != indexAtTopOfPage {
// If the selection isn't already at the top of the page, move it there without scrolling
list.MoveSelectedLine(indexAtTopOfPage - before)
} else {
// Otherwise, move the selection by one page and scroll
list.MoveSelectedLine(newModelIndex - before)
linesToScroll := afterViewIdx - viewPortStart
if linesToScroll < 0 {
view.ScrollUp(-linesToScroll)
}
}
} else {
// Next page: keep selection at bottom of viewport
indexAtBottomOfPage := self.context.ViewIndexToModelIndex(viewPortStart + viewPortHeight - 1)
if before != indexAtBottomOfPage {
// If the selection isn't already at the bottom of the page, move it there without scrolling
list.MoveSelectedLine(indexAtBottomOfPage - before)
} else {
// Otherwise, move the selection by one page and scroll
list.MoveSelectedLine(newModelIndex - before)
linesToScroll := afterViewIdx - (viewPortStart + viewPortHeight - 1)
if linesToScroll > 0 {
view.ScrollDown(linesToScroll)
}
}
}
self.context.HandleFocus(types.OnFocusOpts{})
return nil
} }
func (self *ListController) HandleGotoTop() error { func (self *ListController) HandleGotoTop() error {