Skip to content

[Diff] Add the external diff pager package - #51

Merged
KCaverly merged 1 commit into
mainfrom
ct/diff_view/ecdcdaf3
Jul 28, 2026
Merged

[Diff] Add the external diff pager package#51
KCaverly merged 1 commit into
mainfrom
ct/diff_view/ecdcdaf3

Conversation

@KCaverly

@KCaverly KCaverly commented Jul 26, 2026

Copy link
Copy Markdown
Owner

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


Stack (bottom → top):

  1. [Diff] Add the external diff pager package #51 ← this PR
  2. [Diff] Thread the [diff] config through the viewer and zoom with z #49
  3. [Docs] Document the diff viewer settings #53

@KCaverly
KCaverly force-pushed the ct/diff_view/6ff42d48 branch from 83c8655 to 7309fed Compare July 26, 2026 19:24
@KCaverly
KCaverly force-pushed the ct/diff_view/ecdcdaf3 branch from bf58975 to f171fc0 Compare July 26, 2026 19:24
@KCaverly
KCaverly force-pushed the ct/diff_view/6ff42d48 branch from 7309fed to ad1aca8 Compare July 26, 2026 19:30
@KCaverly
KCaverly force-pushed the ct/diff_view/ecdcdaf3 branch from f171fc0 to 22ec827 Compare July 26, 2026 19:31
@KCaverly
KCaverly force-pushed the ct/diff_view/6ff42d48 branch from ad1aca8 to 53a423d Compare July 26, 2026 19:34
@KCaverly
KCaverly force-pushed the ct/diff_view/ecdcdaf3 branch from 22ec827 to 28be7c0 Compare July 26, 2026 19:34
@KCaverly
KCaverly force-pushed the ct/diff_view/6ff42d48 branch from 53a423d to 136b45f Compare July 26, 2026 19:40
@KCaverly
KCaverly force-pushed the ct/diff_view/ecdcdaf3 branch from 28be7c0 to e95e5f5 Compare July 26, 2026 19:40
@KCaverly
KCaverly force-pushed the ct/diff_view/6ff42d48 branch from 136b45f to ca09a8e Compare July 26, 2026 19:41
@KCaverly
KCaverly force-pushed the ct/diff_view/ecdcdaf3 branch from e95e5f5 to a8efe62 Compare July 26, 2026 19:41
@KCaverly
KCaverly force-pushed the ct/diff_view/6ff42d48 branch from ca09a8e to 9aefdf5 Compare July 26, 2026 20:27
@KCaverly
KCaverly force-pushed the ct/diff_view/ecdcdaf3 branch from a8efe62 to 73c72f3 Compare July 26, 2026 20:27
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
@KCaverly
KCaverly changed the base branch from ct/diff_view/6ff42d48 to main July 26, 2026 20:32
@KCaverly
KCaverly force-pushed the ct/diff_view/ecdcdaf3 branch from 73c72f3 to 327de85 Compare July 26, 2026 20:32
@KCaverly
KCaverly merged commit 0d1aa5c into main Jul 28, 2026
2 checks passed
@KCaverly
KCaverly deleted the ct/diff_view/ecdcdaf3 branch July 28, 2026 04:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant