mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-09-11 16:16:28 -04:00
gocui: swallow the version-only diff-metadata handshake OSC
A metadata-aware pager emits a version-only OSC 1717 record (no fields) as its first output, to announce it speaks the diff-line-metadata protocol so lazygit can probe for it. It isn't per-line metadata, so on a real render it must be swallowed whole rather than lingering in the accumulator and attaching to the following diff-header line (or, if newline-terminated, producing a phantom blank line). Drop any OSC 1717 payload with no fields at its terminator; per-line payloads always have fields, so they're kept. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f3ef02556a
commit
c0ee7de776
|
|
@ -485,8 +485,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)
|
||||
|
|
@ -507,6 +509,18 @@ func (ei *escapeInterpreter) parseOne(ch []byte) (isEscape bool, err error) {
|
|||
return false, nil
|
||||
}
|
||||
|
||||
// dropMetadataIfHandshake discards a just-completed OSC 1717 payload that carries no
|
||||
// fields (no ';'). A metadata-aware pager emits such a version-only record once, as
|
||||
// its first output, to announce it speaks the protocol (so we can probe it; see the
|
||||
// raw-diff fallback in the lazygit staging helper). It isn't per-line metadata, so it
|
||||
// must not linger in the accumulator and attach to the following line. Per-line
|
||||
// payloads always have fields, so they're 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; {
|
||||
|
|
|
|||
|
|
@ -217,6 +217,42 @@ func TestDiffLineMetadataPayloads(t *testing.T) {
|
|||
}, v.DiffLineMetadataPayloads())
|
||||
}
|
||||
|
||||
func TestDiffLineMetadataHandshakeSwallowed(t *testing.T) {
|
||||
v := NewView("name", 0, 0, 80, 10, OutputNormal)
|
||||
|
||||
// A metadata-aware pager emits a version-only handshake (an OSC 1717 with no
|
||||
// fields) as its first output, immediately before the diff, to announce it speaks
|
||||
// the protocol. It must be swallowed whole: no visible bytes, no phantom line, and
|
||||
// crucially it must not attach as metadata to the diff header that follows it.
|
||||
osc := func(payload string) string { return "\x1b]1717;" + payload + "\x1b\\" }
|
||||
v.writeString(osc("1") + strings.Join([]string{
|
||||
"diff --git a/foo.txt b/foo.txt",
|
||||
osc("1;a;1;;foo.txt") + "added",
|
||||
}, "\n"))
|
||||
|
||||
// The handshake produced no phantom line and no visible bytes.
|
||||
assert.Equal(t, []string{
|
||||
"diff --git a/foo.txt b/foo.txt",
|
||||
"added",
|
||||
}, v.BufferLines())
|
||||
|
||||
// The handshake didn't bleed onto the header line, and the real per-line metadata
|
||||
// after it still applies.
|
||||
type result struct {
|
||||
payload string
|
||||
ok bool
|
||||
}
|
||||
got := make([]result, len(v.buf.lines))
|
||||
for y := range v.buf.lines {
|
||||
payload, ok := v.DiffLineMetadataInLine(y)
|
||||
got[y] = result{payload, ok}
|
||||
}
|
||||
assert.Equal(t, []result{
|
||||
{"", false},
|
||||
{"1;a;1;;foo.txt", true},
|
||||
}, got)
|
||||
}
|
||||
|
||||
// When a re-render produces fewer view lines than the previous one,
|
||||
// refreshViewLinesIfNeeded must truncate viewLines to the new content. If it
|
||||
// didn't (it used to overwrite in place and keep the tail), a reader could map a
|
||||
|
|
|
|||
Loading…
Reference in a new issue