From 9fa207e8e2b28aed8d458916f815669bf31f23fa Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Sun, 9 Aug 2026 15:24:29 +0200 Subject: [PATCH] Ask diff renderers for OSC 1717 metadata MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A renderer that speaks the protocol emits nothing unless it is asked to, so that its output stays plain wherever it is used outside lazygit. The variable names the versions we understand. git is one of the renderers we ask. It has no pager to spawn, and so no terminal to spawn one in, but it still renders the diff itself — for the word-diff formats, whose markup nothing else could resolve — so the request has to be made before we decide a pty isn't needed. Co-authored-by: Claude Opus 5 (1M context) --- pkg/gui/main_view_render.go | 10 ++++ .../tests/diff/diff_renderer_metadata.go | 50 +++++++++++++++++++ pkg/integration/tests/test_list.go | 1 + 3 files changed, 61 insertions(+) create mode 100644 pkg/integration/tests/diff/diff_renderer_metadata.go diff --git a/pkg/gui/main_view_render.go b/pkg/gui/main_view_render.go index fdaf73798..7b9b75c23 100644 --- a/pkg/gui/main_view_render.go +++ b/pkg/gui/main_view_render.go @@ -36,6 +36,16 @@ type renderSpec struct { // user has configured. The renderer lays its rendering out to the width of the // view, which only the layout settles, so the task is created after it. func (gui *Gui) newRenderTask(view *gocui.View, cmd *exec.Cmd, prefix string) error { + // Ask whatever renders the diff to state, in an OSC 1717 record per line, + // which line of which file it is rendering. This lets us act on the line the + // user is pointing at even when the rendering no longer looks like a diff. + // The variable names the protocol versions we understand, and a renderer + // that doesn't understand it ignores it, so we can set it always. It has to + // be set before the plain path below, since on that path git renders the + // diff itself, and git speaks the protocol too, for its word-diff formats, + // whose markup we could not otherwise resolve. + cmd.Env = append(cmd.Env, "OSC1717=V1") + if gui.stateAccessor.GetDiffRendererConfigManager().GetDiffRendererType() == config.DiffRendererType_RawGit { // If we're not using a custom diff renderer, then we don't need to use a pty return gui.newCmdTask(view, cmd, prefix) diff --git a/pkg/integration/tests/diff/diff_renderer_metadata.go b/pkg/integration/tests/diff/diff_renderer_metadata.go new file mode 100644 index 000000000..ff211717d --- /dev/null +++ b/pkg/integration/tests/diff/diff_renderer_metadata.go @@ -0,0 +1,50 @@ +package diff + +import ( + "github.com/jesseduffield/lazygit/pkg/config" + . "github.com/jesseduffield/lazygit/pkg/integration/components" +) + +var DiffRendererMetadata = NewIntegrationTest(NewIntegrationTestArgs{ + Description: "A diff renderer is told that we understand the OSC 1717 metadata protocol, and the records it emits don't show up in the rendered diff", + ExtraCmdArgs: []string{}, + Skip: false, + SetupConfig: func(cfg *config.AppConfig) { + // A fake conforming renderer: it announces the protocol with a + // version-only record, reports the protocol versions it was offered, and + // then passes the diff through with a per-line record in front of every + // line. + cfg.GetUserConfig().Git.DiffRenderers = []config.DiffRendererConfig{ + {Command: `printf '\033]1717;1\007'; ` + + `printf 'OFFERED:%s\n' "$OSC1717"; ` + + `while IFS= read -r line; do printf '\033]1717;1;c;1;;file1\007%s\n' "$line"; done`}, + } + }, + SetupRepo: func(shell *Shell) { + shell.CreateFileAndAdd("file1", "one\ntwo\n") + shell.Commit("one") + }, + Run: func(t *TestDriver, keys config.KeybindingConfig) { + t.Views().Commits(). + Focus(). + Lines( + Contains("one").IsSelected(), + ) + + t.Views().Main(). + // The renderer was offered the protocol version we understand. + Content(Contains("OFFERED:V1")). + // Its records are escape sequences, so none of them reaches the + // screen; the diff reads exactly as the renderer wrote it. + ContainsLines( + Equals("diff --git a/file1 b/file1"), + Contains("new file mode"), + Contains("index "), + Equals("--- /dev/null"), + Equals("+++ b/file1"), + Equals("@@ -0,0 +1,2 @@"), + Equals("+one"), + Equals("+two"), + ) + }, +}) diff --git a/pkg/integration/tests/test_list.go b/pkg/integration/tests/test_list.go index 67caf3bbb..d699d8cb6 100644 --- a/pkg/integration/tests/test_list.go +++ b/pkg/integration/tests/test_list.go @@ -228,6 +228,7 @@ var tests = []*components.IntegrationTest{ diff.DiffAndApplyPatch, diff.DiffCommits, diff.DiffNonStickyRange, + diff.DiffRendererMetadata, diff.IgnoreWhitespace, diff.RenameSimilarityThresholdChange, diff.RenderThroughAPipe,