Swallow a diff renderer's protocol handshake

Before the diff, a conforming renderer emits one OSC 1717 record that
carries only the version — its way of announcing that it speaks the
protocol at all, without a host having to inspect what it renders. It
describes no line, so keeping it would give the first line of the diff a
record that says nothing about it.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Stefan Haller
2026-10-04 19:01:01 +02:00
co-authored by Claude Opus 5
parent d1a9850531
commit 42ae6d4ea6
2 changed files with 31 additions and 0 deletions
+14
View File
@@ -489,8 +489,10 @@ func (ei *escapeInterpreter) parseOne(ch []byte) (isEscape bool, err error) {
case stateOSCMetadata:
switch {
case characterEquals(ch, 0x07):
ei.dropMetadataIfHandshake()
ei.state = stateNone
case characterEquals(ch, 0x1b):
ei.dropMetadataIfHandshake()
ei.state = stateOSCEndEscape
default:
ei.metadata.Write(ch)
@@ -511,6 +513,18 @@ func (ei *escapeInterpreter) parseOne(ch []byte) (isEscape bool, err error) {
return false, nil
}
// dropMetadataIfHandshake discards a just-completed OSC 1717 payload that
// carries nothing beyond the version. A diff renderer emits such a record ahead
// of everything else to announce that it speaks the protocol, so that a host can
// find that out by asking rather than by inspecting a rendering. It says nothing
// about any line, so it must not attach to the line that follows it; a per-line
// record always has fields, and is kept.
func (ei *escapeInterpreter) dropMetadataIfHandshake() {
if !strings.Contains(ei.metadata.String(), ";") {
ei.metadata.Reset()
}
}
func (ei *escapeInterpreter) outputCSI() error {
n := len(ei.csiParam)
for i := 0; i < n; {
+17
View File
@@ -314,6 +314,23 @@ func TestDiffLineContentsOfWrappedLine(t *testing.T) {
}
}
func TestDiffLineContentsSwallowsHandshake(t *testing.T) {
v := NewView("name", 0, 0, 80, 10, OutputNormal)
// A diff renderer announces itself with a version-only record before the
// diff. It must leave no trace: no visible bytes, no line of its own, and
// above all no record on the line that follows it.
v.writeString(osc1717("1") + strings.Join([]string{
"diff --git a/foo.txt b/foo.txt",
osc1717("1;a;1;;foo.txt") + "added",
}, "\n"))
assert.Equal(t, []DiffLineContent{
{Text: "diff --git a/foo.txt b/foo.txt"},
{Text: "added", Metadata: []string{"1;a;1;;foo.txt"}},
}, v.DiffLineContents())
}
// An async re-render builds into an off-screen buffer and swaps it in once it
// has enough to paint, so readers keep seeing the previous render — coherent and
// consistent — until the new content appears in one step. See View.offscreen.