Skip to content

Add diffHunkHeaders + diffLineNumberStyle for mobile/minimal renderers#10

Merged
tornikegomareli merged 1 commit into
mainfrom
feat/hunk-header-and-line-number-style
May 13, 2026
Merged

Add diffHunkHeaders + diffLineNumberStyle for mobile/minimal renderers#10
tornikegomareli merged 1 commit into
mainfrom
feat/hunk-header-and-line-number-style

Conversation

@tornikegomareli
Copy link
Copy Markdown
Owner

@tornikegomareli tornikegomareli commented May 13, 2026

Summary

  • New DiffConfiguration.LineNumberStyle = .hidden | .single | .dual, default .dual (no behaviour change for existing callers).
  • New .diffLineNumberStyle(_:) view modifier for the new gutter modes. .single shows one column — new line number on +/context, old line number on - — matching how git diff --color and terminal renderers handle narrow space.
  • New showHunkHeaders: Bool (default true) + .diffHunkHeaders(_:) modifier mirroring the existing .diffFileHeaders(_:) toggle.
  • New .mobile preset bundles .single + hidden hunk headers + compact spacing.

Why

On a phone, the existing .dual gutter renders every context line as 19 19 / 20 20 / etc. — visually duplicated, hard to scan at small sizes. The hunk header @@ -17,10 +17,18 @@ adds another line of low-signal text. Together they crowd out the actual code change. Pi-remote-control is shipping its first mobile diff review surface; this PR unblocks the right minimal-mobile rendering without forking.

Usage

```swift
DiffRenderer(diffText: text)
.diffLineNumberStyle(.single)
.diffHunkHeaders(false)
.diffTheme(.dark)

// or
DiffRenderer(diffText: text)
.diffConfiguration(.mobile)
```

Implementation notes

  • showLineNumbers: Bool stays as a stored property and stays accepted by the legacy init / modifier. When the legacy flag is false we map to .hidden; when true we map to .dual — so any existing call site stays pixel-identical.
  • All other with* builders forward the new fields. The remaining "old" View.diffXxx modifiers (.diffTheme, .diffFont, .diffLineSpacing, .diffWordWrap) were manually re-instantiating DiffConfiguration and would have silently reset the new fields when chained after .diffLineNumberStyle / .diffHunkHeaders. Switched them to the existing .with* builders.

Test plan

  • `swift build` clean
  • `swift test` — 21/21 pass, including 10 new `DiffConfigurationTests` (default values, legacy → new inference, explicit-style-overrides-legacy, hunk-header toggle, chaining preserves new fields, .mobile preset).
  • Existing `DiffParserTests` and `DiffParsingTests` still pass unchanged.
  • Source-compatible — every existing call site keeps working without edits.

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Added .diffLineNumberStyle(_:) modifier supporting hidden, single, and dual line-number display options.
    • Added .diffHunkHeaders(_:) modifier to toggle hunk-header visibility.
    • Introduced .mobile preset configuration with optimized defaults for mobile viewing.
  • Documentation

    • Marked .diffLineNumbers(_:) as legacy; use .diffLineNumberStyle(_:) instead.

Review Change Stack

The library renders a side-by-side `old | new` gutter and an
`@@ -a,b +c,d @@` separator above every hunk. Both are right for
desktop unified-diff review and wrong for narrow viewports — on a
phone every context line shows the same number twice (e.g. `19 19`,
`20 20`) which reads as noise, and the hunk header eats screen space
without adding signal beyond what the surrounding chrome (file name,
stats badge) already conveys.

This adds two opt-in knobs that leave today's behaviour unchanged:

- `DiffConfiguration.LineNumberStyle = .hidden | .single | .dual`,
  default `.dual`. `.single` shows one column with the new line
  number for added/context and the old line number for removed —
  matching how `git diff --color` and most terminal renderers
  present a compact gutter.
- `.diffLineNumberStyle(_:)` view modifier sets it explicitly. The
  legacy `.diffLineNumbers(_:Bool)` modifier and the legacy
  `showLineNumbers: Bool` init parameter still work: `true` → `.dual`,
  `false` → `.hidden`.
