[Diff] Thread the [diff] config through the viewer and zoom with z - #49
Merged
Conversation
This was referenced Jul 26, 2026
KCaverly
force-pushed
the
ct/diff_view/995b1b40
branch
from
July 26, 2026 19:24
eb62af7 to
2e9386d
Compare
KCaverly
force-pushed
the
ct/diff_view/f8a397f5
branch
from
July 26, 2026 19:24
7cb84fd to
554a575
Compare
KCaverly
force-pushed
the
ct/diff_view/995b1b40
branch
from
July 26, 2026 19:30
2e9386d to
14f9032
Compare
KCaverly
force-pushed
the
ct/diff_view/f8a397f5
branch
from
July 26, 2026 19:30
554a575 to
efe9450
Compare
KCaverly
force-pushed
the
ct/diff_view/995b1b40
branch
from
July 26, 2026 19:34
14f9032 to
4317268
Compare
KCaverly
force-pushed
the
ct/diff_view/f8a397f5
branch
from
July 26, 2026 19:34
efe9450 to
d86f6ca
Compare
KCaverly
force-pushed
the
ct/diff_view/995b1b40
branch
from
July 26, 2026 19:39
4317268 to
19702e6
Compare
KCaverly
force-pushed
the
ct/diff_view/f8a397f5
branch
from
July 26, 2026 19:40
d86f6ca to
46c1c4c
Compare
KCaverly
force-pushed
the
ct/diff_view/995b1b40
branch
from
July 26, 2026 19:41
19702e6 to
f157ff7
Compare
KCaverly
force-pushed
the
ct/diff_view/f8a397f5
branch
from
July 26, 2026 19:41
46c1c4c to
90adf42
Compare
KCaverly
force-pushed
the
ct/diff_view/f8a397f5
branch
from
July 26, 2026 20:27
90adf42 to
25916e9
Compare
diffpager pipes each file's patch through an external formatter (delta, diff-so-fancy, bat) while ct keeps ownership of scrolling and keybindings. A zero-value Pager is inert, so the default stays ct's built-in styling. The body is split on `diff --git` boundaries and each file rendered as its own Chunk, which is what preserves the viewer's file-jump index. Headers are matched against ANSI-stripped text so a user running --color=always does not collapse the whole patch into one chunk and lose that index. Rendering is all-or-nothing: the caller's fallback is to re-render with ct's built-in styling, and a half-formatted patch would be worse than either. Chunks render concurrently under a worker cap, since a 40-file diff spawning processes serially would cost 40x a single process's latency on the fetch path. A 30s timeout bounds the whole call so a formatter that hangs cannot strand the fetch goroutine, and the first failure cancels the rest rather than waiting out the budget. cmd.Dir is set to the repo so a formatter reading .gitattributes or git config sees the right repo, and COLUMNS is set because several formatters size their output from it when stdout is not a terminal — which, piped into a Builder, it never is. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> ct-stack-id: ecdcdaf3
Three changes that cannot build apart, so they land as one: repo.DiffOptions
changes the signature of every diff call, the viewer supplies those options and
reads cfg.Diff.Pager, and the config that defines them is exercised by tests
calling the viewer's own m.diffOptions() and m.diffPager(). Any split leaves an
intermediate commit that does not compile.
repo: adds repo.DiffOptions, threading the user's extra git diff flags and
exclude pathspecs in from config rather than reading config here - repo stays
the layer that only talks to git, and these functions stay testable without a
settings file. Args land after ct's pinned diffBodyFlags and before the
revisions, so a user flag wins over a pinned one. This is what makes
`--color=always` a supported override of the pinned --no-color, for feeding a
formatter that wants coloured input. --no-ext-diff stays non-negotiable:
nothing downstream can recover a patch from an external tool's output. Both
Args and Exclude apply to the --numstat calls and the untracked-file listing as
well as the patch calls, since the numstat feeds the file index and the +/-
totals in the viewer header. The zero value produces argv identical to what ct
sent before these knobs existed.
config: a [diff] section supplying args and exclude, plus a [diff.pager]
subtable naming an external formatter each file's patch is piped through.
Omitting the subtable keeps ct's built-in styling, which stays the default. A
literal {width} in the pager args is replaced with the viewer's current column
count, so a formatter can be sized to the pane.
zoom: the preview splits the width between the commit list and the diff, which
is fine for a unified patch but cramped for a side-by-side pager: two code
columns need room the list is taking. z now hides the list so the diff spans
the whole terminal, and toggles back.
Zoomed, the diff owns the keyboard whether or not it held focus - j/k scroll,
] / [ jump files, n / p step commits - so reading a full-width diff needs no
tab dance. tab has nothing to flip to and is inert; z or d bring the list back.
The header reads [zoom] diff, and the footer names z as "show list".
Because the zoomed layout is a single column, it is allowed below the
two-column minimum width: a resize down after zooming keeps showing the diff
rather than snapping back to the plain list. splitShown and stackDiffFocused
are the two predicates the renderer, key routing and wheel all share, so none
of them can disagree about whether the diff is on screen or who owns a key.
Zoom clears when the preview closes, so the next open starts in the standard
two-column layout and the open-time width guard stays coherent; it survives a
status refresh, since that leaves you reading the same view.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ct-stack-id: f8a397f5
KCaverly
force-pushed
the
ct/diff_view/f8a397f5
branch
from
July 26, 2026 20:32
25916e9 to
dad446e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The preview splits the width between the commit list and the diff, which is
fine for a unified patch but cramped for a side-by-side pager: two code
columns need room the list is taking. z now hides the list so the diff spans
the whole terminal, and toggles back.
Zoomed, the diff owns the keyboard whether or not it held focus — j/k scroll,
] / [ jump files, n / p step commits — so reading a full-width diff needs no
tab dance. tab has nothing to flip to and is inert; z or d bring the list
back. The header reads [zoom] diff, and the footer names z as "show list".
Because the zoomed layout is a single column, it is allowed below the
two-column minimum width: a resize down after zooming keeps showing the diff
rather than snapping back to the plain list. splitShown and stackDiffFocused
are the two predicates the renderer, key routing and wheel all share, so none
of them can disagree about whether the diff is on screen or who owns a key.
Zoom clears when the preview closes, so the next open starts in the standard
two-column layout and the open-time width guard stays coherent; it survives a
status refresh, since that leaves you reading the same view.
Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
Stack (bottom → top):