Skip to content

Add external diff renderer support - #365

Merged
kahole merged 2 commits into
kahole:developfrom
dandavison:diff-renderer
Sep 13, 2026
Merged

kahole merged 2 commits into
kahole:developfrom
dandavison:diff-renderer

Conversation

@dandavison

@dandavison dandavison commented Sep 12, 2026 •

Copy link
Copy Markdown
Contributor

AI-written PR I haven't reviewed this carefully. But I have used it quite a lot. Opening nevertheless, as discussed. Please feel free to push fixup / cleanup commits to this branch.

Makes it possible to use an external tool such as delta to add colors to diffs displayed by edamagit.

image

Settings:

  • magit.use-diff-renderer: enable/disable (disabled by default)
  • magit.diff-renderer-command: full command array (default: an appropriate delta command)

Known issue

  • I think there's a fairly rare race somehere. Sometimes the colors from the external renderer are not there on first draw; in that situation they appear on folding/unfolding.

AI-written commit message

Pipe diffs through a user-configured external command (e.g. delta) to get ANSI-colored output, parse it with ansi-sequence-parser, and apply the results as VS Code text decorations on magit diff views.

New modules:

  • diffRenderer: spawns the diff renderer subprocess, parses ANSI tokens into DecorationRange structs
  • diffDecorations: reassembles per-file diffs with headers, runs them through the renderer, and maps renderer line numbers back to document positions via hunk view ranges
  • diffWiring: manages decoration lifecycle (create, dispose, refresh); walks only visible (unfolded) hunk views; uses a generation counter to handle racing refreshDecorations calls; registers an onDidChangeTextDocument listener to re-apply decorations on fold toggles and status refreshes

Pipe diffs through a user-configured external command (e.g. delta) to
get ANSI-colored output, parse it with ansi-sequence-parser, and apply
the results as VS Code text decorations on magit diff views.

New modules:
- diffRenderer: spawns the diff renderer subprocess, parses ANSI tokens
  into DecorationRange structs
- diffDecorations: reassembles per-file diffs with headers, runs them
  through the renderer, and maps renderer line numbers back to
  document positions via hunk view ranges
- diffWiring: manages decoration lifecycle (create, dispose, refresh);
  walks only visible (unfolded) hunk views; uses a generation counter
  to handle racing refreshDecorations calls; registers an
  onDidChangeTextDocument listener to re-apply decorations on fold
  toggles and status refreshes

Settings (off by default):
- magit.use-diff-renderer: enable/disable
- magit.diff-renderer-command: full command array (default: delta)
Split on /^diff --git /m instead of the bare substring, since git
only emits that token at the start of a diff header line — plain
substring matching over-splits when file content contains the same
text (e.g. sample diffs embedded in test fixtures).

Run with: npm run test-compile && npx vscode-test --grep "diffing commands"

Add repro test for stashToMagitChanges diff-header splitting

A diff whose added/modified file content itself contains a literal
"diff --git a/..." line (e.g. a test fixture with a sample diff)
causes stashToMagitChanges to over-split on that substring, so the
computed change count no longer matches --name-status and the
function returns [] — silently blanking commit/stash detail views.
@kahole
kahole merged commit a981b7d into kahole:develop Sep 13, 2026
1 check passed
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.

2 participants