https://github.com/esmuellert/codediff.nvim
A Neovim plugin that provides VSCode-style side-by-side diff rendering with two-tier highlighting (line + character level) using VSCode's algorithm implemented in C.
https://github.com/esmuellert/codediff.nvim
c diff lua neovim vscode
Last synced: 7 days ago
JSON representation
A Neovim plugin that provides VSCode-style side-by-side diff rendering with two-tier highlighting (line + character level) using VSCode's algorithm implemented in C.
- Host: GitHub
- URL: https://github.com/esmuellert/codediff.nvim
- Owner: esmuellert
- License: mit
- Created: 2025-10-23T05:28:45.000Z (5 months ago)
- Default Branch: main
- Last Pushed: 2026-02-11T05:41:11.000Z (about 1 month ago)
- Last Synced: 2026-02-11T13:42:44.439Z (about 1 month ago)
- Topics: c, diff, lua, neovim, vscode
- Language: Lua
- Homepage:
- Size: 1.6 MB
- Stars: 1,079
- Watchers: 5
- Forks: 29
- Open Issues: 40
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Agents: AGENTS.md
Awesome Lists containing this project
- awesome-neovim-sorted - esmuellert/codediff.nvim - style side-by-side diff rendering with two-tier highlighting (line + character level) using VSCode's algorithm implemented in C. | (Git)
- awesome-neovim - esmuellert/codediff.nvim - Side-by-side diff with two-tier highlighting (line + character level) using VSCode's algorithm implemented in C. (Git / Quickfix)
README
# codediff.nvim
[](https://github.com/esmuellert/vscode-diff.nvim/releases)
A Neovim plugin that provides VSCode-style diff rendering with two-tier highlighting, supporting both side-by-side and inline (unified) layouts.

https://github.com/user-attachments/assets/64c41f01-dffe-4318-bce4-16eec8de356e
**Demo: Quick walkthrough of diff features**
## Features
- **Two-tier highlighting system**:
- Light backgrounds for entire modified lines (green for insertions, red for deletions)
- Deep/dark character-level highlights showing exact changes within lines
- **Side-by-side diff view** in a new tab with synchronized scrolling
- **Inline (unified) diff view** — single-window layout with deleted lines as virtual overlays, with treesitter syntax highlighting
- **Git integration**: Compare between any git revision (HEAD, commits, branches, tags)
- **Same implementation as VSCode's diff engine**, providing identical visual highlighting for most scenarios
- **Fast C-based diff computation** using FFI with **multi-core parallelization** (OpenMP)
- **Async git operations** - non-blocking file retrieval from git
- **Moved code detection** — identifies blocks of code that moved within a file, with visual indicators (highlights, signs, annotations) matching VSCode's experimental `showMoves` feature (opt-in)
## Installation
### Prerequisites
- Neovim >= 0.7.0 (for Lua FFI support; 0.10+ recommended for vim.system)
- Git (for git diff features)
- `curl` or `wget` (for automatic binary download)
**No compiler required!** The plugin automatically downloads pre-built binaries from GitHub releases.
### Using lazy.nvim
**Minimal installation:**
```lua
{
"esmuellert/codediff.nvim",
cmd = "CodeDiff",
}
```
> **Note:** The plugin automatically adapts to your colorscheme's background (dark/light). It uses `DiffAdd` and `DiffDelete` for line-level diffs, and auto-adjusts brightness for character-level highlights (1.4x brighter for dark themes, 0.92x darker for light themes). See [Highlight Groups](#highlight-groups) for customization.
**With custom configuration:**
```lua
{
"esmuellert/codediff.nvim",
cmd = "CodeDiff",
opts = {
-- Highlight configuration
highlights = {
-- Line-level: accepts highlight group names or hex colors (e.g., "#2ea043")
line_insert = "DiffAdd", -- Line-level insertions
line_delete = "DiffDelete", -- Line-level deletions
-- Character-level: accepts highlight group names or hex colors
-- If specified, these override char_brightness calculation
char_insert = nil, -- Character-level insertions (nil = auto-derive)
char_delete = nil, -- Character-level deletions (nil = auto-derive)
-- Brightness multiplier (only used when char_insert/char_delete are nil)
-- nil = auto-detect based on background (1.4 for dark, 0.92 for light)
char_brightness = nil, -- Auto-adjust based on your colorscheme
-- Conflict sign highlights (for merge conflict views)
-- Accepts highlight group names or hex colors (e.g., "#f0883e")
-- nil = use default fallback chain
conflict_sign = nil, -- Unresolved: DiagnosticSignWarn -> #f0883e
conflict_sign_resolved = nil, -- Resolved: Comment -> #6e7681
conflict_sign_accepted = nil, -- Accepted: GitSignsAdd -> DiagnosticSignOk -> #3fb950
conflict_sign_rejected = nil, -- Rejected: GitSignsDelete -> DiagnosticSignError -> #f85149
},
-- Diff view behavior
diff = {
layout = "side-by-side", -- Diff layout: "side-by-side" (two panes) or "inline" (single pane with virtual lines)
disable_inlay_hints = true, -- Disable inlay hints in diff windows for cleaner view
max_computation_time_ms = 5000, -- Maximum time for diff computation (VSCode default)
ignore_trim_whitespace = false, -- Ignore leading/trailing whitespace changes (like diffopt+=iwhite)
hide_merge_artifacts = false, -- Hide merge tool temp files (*.orig, *.BACKUP.*, *.BASE.*, *.LOCAL.*, *.REMOTE.*)
original_position = "left", -- Position of original (old) content: "left" or "right"
conflict_ours_position = "right", -- Position of ours (:2) in conflict view: "left" or "right"
conflict_result_position = "bottom", -- "bottom" (default): result below diff panes or "center": result between diff panes (three columns)
conflict_result_height = 30, -- Height of result pane in bottom layout (% of total height)
conflict_result_width_ratio = { 1, 1, 1 }, -- Width ratio for center layout panes {left, center, right} (e.g., {1, 2, 1} for wider result)
cycle_next_hunk = true, -- Wrap around when navigating hunks (]c/[c): false to stop at first/last
cycle_next_file = true, -- Wrap around when navigating files (]f/[f): false to stop at first/last
jump_to_first_change = true, -- Auto-scroll to first change when opening a diff: false to stay at same line
highlight_priority = 100, -- Priority for line-level diff highlights (increase to override LSP highlights)
compute_moves = false, -- Detect moved code blocks (opt-in, matches VSCode experimental.showMoves)
},
-- Explorer panel configuration
explorer = {
position = "left", -- "left" or "bottom"
width = 40, -- Width when position is "left" (columns)
height = 15, -- Height when position is "bottom" (lines)
indent_markers = true, -- Show indent markers in tree view (│, ├, └)
initial_focus = "explorer", -- Initial focus: "explorer", "original", or "modified"
icons = {
folder_closed = "", -- Nerd Font folder icon (customize as needed)
folder_open = "", -- Nerd Font folder-open icon
},
view_mode = "list", -- "list" or "tree"
flatten_dirs = true, -- Flatten single-child directory chains in tree view
file_filter = {
ignore = { ".git/**", ".jj/**" }, -- Glob patterns to hide (e.g., {"*.lock", "dist/*"})
},
focus_on_select = false, -- Jump to modified pane after selecting a file (default: stay in explorer)
visible_groups = { -- Which groups to show (can be toggled at runtime)
staged = true,
unstaged = true,
conflicts = true,
},
},
-- History panel configuration (for :CodeDiff history)
history = {
position = "bottom", -- "left" or "bottom" (default: bottom)
width = 40, -- Width when position is "left" (columns)
height = 15, -- Height when position is "bottom" (lines)
initial_focus = "history", -- Initial focus: "history", "original", or "modified"
view_mode = "list", -- "list" or "tree" for files under commits
},
-- Keymaps in diff view
keymaps = {
view = {
quit = "q", -- Close diff tab
toggle_explorer = "b", -- Toggle explorer visibility (explorer mode only)
focus_explorer = "e", -- Focus explorer panel (explorer mode only)
next_hunk = "]c", -- Jump to next change
prev_hunk = "[c", -- Jump to previous change
next_file = "]f", -- Next file in explorer/history mode
prev_file = "[f", -- Previous file in explorer/history mode
diff_get = "do", -- Get change from other buffer (like vimdiff)
diff_put = "dp", -- Put change to other buffer (like vimdiff)
open_in_prev_tab = "gf", -- Open current buffer in previous tab (or create one before)
close_on_open_in_prev_tab = false, -- Close codediff tab after gf opens file in previous tab
toggle_stage = "-", -- Stage/unstage current file (works in explorer and diff buffers)
stage_hunk = "hs", -- Stage hunk under cursor to git index
unstage_hunk = "hu", -- Unstage hunk under cursor from git index
discard_hunk = "hr", -- Discard hunk under cursor (working tree only)
hunk_textobject = "ih", -- Textobject for hunk (vih to select, yih to yank, etc.)
show_help = "g?", -- Show floating window with available keymaps
align_move = "gm", -- Temporarily align moved code blocks across panes
},
explorer = {
select = "", -- Open diff for selected file
hover = "K", -- Show file diff preview
refresh = "R", -- Refresh git status
toggle_view_mode = "i", -- Toggle between 'list' and 'tree' views
stage_all = "S", -- Stage all files
unstage_all = "U", -- Unstage all files
restore = "X", -- Discard changes (restore file)
toggle_changes = "gu", -- Toggle Changes (unstaged) group visibility
toggle_staged = "gs", -- Toggle Staged Changes group visibility
},
history = {
select = "", -- Select commit/file or toggle expand
toggle_view_mode = "i", -- Toggle between 'list' and 'tree' views
},
conflict = {
accept_incoming = "ct", -- Accept incoming (theirs/left) change
accept_current = "co", -- Accept current (ours/right) change
accept_both = "cb", -- Accept both changes (incoming first)
discard = "cx", -- Discard both, keep base
next_conflict = "]x", -- Jump to next conflict
prev_conflict = "[x", -- Jump to previous conflict
diffget_incoming = "2do", -- Get hunk from incoming (left/theirs) buffer
diffget_current = "3do", -- Get hunk from current (right/ours) buffer
},
},
},
}
```
The C library will be downloaded automatically on first use. No `build` step needed!
### Managing Library Installation
The plugin automatically manages the C library installation:
**Automatic Updates:**
- The library is automatically downloaded on first use
- When you update the plugin to a new version, the library is automatically updated to match
- No manual intervention required!
**Manual Installation Commands:**
```vim
" Install/update the library manually
:CodeDiff install
" Force reinstall (useful for troubleshooting)
:CodeDiff install!
```
**Version Management:**
The installer reads the `VERSION` file to download the matching library version from GitHub releases. This ensures compatibility between the Lua code and C library.
### Manual Installation
If you prefer to install manually without a plugin manager:
1. **Clone the repository:**
```bash
git clone https://github.com/esmuellert/codediff.nvim ~/.local/share/nvim/codediff.nvim
```
2. **Add to your Neovim runtime path in `init.lua`:**
```lua
vim.opt.rtp:append("~/.local/share/nvim/codediff.nvim")
```
3. **Install the C library:**
The plugin requires a C library binary in the plugin root directory. The plugin auto-detects these filenames:
- `libvscode_diff.so` or `libvscode_diff_.so` (Linux/BSD)
- `libvscode_diff.dylib` or `libvscode_diff_.dylib` (macOS)
- `libvscode_diff.dll` or `libvscode_diff_.dll` (Windows)
**Option A: Download from GitHub releases** (recommended)
Download the appropriate binary from the [GitHub releases page](https://github.com/esmuellert/codediff.nvim/releases) and place it in the plugin root directory. Rename it to match the expected format: `libvscode_diff.so`/`.dylib`/`.dll` or `libvscode_diff_.so`/`.dylib`/`.dll`. **Linux users**: If your system lacks OpenMP, also download `libgomp_linux_{arch}_{version}.so.1` and rename it to `libgomp.so.1` in the same directory.
**Option B: Build from source**
Build requirements: C compiler (GCC/Clang/MSVC/MinGW) or CMake 3.15+
Using build scripts (no CMake required):
```bash
# Linux/macOS/BSD
./build.sh
# Windows
build.cmd
```
Or using CMake:
```bash
cmake -B build
cmake --build build
```
Both methods automatically place the library in the plugin root directory.
## Usage
The `:CodeDiff` command supports multiple modes:
### File Explorer Mode
Open an interactive file explorer showing changed files:
```vim
" Show git status in explorer (default)
:CodeDiff
" Show changes for specific revision in explorer
:CodeDiff HEAD~5
" Compare against a branch
:CodeDiff main
" Compare against a specific commit
:CodeDiff abc123
" Compare two revisions (e.g. HEAD vs main)
:CodeDiff main HEAD
" Override layout for this invocation (works with all subcommands)
:CodeDiff --inline
:CodeDiff main --side-by-side
```
#### PR-like Diff (Merge-base)
Show only changes introduced since branching from a base branch—exactly like a Pull Request:
```vim
" Compare merge-base(main, HEAD) vs working tree
" Shows only YOUR changes since you branched from main
:CodeDiff main...
" Compare merge-base(main, HEAD) vs HEAD (committed changes only)
:CodeDiff main...HEAD
" Compare merge-base between two branches
:CodeDiff develop...feature/new-ui
```
This uses `git merge-base` semantics (equivalent to `git diff main...HEAD`), showing only the changes introduced on your branch, not changes that happened on the base branch since you branched.
### Git Diff Mode
Compare the current buffer with a git revision:
```vim
" Compare with last commit
:CodeDiff file HEAD
" Compare with previous commit
:CodeDiff file HEAD~1
" Compare with specific commit
:CodeDiff file abc123
" Compare with branch
:CodeDiff file main
" Compare with tag
:CodeDiff file v1.0.0
" Compare two revisions for current file
:CodeDiff file main HEAD
" PR-like diff: compare merge-base(main, HEAD) vs working tree
:CodeDiff file main...
```
**Requirements:**
- Current buffer must be saved to a file
- File must be in a git repository
- Git revision must exist
**Behavior:**
- Left buffer: Git version (at specified revision) - readonly
- Right buffer: Current buffer content - readonly
- Opens in a new tab automatically
- Async operation - won't block Neovim
### File Comparison Mode
Compare two arbitrary files side-by-side:
```vim
:CodeDiff file file_a.txt file_b.txt
```
### Directory Comparison Mode
Compare two directories without git:
```vim
" Auto-detect directories
:CodeDiff ~/project-v1 ~/project-v2
" Explicit dir subcommand
:CodeDiff dir /path/to/dir1 /path/to/dir2
```
Shows files as Added (A), Deleted (D), or Modified (M) based on file size and modification time. Select a file to view its diff.
### File History Mode
Review commits on a per-commit basis:
```vim
" Show last 50 commits
:CodeDiff history
" Show last N commits
:CodeDiff history HEAD~10
" Show commits in a range (great for PR review)
:CodeDiff history origin/main..HEAD
" Show commits for current file only
:CodeDiff history HEAD~20 %
" Show commits for a specific file
:CodeDiff history HEAD~10 path/to/file.lua
" Show commits in chronological order (oldest first)
:CodeDiff history --reverse
:CodeDiff history HEAD~10 --reverse
:CodeDiff history origin/main..HEAD -r
:CodeDiff history HEAD~20 % --reverse
" Compare each commit against the current working tree
:CodeDiff history --base WORKING
" Compare each commit against HEAD
:CodeDiff history --base HEAD
" Line-range history: show only commits that changed the selected lines
:'<,'>CodeDiff history
:'<,'>CodeDiff history HEAD~10
:'<,'>CodeDiff history --reverse
```
The history panel shows a list of commits. Each commit can be expanded to show its changed files. Select a file to view the diff between the commit and its parent (`commit^` vs `commit`).
**Options:**
- `--reverse` or `-r`: Show commits in chronological order (oldest first) instead of reverse chronological. Useful for following development story from beginning to end, or reviewing PR changes in the order they were made.
- `--base` or `-b`: Compare each commit against a fixed revision instead of its parent. Accepts any git revision (`HEAD`, branch name, commit hash) or `WORKING` for the current working tree.
- `--inline` / `--side-by-side`: Override the diff layout for this invocation. These flags work with all `:CodeDiff` subcommands.
**Visual selection:** When called with a visual range (`:'<,'>CodeDiff history`), only commits that modified the selected lines are shown. This uses `git log -L` under the hood and is useful for tracing the evolution of a specific function or block in a large file.
**History Keymaps:**
- `i` - Toggle between list and tree view for files under commits
### Git Merge Tool
Use CodeDiff as your git merge tool for resolving conflicts:
```bash
git config --global merge.tool codediff
git config --global mergetool.codediff.cmd 'nvim "$MERGED" -c "CodeDiff merge \"$MERGED\""'
```
### Git Diff Tool
Use CodeDiff as your git diff tool for viewing changes:
```bash
git config --global diff.tool codediff
git config --global difftool.codediff.cmd 'nvim "$LOCAL" "$REMOTE" +"CodeDiff file $LOCAL $REMOTE"'
```
Then use `git difftool` to view diffs:
```bash
git difftool # View all uncommitted changes
git difftool HEAD~2 HEAD # Compare two commits
git difftool main feature-branch # Compare branches
git difftool -y # Skip confirmation prompts
```
### Lua API
```lua
-- Primary user API - setup configuration
require("codediff").setup({
highlights = {
line_insert = "DiffAdd",
line_delete = "DiffDelete",
char_brightness = 1.4,
},
})
-- Advanced usage - direct access to internal modules
local diff = require("codediff.diff")
local render = require("codediff.ui")
local git = require("codediff.git")
-- Example 1: Compute diff between two sets of lines
local lines_a = {"line 1", "line 2"}
local lines_b = {"line 1", "modified line 2"}
local lines_diff = diff.compute_diff(lines_a, lines_b)
-- Example 2: Get file content from git (async)
git.get_file_content("HEAD~1", "/path/to/repo", "relative/path.lua", function(err, lines)
if err then
vim.notify(err, vim.log.levels.ERROR)
return
end
-- Use lines...
end)
-- Example 3: Get git root for a file (async)
git.get_git_root("/path/to/file.lua", function(err, git_root)
if not err then
-- File is in a git repository
end
end)
```
### User Autocmd Events
CodeDiff emits `User` autocmd events at key lifecycle points, allowing you to customize behavior without config flags:
| Event | When | Data |
|-------|------|------|
| `CodeDiffOpen` | After diff view is fully ready | `tabpage`, `mode` |
| `CodeDiffClose` | Before cleanup starts | `tabpage`, `mode` |
| `CodeDiffFileSelect` | When a file is selected in explorer | `tabpage`, `path`, `status` |
`mode` is one of `"explorer"`, `"standalone"`, or `"history"`.
Example: Disable cursorline in diff windows
```lua
vim.api.nvim_create_autocmd("User", {
pattern = "CodeDiffOpen",
callback = function()
for _, win in ipairs(vim.api.nvim_tabpage_list_wins(0)) do
vim.wo[win].cursorline = false
end
end,
})
```
Example: Hide tabline while CodeDiff is open
```lua
vim.api.nvim_create_autocmd("User", {
pattern = "CodeDiffOpen",
callback = function()
vim.g.codediff_saved_showtabline = vim.o.showtabline
vim.o.showtabline = 0
end,
})
vim.api.nvim_create_autocmd("User", {
pattern = "CodeDiffClose",
callback = function()
if vim.g.codediff_saved_showtabline then
vim.o.showtabline = vim.g.codediff_saved_showtabline
vim.g.codediff_saved_showtabline = nil
end
end,
})
```
```
## Architecture
### Components
- **C Module** (`libvscode-diff/`): Fast diff computation and render plan generation
- Myers diff algorithm
- Character-level refinement for highlighting
- Matches VSCode's `rangeMapping.ts` data structures
- **Lua FFI Layer** (`lua/vscode-diff/diff.lua`): Bridge between C and Lua
- FFI declarations matching C structs
- Type conversions between C and Lua
- **Render Module** (`lua/vscode-diff/render/`): Neovim buffer rendering
- VSCode-style highlight groups
- Virtual line insertion for alignment
- Side-by-side window management
- Git status explorer
### Syntax Highlighting
The plugin handles syntax highlighting differently based on buffer type:
**Working files (editable):**
- Behaves like normal buffers with standard highlighting
- Inlay hints disabled by default (incompatible with diff highlights)
- All LSP features available
**Git history files (read-only):**
- Virtual buffers stored in memory, discarded when tab closes
- TreeSitter highlighting applied automatically (if installed)
- LSP not attached (most features meaningless for historical files)
- Semantic token highlighting fetched via LSP request when available
### Highlight Groups
The plugin defines highlight groups matching VSCode's diff colors:
- `CodeDiffLineInsert` - Light green background for inserted lines
- `CodeDiffLineDelete` - Light red background for deleted lines
- `CodeDiffCharInsert` - Deep/dark green for inserted characters
- `CodeDiffCharDelete` - Deep/dark red for deleted characters
- `CodeDiffFiller` - Gray foreground for filler line slashes (`╱╱╱`)
- `CodeDiffLineMove` - Background for moved code lines (derived from DiffChange)
- `CodeDiffMoveTo` - Sign column and annotation color for move indicators
📸 Visual Examples (click to collapse)
**Dawnfox Light** - Default configuration with auto-detected brightness (`char_brightness = 0.92` for light themes):

**Catppuccin Mocha** - Default configuration with auto-detected brightness (`char_brightness = 1.4` for dark themes):

**Kanagawa Lotus** - Default configuration with auto-detected brightness (`char_brightness = 0.92` for light themes):

**Default behavior:**
- Uses your colorscheme's `DiffAdd` and `DiffDelete` for line-level highlights
- Character-level highlights are auto-adjusted based on `vim.o.background`:
- **Dark themes** (`background = "dark"`): Brightness multiplied by `1.4` (40% brighter)
- **Light themes** (`background = "light"`): Brightness multiplied by `0.92` (8% darker)
- This auto-detection works out-of-box for most colorschemes
- You can override with explicit `char_brightness` value if needed
**Customization examples:**
```lua
-- Use hex colors directly
highlights = {
line_insert = "#1d3042",
line_delete = "#351d2b",
char_brightness = 1.5, -- Override auto-detection with explicit value
}
-- Override character colors explicitly
highlights = {
line_insert = "DiffAdd",
line_delete = "DiffDelete",
char_insert = "#3fb950",
char_delete = "#ff7b72",
}
-- Mix highlight groups and hex colors
highlights = {
line_insert = "String",
char_delete = "#ff0000",
}
```
## Development
### Building
```bash
make clean && make
```
### Testing
Run all tests:
```bash
make test # Run all tests (C + Lua integration)
```
Run specific test suites:
```bash
make test-c # C unit tests only
make test-lua # Lua integration tests only
```
For more details on the test structure, see [`tests/README.md`](tests/README.md).
### Project Structure
```
codediff.nvim/
├── libvscode-diff/ # C diff engine
│ ├── src/ # C implementation
│ ├── include/ # C headers
│ └── tests/ # C unit tests
├── lua/
│ ├── codediff/ # Main Lua modules
│ │ ├── init.lua # Main API
│ │ ├── config.lua # Configuration
│ │ ├── diff.lua # FFI interface
│ │ ├── git.lua # Git operations
│ │ ├── commands.lua # Command handlers
│ │ ├── installer.lua # Binary installer
│ │ └── ui/ # UI components
│ │ ├── core.lua # Diff rendering
│ │ ├── highlights.lua # Highlight setup
│ │ ├── view/ # View management
│ │ ├── explorer/ # Git status explorer
│ │ ├── history/ # Commit history panel
│ │ ├── lifecycle/ # Lifecycle management
│ │ └── conflict/ # Conflict resolution
│ └── vscode-diff/ # Backward compatibility shims
├── plugin/ # Plugin entry point
│ └── codediff.lua # Auto-loaded on startup
├── tests/ # Test suite (plenary.nvim)
├── docs/ # Documentation and development history
├── Makefile # Build automation
└── README.md
```
## Roadmap
### Current Status: Complete ✅
- [x] C-based diff computation with VSCode-identical algorithm
- [x] Two-tier highlighting (line + character level)
- [x] Side-by-side view with synchronized scrolling
- [x] Git integration (async operations, status explorer, revision comparison)
- [x] Auto-refresh on buffer changes (live diff updates)
- [x] Syntax highlighting preservation (LSP semantic tokens + TreeSitter)
- [x] Read-only buffers with virtual filler lines for alignment
- [x] Flexible highlight configuration (colorscheme-aware)
- [x] Integration tests (C + Lua with plenary.nvim)
- [x] File history mode (per-commit review, similar to DiffviewFileHistory)
### Future Enhancements
- [x] Inline diff mode (single buffer view)
- [x] Moved code detection (VSCode parity)
- [ ] Fold support for large diffs
## VSCode Reference
This plugin follows VSCode's diff rendering architecture:
- **Data structures**: Based on `src/vs/editor/common/diff/rangeMapping.ts`
- **Decorations**: Based on `src/vs/editor/browser/widget/diffEditor/registrations.contribution.ts`
- **Styling**: Based on `src/vs/editor/browser/widget/diffEditor/style.css`
## License
MIT
## Contributing
Contributions are welcome! Please ensure:
1. C tests pass (`make test`)
2. Lua tests pass
3. Code follows existing style
4. Updates to README if adding features