treesitter syntax highlighting for diffs
  • Lua 99.8%
  • Nix 0.2%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Barrett Ruth ae999b3602
All checks were successful
quality / Format (push) Successful in 6s
quality / Lint (push) Successful in 6s
quality / Test (push) Successful in 17s
ci: drop the github-runner test workflow
2026-09-26 16:07:42 -05:00
.forgejo ci: drop the github-runner test workflow 2026-09-26 16:07:42 -05:00
doc docs: remove LuaRocks installation [skip ci] 2026-09-21 21:47:56 -05:00
lua/diffs style: format the migration check 2026-09-26 16:01:55 -05:00
plugin fix: warn GitHub installs [skip ci] 2026-09-21 21:27:59 -05:00
spec test: remove migration specs [skip ci] 2026-09-21 21:32:58 -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 ci: migrate to nix 2026-02-23 18:14:05 -05:00
.luarc.json feat(commands): model Greview as review specs (#214) 2026-04-19 20:21:39 -04:00
.styluaignore refactor(highlight): unified per-line extmark builder (#144) 2026-03-05 09:01:22 -05:00
biome.json chore: replace prettier with biome (#219) 2026-04-25 16:16:01 -04:00
flake.lock build(nix): use nixpkgs vimdoc-language-server (#216) 2026-04-20 17:34:56 -04:00
flake.nix chore: replace prettier with biome (#219) 2026-04-25 16:16:01 -04:00
justfile chore: replace prettier with biome (#219) 2026-04-25 16:16:01 -04:00
LICENSE chore: license under GPL-3.0 2026-09-21 19:29:02 -05:00
README.md docs: host previews on Forgejo [skip ci] 2026-09-21 22:22:19 -05:00
selene.toml ci: migrate to nix 2026-02-23 18:14:05 -05:00
stylua.toml feat: initial setup files 2026-02-01 16:30:24 -05:00
vim.yaml ci: add bit luajit global 2026-02-23 18:18:30 -05:00

diffs.nvim

Treesitter-powered Diff Syntax highlighting for Neovim

Enhance Neovim's built-in diff mode (and much more!) with language-aware syntax highlighting driven by treesitter.

diffs.nvim highlighting Git changes

Features

  • Treesitter syntax highlighting in vim-fugitive, Neogit, builtin diff filetype, and more!
  • Word- and character-level diff highlighting, driven by 'diffopt' inline:
  • :Diff for pierre-style unified, stacked, or split diffs against any revision
  • :Diff review full-repo review diff with qflist/loclist navigation
  • :Diff files to diff two arbitrary files, or the buffer against its last save
  • Inline and 3-way merge conflict detection, highlighting, and resolution
  • Email quoting/patch syntax support (> diff ...)
  • Vim syntax fallback
  • Difftastic highlight support
  • Configurable highlighting

Requirements

  • Neovim 0.9.0+
  • Optional: the Treesitter diff parser for the best experience

Installation

With vim.pack (Neovim 0.12+):

vim.pack.add({
  'https://forge.barrettruth.com/barrettruth/diffs.nvim',
})

Documentation

:help diffs.nvim

FAQ

Q: Does diffs.nvim support vim-fugitive/Neogit/neojj/gitsigns/fzf-lua?

Yes. Enable integrations in your config:

vim.g.diffs = {
  integrations = {
    fugitive = true,
    neogit = true,
    neojj = true,
    gitsigns = true,
  }
}

fzf-lua is supported out-of-the-box.

See the documentation for more information.

Q: Can I use diffs.nvim as a Git mergetool?

Yes. Configure Git to open $MERGED with Neovim; diffs.nvim will detect conflict markers automatically. See :help diffs.nvim-git-mergetool.

Q: Can I exclude untracked files from :Diff review?

Yes. Run :Diff review ++nountracked. To make it the default, wrap it in your own command, e.g. :command! Review Diff review ++nountracked.

Known Limitations

  • Incomplete syntax context: Treesitter parses each diff hunk in isolation. Context lines within the hunk provide syntactic context for the parser. With or without context, hunks that start or end mid-expression may produce imperfect highlights due to treesitter error recovery.

  • Syntax "flashing": diffs.nvim hooks into the FileType fugitive event triggered by vim-fugitive, at which point the buffer is preliminarily painted. The decoration provider applies highlights on the next redraw cycle, so a brief first-paint flash may still occur.

  • Cold Start: Treesitter grammar loading (~10ms) and query compilation (~4ms) are one-time costs per language per Neovim session. Each language pays this cost on first encounter, which may cause a brief stutter when a diff containing a new language first enters the viewport.

  • Vim syntax fallback is deferred: The vim syntax fallback (for languages without a treesitter parser) cannot run inside the decoration provider's redraw cycle due to Neovim's restriction on buffer mutations. Vim syntax highlights for cold hunks may appear one frame later. Warm hunks can reuse cached vim syntax spans, and stale deferred renders are ignored after buffer changes.

  • 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 - diffs.nvim now includes built-in conflict resolution; disable one or the other to avoid overlap

Acknowledgements