Skip to content

Latest commit

 

History

History
464 lines (400 loc) · 21.6 KB

File metadata and controls

464 lines (400 loc) · 21.6 KB

Testing Checklist

Items marked ✅ are covered by automated UI integration tests (tests/ui_integration/).

CLI / Launch Modes

  • ✅ No arguments: launches Welcome window
  • ✅ Two file paths: opens file diff window
  • ✅ Two directory paths: opens directory comparison window
  • ✅ Three file paths: opens 3-way merge window
  • ✅ One directory (git repo): opens VCS window
  • ✅ One directory (not a git repo): prints error and exits
  • ✅ Single file path: prints error and exits
  • ✅ Non-existent path: prints error and exits
  • ✅ File + directory mix: prints error
  • ✅ File + patch file: opens patch viewing window
  • ✅ Directory + patch file: opens multi-file patch dir comparison
  • -L/--label flags: custom pane labels shown for 2-file and 3-file modes
  • --version / --help: correct output

Welcome Window

  • "Compare Files" button: two file dialogs, then opens diff; welcome closes
  • "Compare Directories" button: two folder dialogs, then opens dir window; welcome closes
  • "3-way Merge" button: three file dialogs, then opens merge; welcome closes
  • Preferences button / Ctrl+,: opens Preferences dialog
  • Ctrl+W: closes welcome window
  • Ctrl+N: opens a new welcome window
  • Cancel any file dialog: nothing happens

File Diff (2-way)

Display

  • Chunk backgrounds: blue for replace, green for insert/delete
  • Current chunk: bold dark borders when navigating
  • Inline word-level highlighting: yellow (changed), pink (deleted), green (inserted)
  • Filler lines: thin colored lines where the other side has more content
  • Gutter: curved connecting bands between panes
  • Chunk map strips: minimap of changes at far edges; clickable to jump
  • Chunk map viewport indicator: visible rectangle showing current scroll position
  • Syntax highlighting: detected from filename
  • Line numbers: shown/hidden per settings

Toolbar

  • ✅ Undo (Ctrl+Z) / Redo (Ctrl+Shift+Z): acts on last-focused pane
  • Previous change (Alt+Up / Ctrl+E): navigates to previous diff chunk
  • Next change (Alt+Down / Ctrl+D): navigates to next diff chunk
  • ✅ Chunk label: shows "N changes" or "Change X of N"
  • ✅ Go to line (Ctrl+L): entry appears; type number + Enter to jump; Escape to dismiss; focus returns to active pane
  • ✅ Blanks toggle: re-diffs ignoring blank lines
  • ✅ Spaces toggle: re-diffs ignoring whitespace
  • Apply all (⏪ button): copies all non-conflicting chunks right → left
  • Apply all: single undo operation (one Ctrl+Z reverts everything)
  • Apply all: skips chunks containing conflict markers (<<<<<<< original / >>>>>>> patch)
  • Apply all on binary files: button is disabled
  • Export patch (Ctrl+Shift+P): save dialog; generates unified diff
  • ✅ Swap panes: swaps content, labels, save paths, dirty state; title updates
  • ✅ Preferences (Ctrl+,): opens Preferences

Gutter Interactions

  • Click right arrow: copies left chunk to right
  • Click left arrow: copies right chunk to left
  • Right-click gutter: context menu with both copy options
  • Paste highlight flash: 500ms blue flash on inserted text

Scroll Sync

  • Horizontal scroll synced between panes
  • Vertical scroll synced by chunk between panes

Find / Replace

  • ✅ Ctrl+F: opens find bar; Ctrl+H: opens find + replace
  • Typing highlights all matches in both buffers; shows match count
  • Find next (F3 / Enter) / Find prev (Shift+F3): wraps around
  • F3/Shift+F3 works from find entry, replace entry, and source pane
  • ✅ Escape closes find bar from source pane (not just from find entry)
  • Replace: replaces current selection if it matches
  • Replace All: replaces in both buffers
  • Close (X / Escape): hides bar, clears highlights, returns focus to pane
  • After closing find bar, Ctrl+F / Ctrl+H work immediately

