{"id":47303142,"url":"https://github.com/masak1yu/winxmerge","last_synced_at":"2026-04-12T12:02:34.774Z","repository":{"id":344971520,"uuid":"1183867380","full_name":"masak1yu/winxmerge","owner":"masak1yu","description":"WinXMerge is an Open Source differencing and merging tool for MacOS and Linux. ","archived":false,"fork":false,"pushed_at":"2026-03-31T20:10:06.000Z","size":597,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-04-01T16:42:24.840Z","etag":null,"topics":["diff","linux","macos","merge"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/masak1yu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-17T02:52:23.000Z","updated_at":"2026-03-31T20:10:10.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/masak1yu/winxmerge","commit_stats":null,"previous_names":["masak1yu/winxmerge"],"tags_count":33,"template":false,"template_full_name":null,"purl":"pkg:github/masak1yu/winxmerge","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/masak1yu%2Fwinxmerge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/masak1yu%2Fwinxmerge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/masak1yu%2Fwinxmerge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/masak1yu%2Fwinxmerge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/masak1yu","download_url":"https://codeload.github.com/masak1yu/winxmerge/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/masak1yu%2Fwinxmerge/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31290538,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T13:12:26.723Z","status":"ssl_error","status_checked_at":"2026-04-01T13:12:25.102Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["diff","linux","macos","merge"],"created_at":"2026-03-17T06:02:34.605Z","updated_at":"2026-04-12T12:02:34.767Z","avatar_url":"https://github.com/masak1yu.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# WinXMerge\n\n[![CI](https://github.com/masak1yu/winxmerge/actions/workflows/ci.yml/badge.svg)](https://github.com/masak1yu/winxmerge/actions/workflows/ci.yml)\n\nA cross-platform file diff comparison and merge tool inspired by WinMerge, built with Rust + Slint UI.\n\n\u003cimg width=\"1200\" height=\"827\" alt=\"winxmerge\" src=\"https://github.com/user-attachments/assets/f3d2b2d7-d1d6-4838-9539-a62b45fe7780\" /\u003e\n\n## Features\n\n### File Comparison (2-way)\n- Block-level diff grouping: consecutive changes merged into one diff block (WinMerge-style)\n- Line-level diff display (additions/deletions/changes/moves with color coding)\n- Word-level (character-level) diff display for modified lines\n- Diff navigation (first/previous/next/last diff block)\n- Merge operations (block-level copy: left→right / right→left, copy \u0026 advance, copy all)\n- Two-pane display with inline diff markers\n- Location pane (minimap of diff positions)\n- Automatic detection of moved lines (blue highlight)\n- Synchronized left/right scrolling\n- Click line numbers to select diff blocks\n\n### 3-way Merge\n- Three-pane display (Left / Base / Right)\n- WinMerge-style Make3wayDiff overlap-grouping algorithm\n- Automatic detection of changes from base file\n- Conflict highlighting (red) with L/R buttons for conflict resolution\n- Conflict navigation (next/previous)\n- Copy \u0026 advance, copy all toolbar buttons\n- Auto-merge when both sides have identical changes\n- Inline editing with F5 rescan (VecModel as authoritative source)\n- Save dropdown: save Left / Middle / Right individually\n\n### Folder Comparison\n- Recursive directory comparison with tree-style indentation\n- File status display (identical / different / one-side only)\n- Left/right modification timestamps\n- Automatic .gitignore pattern loading (.git directories auto-excluded)\n- File extension filter\n- Double-click to open file diff view\n- Right-click context menu (copy to left/right, delete)\n- \"\u003c Back\" button to return to folder view\n- **Status filter bar**: All / Identical / Different / Left only / Right only filter buttons above the file list\n- **Column sort**: click any column header (Name / Status / Left Size / Right Size / Left Modified / Right Modified) to sort; click again to toggle ascending/descending (▲▼ indicator)\n\n### Tabs\n- Manage multiple comparisons with tabs\n- Each tab maintains independent state\n- Cmd+T to create new tab, Cmd+W to close\n\n### Diff Detail Pane\n- Bottom pane showing the selected diff block's left/right content\n- Top = left (removed), Bottom = right (added) with scrollable view\n- Automatically updates when navigating between diffs\n\n### Toolbar\n- WinMerge-style icon toolbar with SVG icons\n- Single row: New, Open, Save, Undo/Redo, Rescan, Options, Navigation, Copy, Copy \u0026 Advance, Copy All, Ignore WS/Case\n- Hover hints shown in status bar\n- Toggle buttons for Ignore Whitespace / Ignore Case\n\n### Syntax Highlighting\n- Line-level highlighting via tree-sitter\n- Supported languages: Rust, JavaScript, Python, JSON, C, C++, Go, TypeScript, TSX, Ruby, Java, C#, YAML, TOML, Markdown\n- Automatic file type detection\n- Toggle on/off in options\n\n### Undo / Redo\n- Undo and redo merge operations\n- Cmd+Z / Cmd+Shift+Z\n\n### Diff Options\n- Ignore whitespace\n- Ignore case\n- Ignore blank lines\n- Ignore line ending differences\n- Toggle moved line detection\n\n### Filters\n- **Line filters**: Exclude lines matching regex patterns from comparison (e.g., comments, timestamps)\n- **Substitution filters**: Apply regex find/replace before comparison (e.g., normalize dates, version numbers)\n- Multiple rules support via pipe-separated patterns\n- Configured via Edit → Options... → Filters\n- Settings persisted across sessions\n\n### Encoding\n- Automatic character encoding detection (UTF-8, UTF-16, Shift_JIS, etc.)\n- BOM support\n- Preserves original encoding when saving\n\n### Search \u0026 Replace\n- Text search (match count display, previous/next navigation)\n- Replace / Replace All\n- Available in both 2-way and 3-way diff views\n\n### Go to Line\n- Jump to a specific line number (Cmd+G)\n\n### Bookmarks\n- Toggle bookmarks on diff lines (Cmd+M)\n- Navigate between bookmarks (F2 / Navigate menu)\n\n### Keyboard Shortcuts\n\n| Shortcut | Action |\n|----------|--------|\n| Cmd+S | Save left file |\n| Cmd+F | Toggle search \u0026 replace |\n| Cmd+G | Go to line |\n| Cmd+M | Toggle bookmark |\n| Cmd+Z | Undo |\n| Cmd+Shift+Z | Redo |\n| Cmd+T | New tab |\n| Cmd+W | Close tab |\n| Cmd+N | New comparison |\n| Alt+↓ | Next diff |\n| Alt+↑ | Previous diff |\n| Alt+Home | First diff |\n| Alt+End | Last diff |\n| F2 | Next bookmark |\n| F5 | Rescan files |\n\n### Open in External Editor\n- Open left or right file in system default editor (File menu)\n- Custom editor command configurable in settings\n\n### Plugin System\n- Execute external commands with file path placeholders ({LEFT}, {RIGHT})\n- Plugins configured in settings.json\n- Available via Plugins menu\n\n### Auto-rescan\n- Automatic file change detection (polls every 500ms)\n- Re-runs diff when files are modified externally\n- Skips reload while user has unsaved inline edits (prevents data loss)\n- Toggle via Edit → Options... → Auto-rescan\n\n### Accessibility\n- ARIA-compatible accessible roles and labels on key UI components\n- Screen reader support for diff view and folder comparison\n\n### Internationalization (i18n)\n- Japanese / English UI switching (Edit → Options... → Appearance → Language)\n- Full translation support for menus, toolbar, dialogs, and status bar\n\n### Theme Switching\n- Light / Dark theme switching (Edit → Options... → Appearance)\n- All widgets automatically follow theme via Slint Palette integration\n- Diff colors and syntax highlighting colors optimized per theme\n- Settings persisted across sessions\n\n### Built-in File Browser\n- Native-dialog-independent file/folder picker (works on WSL2 and environments without GTK)\n- Directory navigation with folder/file icons, parent button, and editable path bar\n- Falls back automatically when the system file dialog is unavailable\n\n### ZIP Archive Comparison\n- Compare `.zip` files as virtual folders showing added/removed/changed entries\n- CRC + size based change detection per entry\n\n### CSV / TSV Comparison\n- Compare `.csv` and `.tsv` files with cell-level diff table display\n- Auto-detects delimiter (comma vs tab) independently per file\n- Handles quoted fields with embedded delimiters and newlines\n- Drag column header borders to resize columns\n- Inline cell editing with undo/redo (Cmd+Z / Cmd+Shift+Z)\n- Save edited table as CSV (Cmd+S), with Save As dialog for new documents\n- F5 rescan recomputes diff from edited cells (VecModel as authoritative source)\n- Delimiter mismatch warning when comparing .csv vs .tsv files\n\n### Excel / Spreadsheet Comparison\n- Compare `.xlsx`, `.xls`, `.xlsm`, `.ods` files with table-view cell diff display\n- Changed cells highlighted; sheet selector for multi-sheet files\n\n### Image Comparison\n- Pixel-level comparison for PNG, JPEG, GIF, BMP, WebP, TIFF, ICO\n- Side-by-side left/right panels + diff overlay (changed pixels in red, identical pixels in gray)\n- Continuous zoom slider (10–400%) with Fit mode and diff panel toggle\n- **Blend slider** (0–100%): overlay changed-pixel highlights directly on the left/right panels at adjustable opacity\n\n### Diff Detail Pane (WinMerge-style)\n- Shows only the currently selected diff block (not the whole file)\n- Left panel for removed/modified lines, Right panel for added/modified lines\n- Single panel when only one side has changes; both panels with inner resize handle when both sides differ\n- Character-level background highlighting on changed segments within modified lines\n- Pane height resizable by dragging the top handle; inner split resizable by dragging between panels\n\n### Diff Comments\n- Add per-block notes in the detail pane (Note field)\n- Comments persisted to session and embedded in HTML / Excel export reports\n- **Export All Comments**: File → Export All Comments (CSV/JSON)... — collects all comments across all tabs and saves as CSV or JSON\n\n### App Icon\n- Custom \"Diff Panels\" icon (cross-platform): embedded in the Windows executable (.ico) and macOS bundle (.icns)\n\n### Diff Stats Bar Graph\n- Status bar shows proportional mini bar graph (green=added, red=removed, yellow=modified) alongside `+A -R ~M` counts\n\n### Keyboard Shortcuts Dialog\n- Help → Keyboard Shortcuts: scrollable reference of all shortcuts grouped by File / Navigation / Merge / View\n\n### Session Persistence Improvements\n- Tabs restored with encoding, EOL type, tab width, diff-only mode, status filter, and diff comments\n\n### View Menu Enhancements\n- **Zoom In / Zoom Out / Reset Zoom**: adjust editor font size from the View menu (range 8–32pt)\n- **Wrap Lines**: toggle line wrapping at the window edge (View → Wrap Lines, default off)\n- Row height adapts to font size in both normal and wrap modes\n\n### Window Resizing\n- Window is now properly resizable (initial size 1200×800, minimum 600×400)\n- Diff view panes use proportional layout (no fixed-width binding loops)\n\n### Inline Editing (WinMerge-style)\n- Edit text directly in diff panes — always in aligned Ghost-line view (no separate edit mode)\n- Enter to insert new line (Ghost line added to other pane for alignment)\n- Backspace at start of empty line to delete\n- Arrow keys (Up/Down) to move between editable rows\n- F5 to rescan (recompute diff from edited content)\n- Undo/Redo support for all edit operations\n\n### New Blank Document\n- File → New → Text: create empty 2-way comparison document\n- File → New → Table: create empty CSV/TSV comparison document (10x5 initial grid, editable immediately)\n- File → New (3-pane) → Text / Table: create empty 3-way comparison\n- Toolbar \"New\" button with dropdown for type selection\n\n### Save As Dialog (WinMerge-style)\n- In-app file browser dialog with directory listing, navigation, and filename input\n- Shown when saving documents without file paths (new/clipboard)\n- Directory defaults to current working directory\n- On quit with unsaved changes: Save / Don't Save / Cancel (cancel aborts quit)\n\n### Git Difftool Integration\n- Single-instance mode via Unix domain socket IPC\n- `git difftool` opens diffs as tabs in the existing window\n- Multiple file pairs (2+) displayed as a virtual folder comparison view\n- Double-click a file in the folder view to open detailed diff in a new tab\n\n### Other\n- WinMerge-style initial file selection dialog (with recent files list)\n- WinMerge-style options dialog (Edit → Options...)\n- Right-click context menu (copy, merge, navigation)\n- Unsaved changes confirmation dialog (WinMerge-style Save/Don't Save/Cancel)\n- HTML diff report export (File → Export HTML Report...) with embedded diff comments (also included in Print)\n- Excel diff report export (File → Export Excel (.xlsx)...) with color-coded rows and comments column\n- Native menu bar (macOS / Windows)\n- Settings persistence (~/.config/winxmerge/settings.json)\n- Performance optimizations for large files\n- GitHub Actions CI (build, test, lint on Ubuntu / macOS / Windows)\n- Automated release builds for Linux, macOS (aarch64), and Windows\n\n## Tech Stack\n\n| Component | Technology |\n|-----------|-----------|\n| Language | Rust 1.94.0 |\n| UI Framework | [Slint](https://slint.dev/) 1.15 |\n| Diff Algorithm | [similar](https://crates.io/crates/similar) |\n| Syntax Highlighting | [tree-sitter](https://crates.io/crates/tree-sitter) |\n| File Dialog | [rfd](https://crates.io/crates/rfd) |\n| Encoding Detection | [chardetng](https://crates.io/crates/chardetng) + [encoding_rs](https://crates.io/crates/encoding_rs) |\n| Clipboard | [arboard](https://crates.io/crates/arboard) |\n| Settings Persistence | [serde](https://crates.io/crates/serde) + [serde_json](https://crates.io/crates/serde_json) |\n| ZIP Comparison | [zip](https://crates.io/crates/zip) |\n| Excel Comparison | [calamine](https://crates.io/crates/calamine) |\n| Excel Export | [rust_xlsxwriter](https://crates.io/crates/rust_xlsxwriter) |\n| Image Comparison | [image](https://crates.io/crates/image) |\n| WASM Build | [wasm-bindgen](https://crates.io/crates/wasm-bindgen) + [trunk](https://trunkrs.dev/) |\n\n## Web Version (WASM)\n\n**Live: https://winxmerge.app**\n\nWinXMerge can be built as a WebAssembly app for deployment to Cloudflare Pages.\n\nThe web version supports text input, file upload, clipboard paste, and diff navigation with stats. Desktop-only features (file dialogs, syntax highlighting, folder compare, etc.) are excluded via `cfg(not(target_arch = \"wasm32\"))` conditional compilation — the desktop build is unaffected.\n\n### Build\n\n```bash\n# Install WASM target and trunk\nrustup target add wasm32-unknown-unknown\ncargo install trunk\n\n# Development server\ntrunk serve\n\n# Production build (outputs to dist/)\ntrunk build --release\n```\n\nDeploy the `dist/` directory to Cloudflare Pages.\n\n## Setup\n\n### Prerequisites\n\n- [asdf](https://asdf-vm.com/) installed\n- macOS / Linux / Windows (WSL)\n\n### Getting Started\n\n```bash\n# Clone the repository\ngit clone git@github.com:masak1yu/winxmerge.git\ncd winxmerge\n\n# Install Rust via asdf\nasdf plugin add rust\nasdf install\n\n# Build\ncargo build\n\n# Run tests\ncargo test\n\n# Launch the app\ncargo run\n\n# 2-way comparison\ncargo run -- file1.txt file2.txt\n\n# 3-way merge\ncargo run -- base.txt left.txt right.txt\n```\n\n## Git Integration\n\nWinXMerge can be used as a `git difftool` / `git mergetool`.\n\n### difftool Setup\n\n```bash\ncargo build --release\ncp target/release/winxmerge ~/.local/bin/\n\ngit config --global diff.tool winxmerge\ngit config --global difftool.winxmerge.cmd 'winxmerge \"$LOCAL\" \"$REMOTE\"'\ngit config --global difftool.prompt false\n```\n\n### mergetool Setup (3-way merge)\n\n```bash\ngit config --global merge.tool winxmerge\ngit config --global mergetool.winxmerge.cmd 'winxmerge \"$BASE\" \"$LOCAL\" \"$REMOTE\"'\ngit config --global mergetool.winxmerge.trustExitCode true\n```\n\n### Usage\n\n```bash\n# View working tree changes\ngit difftool\n\n# Diff a specific file\ngit difftool -- path/to/file.rs\n\n# Diff between branches\ngit difftool main..feature-branch\n\n# Resolve merge conflicts\ngit mergetool\n```\n\n### Single-Instance Tab Mode\n\nWhen multiple files are changed, `git difftool` invokes WinXMerge once per file.\nWinXMerge uses IPC (Unix domain socket) to detect a running instance and opens\nsubsequent diffs as new tabs in the existing window instead of spawning separate processes.\n\n## Project Structure\n\n```\nwinxmerge/\n├── Cargo.toml\n├── build.rs                    # Slint build configuration\n├── .tool-versions              # asdf version management\n├── ui/\n│   ├── main.slint              # Main window\n│   ├── theme.slint             # Theme color definitions (light/dark)\n│   ├── icons/                  # SVG toolbar icons\n│   ├── dialogs/\n│   │   ├── open-dialog.slint      # File/folder selection dialog\n│   │   ├── file-browser.slint     # Built-in file browser (WSL2-safe)\n│   │   ├── save-confirm-dialog.slint # Save confirmation dialog (WinMerge-style)\n│   │   ├── new-table-dialog.slint # New table type selection dialog\n│   │   ├── options-dialog.slint   # Options dialog\n│   │   └── shortcuts-dialog.slint # Keyboard shortcuts reference dialog\n│   └── widgets/\n│       ├── diff-view.slint        # 2-way diff display widget\n│       ├── diff-view-3way.slint   # 3-way merge display widget\n│       ├── folder-view.slint      # Folder comparison widget (with status filter)\n│       ├── tab-bar.slint          # Tab bar widget\n│       ├── excel-view.slint       # Excel cell diff table view\n│       └── image-view.slint       # Image comparison widget (continuous zoom)\n├── src/\n│   ├── main.rs                 # Entry point, CLI argument handling\n│   ├── app.rs                  # Application state management (tab support)\n│   ├── encoding.rs             # Encoding detection and conversion\n│   ├── export.rs               # HTML/CSV/patch report export (with comment support)\n│   ├── highlight.rs            # Syntax highlighting (15 languages)\n│   ├── settings.rs             # Settings persistence (SessionEntry with full tab state)\n│   ├── archive.rs              # ZIP archive comparison\n│   ├── excel.rs                # Excel file comparison (calamine)\n│   ├── image_compare.rs        # Image comparison (pixel-level diff)\n│   ├── diff/\n│   │   ├── engine.rs           # 2-way diff engine\n│   │   ├── three_way.rs        # 3-way merge engine\n│   │   └── folder.rs           # Recursive folder comparison\n│   └── models/\n│       ├── diff_line.rs        # Diff line data model\n│       └── folder_item.rs      # Folder comparison item model\n├── translations/               # Translation files (gettext .po)\n│   └── ja/LC_MESSAGES/         # Japanese translations\n└── testdata/                   # Test sample files\n```\n\n## Usage\n\n1. Launch the app with `cargo run`\n2. Enter left/right file or folder paths in the initial dialog and click \"Compare\"\n   - For 3-way merge: check \"3-way merge\" and specify a base file\n   - Re-open recent files from the list with one click\n3. **Diff navigation:** Use ◀ Prev / Next ▶ toolbar buttons or Alt+↓/↑\n4. **Merge:** Use Copy → / ← Copy buttons, or inline ▶ / ◀ buttons between diff lines\n5. **3-way conflict resolution:** Click L / R buttons on red (conflict) lines to choose left or right\n6. **Undo:** Cmd+Z to undo operations\n7. **Search:** Cmd+F to show the search \u0026 replace bar\n8. **Tabs:** Cmd+T for a new tab, manage multiple comparisons in parallel\n9. **Options:** Edit → Options... to configure settings\n\n## License\n\nThis project is distributed under the [Slint Royalty-Free Desktop, Mobile, and Web Applications License v2.0](https://slint.dev/terms-and-conditions#royalty-free).\n\nSince this project uses the Slint UI framework, the following conditions apply:\n\n- Distribution as desktop / mobile / web applications is royalty-free\n- Embedded system use is not covered\n- Slint attribution (AboutSlint widget or web badge) is required\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmasak1yu%2Fwinxmerge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmasak1yu%2Fwinxmerge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmasak1yu%2Fwinxmerge/lists"}