- `showHunkHeaders: Bool`, default `true`, exposed via
  `.diffHunkHeaders(_:)`. Mirrors the existing
  `.diffFileHeaders(_:)` modifier.
- New `.mobile` preset bundles `.single` + hidden hunk headers +
  compact font/spacing for a sensible mobile default.

The existing modifiers (`.diffTheme`, `.diffFont`, `.diffLineSpacing`,
`.diffWordWrap`) were each manually re-instantiating
`DiffConfiguration` with the old field set — that would have silently
reset the new fields whenever chained after `.diffLineNumberStyle` /
`.diffHunkHeaders`. Switched them to the existing `.with*` builders
so every field flows through unchanged.

10 new tests cover field inference (legacy → new), the new
modifiers, the `.mobile` preset, and that chaining other modifiers
preserves the new fields. 21/21 passing total (was 11).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 13, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 53d40b4a-2bf1-4087-8e5b-b4688b12fdf5

📥 Commits

Reviewing files that changed from the base of the PR and between bb75a93 and 00c09df.

📒 Files selected for processing (7)
  • README.md
  • Sources/gitdiff/DiffConfiguration.swift
  • Sources/gitdiff/DiffConfigurationBuilder.swift
  • Sources/gitdiff/DiffEnvironment.swift
  • Sources/gitdiff/Views/DiffFileView.swift
  • Sources/gitdiff/Views/DiffLineView.swift
  • Tests/gitdiffTests/DiffConfigurationTests.swift

📝 Walkthrough

Walkthrough

This PR introduces a refined line-number rendering system and hunk header visibility control for diffs. It replaces the boolean showLineNumbers API with a three-mode LineNumberStyle enum, adds a showHunkHeaders configuration flag, updates all builder and View modifier chains to preserve these settings, and refactors view rendering to support single-column and hidden line numbers alongside the existing dual mode.

Changes

Line number styles and hunk header visibility

Layer / File(s) Summary
Configuration contract and data model
Sources/gitdiff/DiffConfiguration.swift
LineNumberStyle enum (hidden/single/dual) and DiffConfiguration properties for lineNumberStyle and showHunkHeaders are added. The initializer computes lineNumberStyle from the legacy showLineNumbers boolean when not explicitly provided.
Builder method implementation
Sources/gitdiff/DiffConfigurationBuilder.swift
New withLineNumberStyle(_:) builder method and updates to all existing builder methods (withLineNumbers, withFont, withLineSpacing, withFileHeaders, withHunkHeaders, withWordWrap) to forward and derive the new configuration fields. Mobile and presentation presets are updated.
SwiftUI environment modifier refactoring
Sources/gitdiff/DiffEnvironment.swift
View modifiers now use transformEnvironment with builder methods instead of reconstructing DiffConfiguration inline. New diffHunkHeaders(_:) modifier is introduced alongside existing modifiers.
View rendering with new line number styles and hunk headers
Sources/gitdiff/Views/DiffFileView.swift, Sources/gitdiff/Views/DiffLineView.swift
DiffFileView conditionally renders hunk headers based on showHunkHeaders. DiffLineView adds singleColumnLineNumber computed property and switches on lineNumberStyle to render appropriate line number styles.
Comprehensive configuration tests
Tests/gitdiffTests/DiffConfigurationTests.swift
New test suite verifies lineNumberStyle defaults, legacy-to-new inference, explicit precedence, builder method field preservation, hunk header toggling, and mobile preset configuration.
README documentation updates
README.md
Modifiers section documents new diffLineNumberStyle(_:) and diffHunkHeaders(_:), marks diffLineNumbers(_:) as legacy, and adds Mobile-friendly defaults subsection with recommended configuration.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A diff now wears three styles of line—
Hidden, single, or dual design,
Hunk headers toggle on and off with grace,
Mobile defaults find their place!
Configuration builders chain so clean—
The finest diff renderer ever seen! 🎨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 77.78% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main changes: adding two new modifiers (diffHunkHeaders and diffLineNumberStyle) designed for mobile/minimal diff renderers.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/hunk-header-and-line-number-style

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@tornikegomareli tornikegomareli merged commit 114b571 into main May 13, 2026
2 checks 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.

1 participant