Commit f64c307
feat(diff): add layout = "inline" for VS Code-style unified diff (#195)
## Summary
Add a new `layout = "inline"` option for `diff_opts` that renders a VS
Code-style unified inline diff - a single read-only buffer with deleted
(red/strikethrough) and added (green) lines interleaved. This
complements the existing `"vertical"` and `"horizontal"` two-panel diff
layouts.
Closes #82
## Motivation
The existing diff layouts use Neovim's built-in `diffthis` to show old
and new content side by side. While effective, this uses significant
screen real estate with two panels. An inline unified diff provides a
more compact view that's familiar to VS
Code users, showing changes in context within a single buffer.
## Changes
- **New module** `lua/claudecode/diff_inline.lua` — self-contained
inline diff implementation with:
- Pure diff computation via `vim.diff()` (indices mode)
- Extmark-based rendering with sign column markers (`+`/`-`)
- Resolution (accept/reject) and cleanup functions
- **Dispatch in `diff.lua`** — routes to inline module when `layout =
"inline"` is configured; exposes shared utilities as `M._` members
following existing patterns
- **Config/types** — validates `"inline"` as a valid layout value
- **`close_all_diff_tabs`** — detects inline diff buffers via
`claudecode_inline_diff` buffer variable
- **Test mock** — adds `vim.diff` mock with LCS-based hunk computation
to `tests/mocks/vim.lua`
- **23 new tests** covering diff computation, content extraction,
rendering, MCP response format, config validation, and cleanup
## Configuration
```lua
require("claudecode").setup({
diff_opts = {
layout = "inline", -- "vertical" (default), "horizontal", or "inline"
},
})
```
Highlight groups are customizable:
- ClaudeCodeInlineDiffAdd — green background for added lines
- ClaudeCodeInlineDiffDelete — red background + strikethrough for deleted lines
- ClaudeCodeInlineDiffAddSign / ClaudeCodeInlineDiffDeleteSign — sign column colors
Requirements
- layout = "inline" requires Neovim >= 0.9.0 (for vim.diff())
- The plugin's base requirement remains Neovim >= 0.8.0; only inline layout needs 0.9+
Design Decisions
1. Separate module rather than inlining into diff.lua — keeps the already-large file manageable; inline diff uses fundamentally different rendering (extmarks vs diffthis)
2. layout field in diff state — enables dispatch in resolution/cleanup without re-reading config
3. Read-only buffer — inline diff is review-only; content extraction uses saved line_types array rather than parsing buffer text
4. Always vsplit — single buffer doesn't need horizontal/vertical choice
Test Plan
- [x] luacheck lua/ tests/ passes with 0 warnings / 0 errors
- [x] All 406 tests pass (23 new, 5 pre-existing failures unrelated to this change)
- [x] Manual: layout = "inline" → single-window diff with colored lines
- [x] Manual: Accept (<leader>aa) → file saved correctly, diff closes
- [x] Manual: Deny (<leader>ad) → file unchanged, diff closes
- [x] Manual: New file creation → all lines shown as green/added
- [x] Manual: layout = "vertical" still works unchanged (regression check)
---------
Signed-off-by: Thomas Kosiewski <tk@coder.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Thomas Kosiewski <tk@coder.com>1 parent 03f8bbe commit f64c307
7 files changed
Lines changed: 1219 additions & 8 deletions
File tree
- lua/claudecode
- tests
- mocks
- unit
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
371 | 371 | | |
372 | 372 | | |
373 | 373 | | |
374 | | - | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
375 | 379 | | |
376 | 380 | | |
377 | 381 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
130 | 130 | | |
131 | 131 | | |
132 | 132 | | |
133 | | - | |
134 | | - | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
135 | 137 | | |
136 | 138 | | |
137 | 139 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
826 | 826 | | |
827 | 827 | | |
828 | 828 | | |
| 829 | + | |
| 830 | + | |
| 831 | + | |
| 832 | + | |
| 833 | + | |
| 834 | + | |
| 835 | + | |
829 | 836 | | |
830 | 837 | | |
831 | 838 | | |
| |||
913 | 920 | | |
914 | 921 | | |
915 | 922 | | |
| 923 | + | |
| 924 | + | |
| 925 | + | |
| 926 | + | |
| 927 | + | |
| 928 | + | |
| 929 | + | |
916 | 930 | | |
917 | 931 | | |
918 | 932 | | |
| |||
1135 | 1149 | | |
1136 | 1150 | | |
1137 | 1151 | | |
| 1152 | + | |
| 1153 | + | |
| 1154 | + | |
| 1155 | + | |
| 1156 | + | |
| 1157 | + | |
| 1158 | + | |
| 1159 | + | |
1138 | 1160 | | |
1139 | 1161 | | |
1140 | 1162 | | |
| |||
1276 | 1298 | | |
1277 | 1299 | | |
1278 | 1300 | | |
| 1301 | + | |
| 1302 | + | |
| 1303 | + | |
| 1304 | + | |
| 1305 | + | |
| 1306 | + | |
| 1307 | + | |
1279 | 1308 | | |
1280 | 1309 | | |
1281 | 1310 | | |
| |||
1742 | 1771 | | |
1743 | 1772 | | |
1744 | 1773 | | |
| 1774 | + | |
| 1775 | + | |
| 1776 | + | |
| 1777 | + | |
| 1778 | + | |
| 1779 | + | |
| 1780 | + | |
| 1781 | + | |
| 1782 | + | |
| 1783 | + | |
| 1784 | + | |
| 1785 | + | |
1745 | 1786 | | |
1746 | 1787 | | |
1747 | 1788 | | |
| |||
1756 | 1797 | | |
1757 | 1798 | | |
1758 | 1799 | | |
| 1800 | + | |
| 1801 | + | |
| 1802 | + | |
| 1803 | + | |
| 1804 | + | |
| 1805 | + | |
| 1806 | + | |
| 1807 | + | |
| 1808 | + | |
| 1809 | + | |
| 1810 | + | |
| 1811 | + | |
1759 | 1812 | | |
1760 | 1813 | | |
1761 | 1814 | | |
| |||
1767 | 1820 | | |
1768 | 1821 | | |
1769 | 1822 | | |
| 1823 | + | |
| 1824 | + | |
| 1825 | + | |
| 1826 | + | |
| 1827 | + | |
| 1828 | + | |
| 1829 | + | |
| 1830 | + | |
1770 | 1831 | | |
1771 | 1832 | | |
1772 | 1833 | | |
| |||
0 commit comments