fix(review): keep the cursor line across a review layout toggle - #427
Merged
Conversation
Toggling a review map into the split carried a file, not a position: the selection handed to the split was the file plus its hunk index, and the way back was a quickfix lookup that jumped to the file's entry. Leaving the split therefore landed on the file header row in the map no matter where the cursor had been, and entering it landed on the first change of a hunk rather than the line that was selected. Both directions now travel as a source position, a side and a line number, which is the one thing a review map row and a split row can both name. Going in resolves the map row to that position through the hunk model and moves the pane pair to the row that shows it; coming back reads the position under the split cursor and resolves it to the map row that carries it, falling back to the file's quickfix row when the row names no source line. The split position is read when the toggle happens rather than when the split opened, so moving around inside the split is respected. Rows that face a filler, a deletion with nothing opposite it, take the position from the other pane, so deleted lines return to their own map row instead of the nearest surviving line. Duplicate paths across review sections resolve by review key, so a file that appears staged and unstaged returns to the section it came from.
barrettruth
force-pushed
the
fix/review-toggle-cursor-line
branch
from
August 12, 2026 23:51
78f0bdf to
fb6c1a7
Compare
A removed line and the line that replaced it occupy one row in the split and two in the map, so returning from the right pane lands on the added line even when the removed line is what opened the split. This is the cursor following the line it is actually on, and it settles there rather than drifting, but the rule was left implicit.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The review layout toggle carried a file, not a position. Going into the split, the selection handed over was the file plus its hunk index, so the pair opened at the first change of the hunk rather than the line that was selected. Coming back,
goto_review_map_selection()looked the file up in the quickfix list and jumped to its entry, which is thediff --githeader row, sogsout of a split always landed at the top of that file's diff no matter where the cursor had been.The mapping needed for the return trip already existed in one direction: a split row resolves to a source line through the pane's alignment rows, which is how opening the source file from a split lands on the right line. Nothing computed the inverse.
Solution
Both directions now travel as a source position, a side and a line number, which is the one thing a review map row and a split row can both name. Entering resolves the map row to that position through the hunk model and moves the pane pair to the row that shows it; leaving reads the position under the split cursor and resolves it back to the map row that carries it, falling back to the file's quickfix row when the row names no source line, such as a file or hunk header. The split position is read when the toggle happens rather than when the split was opened, so moving around inside the split is reflected in the map.
Rows facing a filler, a deletion with nothing opposite it, take their position from the other pane, so deleted lines return to their own map row instead of the nearest surviving line. Duplicate paths across review sections resolve by review key, so a file that appears both staged and unstaged returns to the section it came from.