Save

  • ✅ Ctrl+S: saves focused pane; button goes insensitive
  • ✅ Save button insensitive until buffer changes
  • ✅ Save writes correct file; button goes insensitive; error dialog on failure
  • Save path tracks swaps: after swap, save writes to correct original file
  • Save after swap: pane contents and labels remain consistent (no un-swap)
  • Save after swap in dir file tab: watcher reload preserves swapped state
  • Ctrl+Shift+S (Save As): file dialog; writes to chosen path; updates pane label and tooltip
  • Save As updates tab-tracked path (close/unsaved dialog shows new name)
  • Ctrl+Shift+L (Save All): saves all dirty panes in current view
  • Ctrl+Shift+O: opens focused file in system default app
  • ✅ Ctrl+R / F5 (Refresh): reloads both files from disk
  • Refresh with unsaved changes: confirm dialog before reloading
  • Refresh on blank comparison pane: no-op (doesn't crash)

File Watcher

  • External file change: auto-reloads if no unsaved changes
  • External change while unsaved: reload skipped
  • Save suppresses reload for 600ms (no reload loop)

Close / Dialogs

  • Ctrl+W: closes window
  • Close with no unsaved changes: closes immediately
  • Close with unsaved changes: dialog with per-file checkboxes, Save/Close without Saving/Cancel
  • Save failure in dialog: window does NOT close
  • Overwrite confirm dialog: Escape key closes it
  • Ctrl+Shift+P: export patch dialog opens (sourceview doesn't consume it)

Chunk Copy (Alt+Left / Alt+Right)

  • Alt+Right on a diff chunk: copies left chunk content to right (no file copy dialog)
  • Alt+Left on a diff chunk: copies right chunk content to left (no file copy dialog)
  • Alt+Left/Right with no current chunk: nothing happens
  • In file diff tab opened from dir window: Alt+Left/Right copies chunks, does NOT trigger dir file copy

Chunk Pull (Alt+Shift+Left / Alt+Shift+Right)

  • Alt+Shift+Right: pulls content from right pane into focused pane
  • Alt+Shift+Left: pulls content from left pane into focused pane
  • Pull when focused on the same side as pull direction: no-op

Delete Change (Alt+Delete)

  • ✅ Alt+Delete: deletes the current chunk's text from the focused pane
  • Alt+Delete with no current chunk: nothing happens
  • Alt+Delete at end of buffer: removes preceding newline too

Pane Switching (Alt+PageUp / Alt+PageDown)

  • ✅ Alt+PageDown: switches focus to next pane (wraps around)
  • ✅ Alt+PageUp: switches focus to previous pane (wraps around)
  • In 3-way merge: cycles left→middle→right→left

Fullscreen (F11)

  • ✅ F11: toggles fullscreen mode
  • ✅ F11 again: exits fullscreen

Edge Cases

  • ✅ Identical files: "Files are identical" info bar; edit one side -> bar disappears; undo -> reappears
  • ✅ Binary files: info bar, panes read-only, patch button disabled, swap/nav/blanks/spaces/undo/redo buttons disabled
  • Empty files: no chunks, label shows "No changes"
  • ✅ Empty file vs non-empty file: all-insert chunks on one side
  • Very large files (10K+ lines): background diff, UI stays responsive
  • UTF-8 with multi-byte characters: inline highlighting correct
  • ✅ Files with only whitespace differences + Spaces toggle on: no differences shown
  • ✅ Files with only blank line differences + Blanks toggle on: no differences shown
  • ✅ Swap panes twice: returns to original state

Navigation

  • ✅ Alt+Up/Down: cursor moves to chunk start line
  • Click in pane, then Alt+Down: navigates from cursor position, not from top
  • Navigate chunks with cursor in different positions: cursor-aware seeking
  • Alt+Up/Down intercepted: sourceview move-lines action does not fire
  • Wrap-around navigation: Alt+Down past last chunk wraps to first (if enabled in prefs)
  • ✅ Wrap-around off: Alt+Down on last chunk stays; Alt+Up on first chunk stays

Directory Comparison

Display

  • ✅ Tree view with expandable directories
  • Columns: Name (with icon), Size, Modification time
  • Directory headers above each pane with full path as tooltip
  • Copy path button next to each header: copies full absolute path to clipboard
  • Copy path after swap: copies the swapped (current) path, not the original
  • Status colors: blue (different), orange (left-only), green (right-only), red (conflict), dim italic (missing side)

Navigation

  • ✅ Double-click file row: opens diff in new notebook tab
  • Enter on file row: opens diff in new notebook tab
  • ✅ Enter on directory row: expands/collapses folder
  • Enter after closing a file tab: still works (no broken activation state)
  • Left/Right arrow keys: switch focus between panes
  • Selection syncs between panes (highlighted on both sides)
  • Active pane: accent-color border; inactive pane: dim border + reduced opacity
  • Switching panes: no scroll jump, keyboard cursor syncs to selected row

Toolbar

  • Copy to left (Alt+Left): copies right to left; confirms if overwriting
  • Copy to right (Alt+Right): copies left to right; confirms if overwriting
  • Delete (Delete key): trashes selected file with confirmation
  • ✅ Collapse all: collapses every expanded directory row
  • ✅ Expand all: expands every directory row
  • Apply all non-conflicting (⏪ button): copies all non-conflicting files right → left
  • Apply all: confirmation dialog shows file count
  • Apply all: handles modified, new, and deleted files
  • Apply all: skips conflicting files
  • Swap panes: rescans, updates headers and window title
  • Preferences (Ctrl+,)

Context Menu

  • Right-click selects the clicked row first
  • Right-click targets correct row: select row A, right-click row B, action operates on B (not A)
  • "Open Diff": opens diff tab (disabled for directories)
  • "Copy to Left" / "Copy to Right": enabled for appropriate statuses
  • "Delete": enabled only when file exists on focused side
  • "Open Externally" / "Copy File Path": enabled only when file exists on focused side
  • Missing-side file: Copy, Delete, Open Externally, Copy Path all disabled

Notebook Tabs

  • ✅ Directory tab labeled with "dir1 — dir2"
  • File tabs labeled with dir-relative names
  • Opening file diff tab: left pane has focus, cursor at line 1
  • Tab close (X): prompts for unsaved changes
  • Ctrl+W on Directory tab: closes entire window
  • ✅ Ctrl+W on file tab: closes that tab
  • ✅ Same file not opened twice: switches to existing tab
  • ✅ Alt+1..9: switches to tab by index
  • Ctrl+N: opens New Comparison tab
  • New Comparison tab: "Compare Files" and "3-Way Merge" buttons with file choosers
  • New Comparison → Compare Files: opens diff tab, removes new-comparison tab
  • New Comparison → 3-Way Merge: opens merge tab, removes new-comparison tab
  • Blank comparison (Ctrl+T or from New Comparison): opens editable blank diff tab

File Watcher

  • Directory rescans on FS changes (500ms poll)
  • Expanded directories and selection restored after rescan
  • Open tab buffers reloaded unless unsaved

Filters

  • Filtered names (.git, node_modules, etc.) excluded from tree
  • Custom filters from preferences applied
  • Hide hidden files on (default): dotfiles excluded from tree
  • Hide hidden files off: dotfiles shown in tree

Edge Cases

  • Collapse all with missing-side files expanded: no crash
  • Deeply nested directory trees
  • Copy directory recursively: all nested files copied
  • Dir -> file tab -> swap -> edit -> save dialog shows correct filename
  • Window close with unsaved tabs: dialog lists all unsaved files

3-Way Merge

Display

  • ✅ Three panes: left (read-only), middle (editable), right (read-only)
  • ✅ Left/right save buttons hidden; only middle has save button
  • Left gutter: bands connecting left to middle
  • Right gutter: bands connecting middle to right
  • Conflict backgrounds: red/pink overlays on middle where left/right overlap
  • Chunk maps on both edges

Toolbar

  • ✅ Undo/Redo (Ctrl+Z / Ctrl+Shift+Z): acts on active pane
  • ✅ Previous/Next change (Alt+Up/Down): per-pane cursor-based navigation
  • Navigation only places cursor on involved panes (not the third uninvolved pane)
  • Previous/Next conflict (Ctrl+J / Ctrl+K): navigates <<<<<<< markers in middle
  • Conflict label: "N conflicts" / "Conflict X of N" / "No conflicts"
  • Go to line (Ctrl+L)
  • ✅ Blanks / Spaces toggles
  • Preferences (Ctrl+,)

Gutter Interactions

  • Only inward arrows: left gutter has right-arrows only, right gutter has left-arrows only
  • Click left gutter arrow: copies left chunk into middle
  • Click right gutter arrow: copies right chunk into middle
  • Right-click context menus: "Copy Left -> Middle" / "Copy Right -> Middle"

Scroll Sync

  • Horizontal sync across all three panes
  • Vertical scroll synced by chunk across all three panes

Find / Replace

  • Ctrl+F/H: find bar highlights matches across all three buffers
  • Match count sums all three buffers
  • Replace All replaces only in editable middle buffer (not read-only left/right)

Save

  • ✅ Ctrl+S: saves middle pane
  • Ctrl+Shift+S (Save As): saves middle to a new path; updates pane label
  • Save As updates tab-tracked path (close/unsaved dialog shows new name)
  • Ctrl+Shift+L (Save All): saves middle if dirty
  • Ctrl+Shift+O: opens focused file externally (works for all 3 panes)
  • Ctrl+R / F5 (Refresh): reloads all 3 files from disk
  • Refresh with unsaved middle: confirm dialog before reloading
  • After Save As, watcher reloads from new path (left/right still watch originals)

Edge Cases

  • Binary files: all panes show info bar; all read-only; middle save hidden
  • All three identical: no changes, no chunks
  • Both sides modify same region: conflict overlay on middle
  • Copy left then copy right to same region: middle updates; undo works
  • Undo/redo across panes: applies to active pane's buffer

VCS (Git) Window

Display

  • ✅ Window title: "mergers — reponame (branchname)"
  • ✅ Branch name shown in toolbar
  • ColumnView: Status, File, and Extra columns
  • Status colors: Modified/Renamed = blue, Added/Untracked = green, Deleted = orange
  • ✅ Extra column: "Staged" for fully staged, "Partially staged" for staged+unstaged
  • ✅ Conflict files: Extra column empty (not falsely "Staged")
  • ✅ Repo path label and changed file count

Opening Diffs

  • ✅ Double-click / Enter: opens diff tab (HEAD vs working copy)
  • Modified/Renamed: HEAD content on left, working file on right
  • Added/Untracked: empty left, working file on right
  • Deleted: HEAD content on left, empty right
  • Already-open tab: switches to existing tab

Context Menu

  • Right-click selects clicked row
  • "Open Diff": opens diff (disabled for Untracked)
  • "Discard Changes": runs git checkout -- with confirmation (disabled for Untracked)
  • "Stage": runs git add (disabled when already staged)
  • "Stage" on conflicted file: confirmation dialog warning it marks conflict resolved
  • "Unstage": runs git restore --staged (enabled only when staged)
  • "Trash": moves to trash with confirmation (Untracked only)

Commit Dialog

  • ✅ Commit button in toolbar
  • Commit dialog shows branch name
  • Commit dialog lists staged files (read-only)
  • Commit dialog prefills message from .git/MERGE_MSG
  • Commit button disabled when no staged files or empty message
  • Successful commit refreshes file list

Status Filters

  • ✅ Modified toggle (on by default): shows M, A, D, R, C files
  • ✅ Untracked toggle (on by default): shows U files
  • Ignored toggle (off by default): shows ignored files
  • Toggling filters updates file list and count label

File Watcher

  • Auto-refresh on FS changes (500ms poll)
  • .git directory events ignored
  • Smart update: skips rebuild if status unchanged

Notebook / Close

  • ✅ "Changes" tab first; Ctrl+W on it closes window
  • Ctrl+W on file tab: closes tab with unsaved check
  • Window close: checks all tabs for unsaved changes
  • Temp directory cleaned up on window destroy
  • Alt+1..9: switches to tab by index
  • Ctrl+N: opens New Comparison tab

Security

  • Paths with .. components refused

Patch Viewing / Applying

CLI

  • mergers file.c patch.diff: opens single-file patch view (original vs patched)
  • mergers dir/ patch.diff: opens multi-file patch view (dir comparison)
  • .diff extension auto-detected as patch mode
  • ✅ Ctrl+W closes patch window cleanly
  • -L labels applied to patch views
  • Invalid patch file: error dialog shown
  • Base path does not exist: error dialog shown

Single-File Patch

  • ✅ Window title contains "patch" and base filename
  • ✅ Two text panes shown
  • ✅ Left pane: original file content; Right pane: patched result
  • ✅ Right pane contains inserted lines from patch
  • ✅ Chunk label shows change count
  • ✅ Tab label contains "patch"
  • Conflict hunks shown with <<<<<<< original / >>>>>>> patch markers in right pane
  • Labels show base filename and "filename (patched)" (not temp paths)
  • Window destroy cleans up temp directory

Multi-File Patch (Dir View)

  • ✅ Window opens successfully
  • ✅ Shows patched files (e.g. "different.txt")
  • ✅ Shows subdirectories from the patch
  • Left header shows base directory name (not temp path)
  • Left header tooltip shows original base path (not temp path)
  • Right header shows "dirname (patched)"
  • Right header tooltip shows temp directory path
  • Conflicted files colored red in tree view
  • Same-status files filtered out of tree view
  • Empty directories filtered out of tree view
  • Double-click file: opens diff tab with resolved paths
  • Diff tab left pane header/tooltip: shows original file path (resolved through symlink)
  • Diff tab right pane: shows temp patched file path
  • Unsaved changes dialog shows original path (not temp path)

Apply All (Dir Patch View)

  • ⏪ button: confirmation dialog shows file count
  • Modified files (Different): copied right → left through symlink, then removed from view
  • New files (RightOnly): created in original directory, parent dirs created as needed
  • Deleted files (LeftOnly): removed from original directory
  • Conflicted files: skipped (not applied)
  • View reloads after apply; applied files vanish from tree
  • File watcher suppressed during bulk copy (no spurious reloads)
  • Errors during apply: error dialog shown with details

Temp Directory Cleanup

  • Normal window close: temp dir removed (connect_shutdown)
  • SIGINT (Ctrl+C): temp dir removed (ctrlc handler)
  • SIGTERM (kill): temp dir removed (ctrlc handler)
  • Multiple patch windows: all temp dirs tracked and cleaned up

Preferences

  • Font: chooser dialog; live-apply
  • Color scheme: dropdown; live-apply; case-insensitive matching
  • Show line numbers: toggle; live-apply
  • Highlight current line: toggle; live-apply
  • Word wrap (None/Word/Character): dropdown; live-apply
  • Tab width (1-16): spin button; live-apply
  • Hide hidden files: toggle; default on; saved to settings
  • Wrap-around navigation: toggle; saved to settings
  • File filters: add/remove entries; saved on dialog close
  • Settings persisted to ~/.config/mergers/settings.toml
  • Changes applied to all views in the parent window
  • Escape closes preferences dialog
  • Close button at bottom closes preferences dialog

Window State Persistence

  • ✅ Window size saved to settings.toml on close
  • Window maximized state restored on relaunch
  • Window fullscreen state restored on relaunch (macOS green button)
  • Per-window default sizes: VCS=700×500, merge=1200×600, file diff=900×600, dir=900×600
  • Old configs without window fields get sentinel defaults (0 = use per-window default)
  • Size only saved when not maximized/fullscreen (avoids saving inflated dimensions)

Dark Mode

  • Linux/GNOME: auto-detects system dark mode
  • macOS: falls back to defaults read -g AppleInterfaceStyle
  • Sets gtk_application_prefer_dark_theme for GTK widgets

Global Shortcuts

Shortcut Action
Ctrl+Q Quit (close all windows)
Ctrl+W Close current tab/window
Ctrl+, Preferences
Ctrl+Z Undo
Ctrl+Shift+Z Redo
Alt+Up / Ctrl+E Previous change
Alt+Down / Ctrl+D Next change
Ctrl+J Previous conflict (merge only)
Ctrl+K Next conflict (merge only)
Ctrl+F Find
Ctrl+H (Cmd+Shift+H on macOS) Find + Replace
F3 Find next
Shift+F3 Find previous
Ctrl+L Go to line
Alt+PageUp Previous pane
Alt+PageDown Next pane
Alt+Shift+Left Pull chunk from left
Alt+Shift+Right Pull chunk from right
Alt+Delete Delete current chunk
F11 Toggle fullscreen
Ctrl+Shift+P Export patch (file diff only)
Alt+Left Copy chunk right→left (file diff) / Copy file to left (dir)
Alt+Right Copy chunk left→right (file diff) / Copy file to right (dir)
Ctrl+S Save active pane
Ctrl+Shift+S Save As (file diff / merge)
Ctrl+Shift+L Save All dirty panes
Ctrl+Shift+O Open focused file externally
Ctrl+R / F5 Refresh (reload from disk)
Ctrl+N New Comparison tab (dir/VCS windows)
Alt+1..9 Switch to tab by index (notebook windows)
Delete Delete selected (dir only)
Enter Open selected file / expand-collapse dir (dir/VCS)
Escape Close find bar / go-to-line / preferences dialog

Preferences — Keyboard Shortcuts

  • "Keyboard Shortcuts" button in Preferences: opens shortcuts dialog
  • Dialog lists all shortcuts grouped by category