Skip to content

Feature idea: side-by-side (split) diff view (builds on #2997) #2998

Description

@stevenpollack

Summary

An opt-in side-by-side (split) diff view for the diff component, toggled with Shift+V, alongside the existing unified view. It's view-only and defaults to unified, so nothing changes unless you turn it on. It lives in the shared diff component, so all diff hosts (status, compare-commits, inspect-commit, file-history) get it with no host changes.

This builds on #2997 (syntax highlighting in the diff view): it reuses that PR's per-line highlight cache and change-status styling. So it's naturally a follow-up rather than a standalone change, and I wanted to check whether you'd welcome it before opening a PR.

Motivation

Unified diffs interleave -/+ lines, which can be hard to scan for edits and reflows. A side-by-side view puts the old text on the left and the new on the right, aligned, which many people find easier to read at a glance.

What it adds

  • Shift+V toggles split ⟷ unified (persisted per-repo; default unified). The command hint shows the next state ("Split view" / "Unified view").
  • View-only: staging and hunk-jumping stay unified-only; movement, copy, edit, and syntax highlighting work in both. Deletions align on the left, additions on the right (paired by position); context and hunk headers span both columns.
  • Reuses existing data: a small pure build_split_rows(&FileDiff) state machine over the existing FileDiff; the syntax-highlight cache from Syntax highlighting in the diff view #2997 maps for free (left cell → old side, right → new). No new dependencies.
  • Narrow-terminal fallback (a centered hint below a minimum column width); binary/empty diffs fall back to unified.

Dependency on #2997 (heads-up)

Split reuses the syntax-highlight machinery from #2997 (diff_highlight cache, DiffHighlightStyle tint, a shared span-clipping helper), so it applies cleanly on top of #2997 but not on master alone. If you're open to the feature, the natural options are: (a) I open it as a follow-up PR once #2997 merges, (b) I stack it on #2997, or (c) fold it into #2997 — whichever you prefer.

Status

Implemented on my fork; make check is green (fmt + clippy --all-features + nextest + tombi + deny; 343 tests, incl. 12 new for the row-alignment model). Defaulting to unified keeps the snapshot tests unchanged. Happy to open the PR in whatever form suits you.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions