Lay a diffstat out to the width of the view showing it

Tell a command that renders into a view how wide that view is, through
COLUMNS. git reads it in preference to the size of the terminal it is
talking to, so the diffstat now fills the view whether or not the render
has a terminal to offer.

A diff renderer that can't ask a terminal gets the width from it too;
difftastic, diff-so-fancy and delta all support COLUMNS, so we can stop
running git in a PTY and these will still work.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Stefan Haller
2026-09-25 11:31:59 +02:00
co-authored by Claude Opus 5
parent c217a899ee
commit a51952d826
2 changed files with 11 additions and 3 deletions
+11
View File
@@ -112,6 +112,8 @@ type runRender func(spec renderSpec) (startRender, onCloseRender)
// view, running the command the given way. key names what is rendered, so that
// a re-render of the same content can be told from a render of other content.
func (gui *Gui) newTaskForRender(spec renderSpec, prefix string, key string, run runRender) error {
setColumnsEnvVar(spec.cmd, spec.width)
start, onClose := run(spec)
manager := gui.getManager(spec.view)
@@ -119,6 +121,15 @@ func (gui *Gui) newTaskForRender(spec renderSpec, prefix string, key string, run
return manager.NewTask(manager.NewCmdTask(start, prefix, linesToRead, onClose), key)
}
// setColumnsEnvVar tells a command how wide the view its output goes into is.
// git reads COLUMNS in preference to the size of the terminal it is talking to,
// and lays the diffstat graph out to it; a diff renderer with no terminal to
// ask may read it too (difftastic and diff-so-fancy do, delta does not). A
// command told nothing renders for 80 columns.
func setColumnsEnvVar(cmd *exec.Cmd, width int) {
cmd.Env = append(cmd.Env, fmt.Sprintf("COLUMNS=%d", width))
}
func removeExistingTermEnvVars(env []string) []string {
return lo.Filter(env, func(envVar string, _ int) bool {
return !isTermEnvVar(envVar)
@@ -37,9 +37,6 @@ var StatUsesTheViewWidth = NewIntegrationTest(NewIntegrationTestArgs{
)
t.Views().Main().
/* EXPECTED:
Content(MatchesRegexp(`(?m)^ file1 \| 200 \+{80,}$`))
ACTUAL: */
Content(MatchesRegexp(`(?m)^ file1 \| 200 \+{60,70}$`))
},
})