Fixed
- Scroll offset centering misaligns when alternating up/down movement — with high
scrolloffvalues (e.g.,set scrolloff=999for centered scrolling), the cursor's vertical position drifted ~17px when changing movement direction (move down, stop, move up). Root cause: theupdateListener-based scrolloff usedif/else ifto enforce only one margin (top or bottom) per update cycle. With centering, both constraints are always violated but only one was corrected, causing direction-dependent asymmetry. Fixed by replacing theif/else ifwith a constraint-based algorithm: convert visual coordinates to document-relative positions, computeminScroll/maxScrollfor both margins simultaneously, clampscrollTopinto the valid interval, and use the midpoint when the interval is inverted (high scrolloff centering) for direction-independent symmetric positioning. Also narrowed the update trigger fromselectionSet || viewportChangedtoselectionSetonly — viewport-only changes (e.g.,zt/zz/zbscroll commands) should not trigger scrolloff re-adjustment. A 1px dead zone prevents subpixel oscillation. (#176)- Plugin:
src/vim/scrolloff.ts(constraint-based dual-margin algorithm withcoordsAtPos+ midpoint, narrowed trigger toselectionSetonly)
- Plugin:
Tests
- 1 regression test in
test/specs/scrolloff-centering.e2e.tsfor #176 (cursor stays centered when alternating up/down movement withscrolloff=100)
Documentation
CHANGELOG.md
Full Changelog: 0.146.0...0.147.0