Preserve the diff scroll position when switching pagers

Cycling pagers re-renders the diff into the main view. Until now that
either lost the scroll position outright — an entry with its own
externalDiffCommand changes the actual git command, so the re-render
reset the view to the top — or kept it only by raw line number, which a
plain pager swap got for free because the git command was unchanged.

Raw line number is the wrong anchor: two pagers can structure the same
diff very differently (side-by-side vs inline), so the same screen line
means something different afterwards. Reuse the identity-based restore
(PreserveDiffPositionOnRerender, already driving the -U context-size
consumer) to re-anchor on the same patch line instead. That both keeps
the position meaningful when the structure changes and covers the
externalDiffCommand case the line-number approach couldn't.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Stefan Haller 2026-06-10 19:47:32 +02:00
parent 0cceaecfda
commit de8b19c247

View file

@ -190,6 +190,14 @@ func (self *GlobalController) onDiffRenderersChanged() {
if currentSide.GetKey() == currentKey ||
currentKey == context.NORMAL_MAIN_CONTEXT_KEY ||
currentKey == context.NORMAL_SECONDARY_CONTEXT_KEY {
// Switching pagers re-renders the diff. Keep it anchored on the same patch
// line across the switch, restoring by patch identity rather than raw line
// number: two pagers can structure the same diff very differently (side-by-
// side vs inline), so the same screen line means something different after.
// Without this a plain pager swap keeps the old origin (the git command is
// unchanged) but now pointing at the wrong content, while an entry with its
// own externalDiffCommand changes the git command and so resets to the top.
self.c.Helpers().Staging.PreserveDiffPositionOnRerender(self.c.Contexts().Normal.GetView())
currentSide.HandleRenderToMain()
}