From ec3427fdcc7dfed7b938fee1ab34c12a2dc2516a Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Tue, 15 Sep 2026 17:33:05 +0200 Subject: [PATCH] Let an external diff command be told the width it renders at Like a stdin filter, an external diff program lays out its rendering to the width it reads off the terminal, and a render through a pipe leaves it nothing to read. difftastic in side-by-side mode is the case that shows it. Offer the width as the {{width}} template variable, the same name the stdin filter command takes it by. Since difftastic supports the COLUMNS variable, which we will set later in this branch, and I don't know of any other external-diff renderer that doesn't, we don't document this. Co-Authored-By: Claude Opus 5 (1M context) --- pkg/config/diff_renderer_config_manager.go | 3 +- .../diff_renderer_config_manager_test.go | 39 +++++++++++++++++++ pkg/gui/pty.go | 2 +- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/pkg/config/diff_renderer_config_manager.go b/pkg/config/diff_renderer_config_manager.go index 8859394d3..80dee5830 100644 --- a/pkg/config/diff_renderer_config_manager.go +++ b/pkg/config/diff_renderer_config_manager.go @@ -88,7 +88,7 @@ func (self *DiffRendererConfigManager) GetColorArg() string { return colorArg } -func (self *DiffRendererConfigManager) GetExternalDiffCommand(diffContext uint64) string { +func (self *DiffRendererConfigManager) GetExternalDiffCommand(diffContext uint64, width int) string { currentDiffRendererConfig := self.currentDiffRendererConfig() if currentDiffRendererConfig == nil || currentDiffRendererConfig.getType() != DiffRendererType_ExtDiff { return "" @@ -96,6 +96,7 @@ func (self *DiffRendererConfigManager) GetExternalDiffCommand(diffContext uint64 templateValues := map[string]string{ "diffContext": strconv.Itoa(int(diffContext)), + "width": strconv.Itoa(width), } return utils.ResolvePlaceholderString(string(currentDiffRendererConfig.Command), templateValues) diff --git a/pkg/config/diff_renderer_config_manager_test.go b/pkg/config/diff_renderer_config_manager_test.go index 9c805b152..e2d4a8e44 100644 --- a/pkg/config/diff_renderer_config_manager_test.go +++ b/pkg/config/diff_renderer_config_manager_test.go @@ -113,6 +113,45 @@ func TestGetStdinFilterCommand(t *testing.T) { } } +func TestGetExternalDiffCommand(t *testing.T) { + scenarios := []struct { + name string + diffRendererConfig DiffRendererConfig + expected string + }{ + { + name: "a command without template variables is passed through", + diffRendererConfig: DiffRendererConfig{Type: "extDiff", Command: "difft --color=always"}, + expected: "difft --color=always", + }, + { + name: "the width the diff is rendered at", + diffRendererConfig: DiffRendererConfig{Type: "extDiff", Command: "difft --width={{width}}"}, + expected: "difft --width=120", + }, + { + name: "the width alongside the diff context size", + diffRendererConfig: DiffRendererConfig{Type: "extDiff", Command: "difft --width={{width}} --context={{diffContext}}"}, + expected: "difft --width=120 --context=3", + }, + { + name: "nothing is returned for a renderer of another type", + diffRendererConfig: DiffRendererConfig{Command: "delta --width={{width}}"}, + expected: "", + }, + } + + for _, s := range scenarios { + t.Run(s.name, func(t *testing.T) { + userConfig := &UserConfig{} + userConfig.Git.DiffRenderers = []DiffRendererConfig{s.diffRendererConfig} + config := NewDiffRendererConfigManager(func() *UserConfig { return userConfig }) + + assert.Equal(t, s.expected, config.GetExternalDiffCommand(3, 120)) + }) + } +} + func TestCurrentDiffRendererNameWithoutDiffRenderers(t *testing.T) { config := NewDiffRendererConfigManager(func() *UserConfig { return &UserConfig{} }) diff --git a/pkg/gui/pty.go b/pkg/gui/pty.go index a7ef22d8e..edf03b7ef 100644 --- a/pkg/gui/pty.go +++ b/pkg/gui/pty.go @@ -89,7 +89,7 @@ func (gui *Gui) newPtyTask(view *gocui.View, cmd *exec.Cmd, prefix string) error width = view.InnerWidth() diffRendererConfigManager := gui.stateAccessor.GetDiffRendererConfigManager() pager := diffRendererConfigManager.GetStdinFilterCommand(width) - externalDiff := diffRendererConfigManager.GetExternalDiffCommand(gui.c.UserConfig().Git.DiffContextSize) + externalDiff := diffRendererConfigManager.GetExternalDiffCommand(gui.c.UserConfig().Git.DiffContextSize, width) cmdStr := strings.Join(cmd.Args, " ")