Keep a metadata-carrying cell for a blank changed line

delta, fed a colored diff, renders some blank changed lines (an empty
deleted/added line) as just the OSC 1717 metadata followed by an empty
line — either with no fill at all, or as a background plus an ESC[0K that
the buffer now turns into a draw-time trailing fill rather than content
cells. Either way the line ends up with no cells, so its metadata had
nowhere to live and the line resolved to "not a change".

In the focused main view that broke change-block detection: a blank
deleted line in the middle of a hunk split it in two, so pressing 0
selected only the lines above the blank and the down arrow jumped to the
rest below it.

Restore the content-less sentinel cell finishLine used to add, but only
when there is pending OSC metadata to carry — so an empty line stays
resolvable as the change it is, without reintroducing the unconditional
sentinel (and its prevFgColor coupling) that was removed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Stefan Haller 2026-06-18 19:07:22 +02:00
parent 2088408f43
commit 131a315b7f

View file

@ -915,6 +915,15 @@ func (b *viewBuffer) write(v *View, p []byte) {
finishLine := func() {
b.autoRenderHyperlinksInCurrentLine(v)
// A pager can render a blank changed line as just its OSC 1717 metadata
// followed by an empty line — delta does this for some empty deleted/added
// lines. Keep a content-less cell to carry that metadata, so the line is
// still recognized as a change; without it the line resolves to nothing and
// breaks a change block in two (e.g. when selecting a hunk in the focused
// main view).
if len(b.lines[b.wy].cells) == 0 && b.ei.metadata.Len() > 0 {
b.writeCells([]cell{{metadata: b.ei.metadata.String()}})
}
}
advanceToNextLine := func() {