No description
Find a file
Barrett Ruth bbb87b660e fix(highlight): split old/new treesitter parsing
Problem: highlight_treesitter concatenated all hunk lines (context, -,
+) into a single string. Mixed old/new code produced invalid syntax
(e.g. two return statements), causing treesitter error recovery to drop
captures on lines after the syntax error.

Solution: split hunk lines into two versions — new (context + added)
and old (context + deleted) — each parsed independently. Use a line_map
to resolve treesitter row indices to buffer lines, with the old version
only mapping deleted lines to avoid duplicate extmarks on context.

Also fixes three related issues exposed by the improved TS coverage:

- Replace Normal extmark with DiffsClear (explicit fg from Normal.fg).
  Normal in extmarks doesn't reliably override vim :syntax foreground.

- Reorder priority stack to DiffsClear(198) < syntax(199) < line
  bg(200) < char bg(201). TS capture groups can carry colorscheme
  backgrounds that would override diff line backgrounds at higher
  priority.

- Gate DiffsClear on per-line coverage tracking. Only clear fugitive
  syntax fg on lines where TS/vim actually produced captures, preventing
  force-clearing on lines where error recovery drops captures.
2026-02-07 00:50:21 -05:00
.github fix: remove useless ci script 2026-02-04 15:39:27 -05:00
doc feat(config): replace algorithm 'auto'/'native' with 'default'/'vscode' 2026-02-06 21:23:40 -05:00
lua/diffs fix(highlight): split old/new treesitter parsing 2026-02-07 00:50:21 -05:00
plugin fix(commands): handle :e on diffs:// buffers via BufReadCmd 2026-02-06 22:21:33 -05:00
spec fix(highlight): split old/new treesitter parsing 2026-02-07 00:50:21 -05:00
.busted feat(test): testing infrastructure 2026-02-01 23:09:05 -05:00
.editorconfig feat: initial setup files 2026-02-01 16:30:24 -05:00
.gitignore feat: initial setup files 2026-02-01 16:30:24 -05:00
.luarc.json fix(ci): add jit to luarc globals for lua-language-server 2026-02-06 13:58:30 -05:00
.pre-commit-config.yaml fix: use yaml, not yml YAML file extension 2026-02-02 22:14:04 -05:00
.prettierignore feat: initial setup files 2026-02-01 16:30:24 -05:00
.prettierrc fix: use yaml, not yml YAML file extension 2026-02-02 22:14:04 -05:00
diffs.nvim-scm-1.rockspec feat: rename everything 2026-02-02 22:09:13 -05:00
LICENSE feat: initial setup files 2026-02-01 16:30:24 -05:00
README.md feat(config): replace algorithm 'auto'/'native' with 'default'/'vscode' 2026-02-06 21:23:40 -05:00
selene.toml feat: initial setup files 2026-02-01 16:30:24 -05:00
stylua.toml feat: initial setup files 2026-02-01 16:30:24 -05:00
vim.toml cleanup 2026-02-02 14:06:58 -05:00

diffs.nvim

Syntax highlighting for diffs in Neovim

Enhance vim-fugitive and Neovim's built-in diff mode with language-aware syntax highlighting.

diffs.nvim preview

Features

  • Treesitter syntax highlighting in :Git diffs and commit views
  • Diff header highlighting (diff --git, index, ---, +++)
  • :Gdiffsplit / :Gvdiffsplit syntax through diff backgrounds
  • :Gdiff unified diff against any git revision with syntax highlighting
  • Fugitive status buffer keymaps (du/dU) for unified diffs
  • Background-only diff colors for any &diff buffer (:diffthis, vimdiff)
  • Vim syntax fallback for languages without a treesitter parser
  • Hunk header context highlighting (@@ ... @@ function foo())
  • Character-level (intra-line) diff highlighting for changed characters
  • Configurable debouncing, max lines, and diff prefix concealment

Requirements

  • Neovim 0.9.0+

Installation

Install with your package manager of choice or via luarocks:

luarocks install diffs.nvim

Documentation

:help diffs.nvim

Known Limitations

  • Incomplete syntax context: Treesitter parses each diff hunk in isolation without surrounding code context. When a hunk shows lines added to an existing block (e.g., adding a plugin inside return { ... }), the parser doesn't see the return statement and may produce incorrect highlighting. This is inherent to parsing code fragments—no diff tooling solves this without significant complexity.

  • Syntax flashing: diffs.nvim hooks into the FileType fugitive event triggered by vim-fugitive, at which point the buffer is preliminarily painted. The buffer is then re-painted after debounce_ms milliseconds, causing an unavoidable visual "flash" even when debounce_ms = 0.

  • Conflicting diff plugins: diffs.nvim may not interact well with other plugins that modify diff highlighting. Known plugins that may conflict:

    • diffview.nvim - provides its own diff highlighting and conflict resolution UI
    • mini.diff - visualizes buffer differences with its own highlighting system
    • gitsigns.nvim - generally compatible, but both plugins modifying line highlights may produce unexpected results
    • git-conflict.nvim - conflict marker highlighting may overlap with diffs.nvim

Acknowledgements