Skip to content

feat(diff): add unified/side-by-side diff view with XDG preferences - #13

Merged
jfyne merged 6 commits into
masterfrom
worktree-diff-options
Mar 9, 2026
Merged

feat(diff): add unified/side-by-side diff view with XDG preferences#13
jfyne merged 6 commits into
masterfrom
worktree-diff-options

Conversation

@jfyne

@jfyne jfyne commented Mar 9, 2026

Copy link
Copy Markdown
Owner

What's changed

Adds switchable unified/side-by-side diff view with DiffFormat type and buildViewDiffSplit pairing algorithm, enables commenting on deleted (old) lines via Comment.Side field, changes diff background to black, and replaces localStorage with server-side XDG preference storage for diff format and sidebar width.

Requirements

Functional Requirements (EARS notation):

  • When the user clicks the diff format toggle, the system shall switch between unified and side-by-side diff views
  • While in side-by-side mode, the system shall display old lines on the left and new lines on the right, paired by position within each hunk
  • When the user selects a diff format, the system shall persist the choice
  • When the application loads, the system shall restore the diff format preference
  • While viewing a diff in either format, the system shall allow clicking on both old (deleted) and new (added) lines to create comments
  • The diff code area background shall be black (#000000)
  • If the user is not in diff mode, then the diff format toggle shall be hidden

Acceptance Criteria:

Feature: Diff view options

  Scenario: Toggle between unified and side-by-side diff view
    Given the user is viewing a diff
    When the user clicks the diff format toggle button
    Then the view switches from unified to side-by-side (or vice versa)
    And the toggle button shows an active state when in side-by-side mode

  Scenario: Diff format preference persists across sessions
    Given the user has selected side-by-side diff format
    When the user closes and reopens the tool
    Then the diff view loads in side-by-side format

  Scenario: Side-by-side view pairs old and new lines correctly
    Given a diff hunk with 2 deleted lines followed by 3 added lines
    When the view is in side-by-side mode
    Then the first 2 rows show del on the left and add on the right
    And the 3rd row shows an empty left cell and add on the right

  Scenario: Context lines appear on both sides
    Given a diff hunk with context lines
    When the view is in side-by-side mode
    Then context lines appear on both the left and right sides with matching line numbers

  Scenario: Comment on a deleted line in unified view
    Given the user is viewing a diff in unified mode
    When the user clicks on a deleted line
    Then the line is selected and a comment form appears
    And the comment is anchored to the old-side line number

  Scenario: Comment on a deleted line in side-by-side view
    Given the user is viewing a diff in side-by-side mode
    When the user clicks on a deleted line in the left column
    Then the line is selected and a comment form appears
    And the comment is anchored to the old-side line number

  Scenario: Side-by-side comments on old vs new lines with same number
    Given a comment exists on old line 5 (deleted) and another on new line 5 (added)
    When viewing in side-by-side mode
    Then the old-line comment appears in the left column
    And the new-line comment appears in the right column
    And they do not cross-contaminate

  Scenario: Side-by-side view renders hunk headers full-width
    Given a diff with multiple hunks
    When the view is in side-by-side mode
    Then hunk headers span the full width of both columns

  Scenario: Side-by-side view with syntax highlighting
    Given syntax highlighting is enabled
    When the view is in side-by-side mode
    Then both left and right columns render syntax-highlighted code

  Scenario: Diff format toggle hidden in file mode
    Given the user is viewing a plain file (not a diff)
    Then the diff format toggle button is not visible

  Scenario: Diff area background is black
    Given the user is viewing a diff
    Then the diff code area background is black (#000000)
    And the sidebar and other panels retain their original background

Suggested review order

# File What it does Link
1 template.html HTML template — toggle button, split view block, old-line attributes, JS click handlers, sidebar resize events View
2 styles.css CSS — diff background, side-by-side grid layout, pre-wrap wrapping, diff-inner wrapper, intensified add/del colors View
3 app.go Event handlers — toggle-diff-format, save-sidebar-width, updated select-line/add-comment/cancel-comment for old-line support View
4 view.go View builders — buildViewDiffSplit pairing algorithm, side-aware projectLineComments, updateDiffView format dispatch View
5 model.go Data types — DiffFormat, ViewDiffSide/ViewDiffRow/ViewDiffSplitHunk, Comment.Side, SelectionSide, SidebarWidth View
6 preferences.go XDG-based preference persistence — load/save preferences.json for diff format and sidebar width View
7 go.mod Adds github.com/adrg/xdg dependency View
8 diff_format_test.go Tests for DiffFormat constants and diffOldLineExists View
9 side_comment_test.go Tests for side-aware projectLineComments and Comment.Side JSON marshaling View
10 view_diff_test.go Tests for buildViewDiff old-line selection and commenting View
11 view_diff_split_test.go Tests for buildViewDiffSplit pairing — context lines, del/add blocks, selection, comments, hunk headers View
12 diff_format_view_test.go Tests for updateDiffView dispatch, toggle selection clearing, template render tests View
13 comment_test.go Updated call site for 5-arg projectLineComments View
14 diff-view-options.md Implementation plan document View
15 2026-03-09-diff-view-options.md Research document View

jfyne added 4 commits March 9, 2026 10:02
…ences and black background

- Add DiffFormat type with unified/split modes, toggle via toggle-diff-format event
- Implement side-by-side view builder (buildViewDiffSplit) with del/add pairing algorithm
- Enable commenting on deleted (old) lines in both unified and split views
- Add Comment.Side field for old vs new line disambiguation
- Persist diff format preference to localStorage across sessions
- Change diff area background from var(--panel) to #000000
- Add side-by-side CSS layout with grid-based left/right columns
- Update JS click handler to support old-line selection via data-old-line attribute
Replace localStorage with server-side preference storage using XDG config directory. Sidebar width and diff view format are now persisted across sessions and survive port changes.

Changes:
- Add xdg library for proper config directory selection (respects XDG_CONFIG_HOME)
- Create preferences.json at ~/.config/meatcheck/preferences.json
- Persist diff format (unified/split) and sidebar width on change
- Remove localStorage entirely (sidebar restore, diff format restore, diff format save)
- Add save-sidebar-width event handler to capture resize on mouseup
- Set initial sidebar width via inline style (server-rendered)

Layout improvements:
- Fix grid alignment: change from max-content to 1fr with pre-wrap text wrapping
- Add .diff-inner wrapper for consistent line width across all diff lines
- Constrain split view horizontally with overflow-x: hidden
- Toggle button moved to left side of header button group (first button)
@jfyne
jfyne marked this pull request as ready for review March 9, 2026 12:17
jfyne added 2 commits March 9, 2026 12:21
Apply `go fmt ./...` and `go fix ./...` to align struct field declarations and modernize for-loop syntax (range over maxLen).
@jfyne
jfyne merged commit 5e5379c into master Mar 9, 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.

1 participant