Commit graph

60 commits

Author SHA1 Message Date
Barrett Ruth
d584d816bf
feat: add telescope.nvim integration (#170)
Closes #169.

## Problem

Telescope never sets `filetype=diff` on preview buffers — it calls
`vim.treesitter.start(bufnr, "diff")` directly, so diffs.nvim's
`FileType` autocmd never fires.

## Solution

Add a `telescope` config toggle (same pattern as
neogit/gitsigns/committia) and a `User TelescopePreviewerLoaded` autocmd
that calls `attach()` on the preview buffer. Disabled by default; enable
with `telescope = true`.

Also adds a `diffs-telescope` vimdoc section documenting the integration
and the upstream first-line preview bug
(nvim-telescope/telescope.nvim#3626).

Includes committia.vim integration from `feat/committia`.
2026-03-06 13:46:15 -05:00
Barrett Ruth
d06144450c
docs: revamp vimdoc structure and content (#167)
## Problem

The vimdoc had several issues: integration sections (fugitive, neogit,
gitsigns) were scattered as top-level entries with no grouping, the
intro implied diffs.nvim works automatically with fugitive/neogit out of
the box, the neogit section described a highlight override workaround
that was already removed, and `extra_filetypes` didn't mention picker
support.

## Solution

- Rewrite intro to document default behavior: `gitcommit` highlighting,
conflict detection, `&diff` winhighlight — everything else is opt-in
- Remove vim-fugitive as a dependency in setup
- Add `|diffs-integrations|` parent section grouping fugitive, neogit,
and gitsigns
- Add fugitive intro paragraph mentioning `:Gdiff`
- Trim neogit section (remove stale highlight override docs)
- Trim gitsigns section (remove implementation details)
- Add `committia` config field docs
- Expand `extra_filetypes` docs to mention telescope, snacks, and
fzf-lua
2026-03-06 11:31:40 -05:00
Barrett Ruth
8122f23541
docs: restructure vimdoc with integrations parent section (#165)
## Problem

Integration docs (fugitive, neogit, gitsigns) were scattered as
top-level sections with no grouping, making it hard to find all
supported plugin integrations in one place.

## Solution

Add `|diffs-integrations|` parent section that groups all integration
subsections under a single TOC entry. Fugitive, neogit, and gitsigns are
now subsections (using `---` separators) under the new `INTEGRATIONS`
heading. The intro paragraph documents the two attachment patterns:
automatic (config toggles like `fugitive = true`) and opt-in
(`extra_filetypes`). Conflict resolution and merge diff resolution
remain as standalone top-level sections. TOC renumbered accordingly.
2026-03-06 11:26:35 -05:00
Barrett Ruth
cb852d115b
docs: document picker integration via extra_filetypes (#164)
## Problem

`extra_filetypes = { 'diff' }` enables highlighting in telescope,
snacks, and fzf-lua git preview buffers, but this was not documented
beyond a brief mention of `.diff` files.

## Solution

Add a README FAQ entry and expand the vimdoc `extra_filetypes` field
description to mention specific pickers and which previewer styles are
supported.
2026-03-06 11:22:13 -05:00
Barrett Ruth
993fed4a45
feat: gitsigns blame popup highlighting (#157)
## Problem

gitsigns' `:Gitsigns blame_line` popup shows flat
`GitSignsAddPreview`/`GitSignsDeletePreview` line highlights with basic
word-level inline diffs, but no treesitter syntax or diffs.nvim's
character-level intra-line highlighting.

## Solution

Add `lua/diffs/gitsigns.lua` which patches gitsigns' `Popup.create` and
`Popup.update` to intercept blame popups. Parses `Hunk N of M` sections
from the popup buffer, clears gitsigns' own `gitsigns_popup` namespace
on the diff region, and applies `highlight_hunk` with manual
`@diff.plus`/`@diff.minus` prefix extmarks. Uses a separate
`diffs-gitsigns` namespace to avoid colliding with the main decoration
provider.

Enabled via `vim.g.diffs = { gitsigns = true }`. Wired in
`plugin/diffs.lua` with a `User GitAttach` lazy-load retry for when
gitsigns loads after diffs.nvim. Config plumbing adds
`get_highlight_opts()` as a public getter, replacing the
`debug.getupvalue` hack used by the standalone `blame_hl.nvim` plugin.

Closes #155.
2026-03-06 08:42:02 -05:00
Barrett Ruth
58589947e8
fix(highlight): use theme-agnostic fallbacks and retry when Normal has no background (#153)
## Problem

Highlight group fallbacks in `compute_highlight_groups` were hardcoded
to
catppuccin mocha colors, producing wrong results for any other
colorscheme
when `Normal.bg` is nil. This happens on transparent terminals or when
the
colorscheme loads after the first diff buffer opens.

## Solution

Replace hardcoded fallbacks with `vim.o.background`-aware neutral
values.
When `Normal.bg` is still absent after initial computation, schedule a
single
deferred retry via `vim.schedule` that recomputes and invalidates all
attached
buffer caches. Document the load-order requirement in the setup section.
2026-03-05 19:50:22 -05:00
Barrett Ruth
e7d56e3bbe
feat(highlight): wire highlights.context into treesitter pipeline (#151)
Some checks are pending
luarocks / quality (push) Waiting to run
luarocks / publish (push) Blocked by required conditions
## Problem

`highlights.context.enabled` and `highlights.context.lines` were
defined, validated, and range-checked but never read during
highlighting. Hunks inside incomplete constructs (e.g., a table literal
or function body whose opening is beyond the hunk's own context lines)
parsed incorrectly because treesitter had no surrounding code.

## Solution

`compute_hunk_context` in `init.lua` reads the working tree file using
the hunk's `@@ +start,count @@` line numbers to collect up to `lines`
(default 25) surrounding code lines in each direction. Files are read
once via `io.open` and cached across hunks in the same file.
`highlight_treesitter` in `highlight.lua` accepts an optional context
parameter that prepends/appends context lines to the parse string and
offsets capture rows by the prefix count, so extmarks only land on
actual hunk lines. Wired through `highlight_hunk` for the two
code-language treesitter calls (not headers, not `highlight_text`, not
vim syntax).

Closes #148.
2026-03-05 11:14:31 -05:00
Barrett Ruth
29e624d9f0
feat: enable vim syntax fallback by default (#152)
## Problem

Languages without a treesitter parser (COBOL, Fortran, etc.) got no
syntax highlighting because \`highlights.vim.enabled\` defaulted to
\`false\`.

## Solution

Flip the default to \`true\`. The vim syntax path is already deferred
via \`vim.schedule\` so it never blocks the first paint. \`max_lines =
200\` stays unchanged — appropriate given the ~30x slower per-hunk cost
vs treesitter.
2026-03-05 11:13:28 -05:00
Barrett Ruth
7a3c4ea01e
docs: add table of contents to vimdoc (#146)
## Problem

The vimdoc has 16 sections but no table of contents, making it hard
to navigate with `:help diffs`.

## Solution

Add a numbered `CONTENTS` section with dot-leader formatting and
`|tag|` links to each existing section, matching the style used in
the project's other plugins.
2026-03-05 01:31:15 -05:00
Barrett Ruth
700a9a21ad
fix(conflict)!: change default nav keymaps from ]x/[x to ]c/[c (#132)
## Problem

The default conflict navigation keymaps `]x`/`[x` are non-standard. Vim
natively uses `]c`/`[c` for diff navigation, so the same keys are far
more
intuitive for conflict jumping.

## Solution

Change the defaults for `conflict.keymaps.next` and
`conflict.keymaps.prev`
to `]c` and `[c`. This is a breaking change for users relying on the
previous
defaults without explicit configuration.
2026-02-24 12:07:54 -05:00
Barrett Ruth
b1abfe4f4a
feat: remove config deprecation in v0.3.0 (#129) 2026-02-18 13:34:43 -05:00
Barrett Ruth
cbc93f9eaa
refactor: remove enabled field from fugitive/neogit config (#126)
## Problem

Users had to pass `enabled = true` or `enabled = false` inside
fugitive/neogit config tables, which was redundant — table presence
already implied the integration should be active.

## Solution

Remove the `enabled` field from the public API. Table presence now
implies enabled, `false` disables, `true` expands to sub-defaults.
The `enabled` field is still accepted for backward compatibility.

Added 20 `compute_filetypes` tests covering all config shapes (true,
false, table, nil, backward-compat enabled field). Updated docs
and type annotations.
2026-02-15 19:42:38 -05:00
Barrett Ruth
3d640c207b
feat: add neogit support (#117)
## TODO

1. docs (vimdoc + readme) - this is a non-trivial feature
2. push luarocks version

## Problem

diffs.nvim only activates on `fugitive`, `git`, and `gitcommit`
filetypes.
Neogit uses its own custom filetypes (`NeogitStatus`,
`NeogitCommitView`,
`NeogitDiffView`) and doesn't set `b:git_dir`, so the plugin never
attaches
and repo root resolution fails for filetype detection within diff hunks.

## Solution

Two changes:

1. **`lua/diffs/init.lua`** — Add the three Neogit filetypes to the
default
`filetypes` list. The `FileType` autocmd in `plugin/diffs.lua` already
handles them correctly since the `is_fugitive_buffer` guard only applies
   to the `git` filetype.

2. **`lua/diffs/parser.lua`** — Add a CWD-based fallback in
`get_repo_root()`.
After the existing `b:diffs_repo_root` and `b:git_dir` checks, fall back
to
`vim.fn.getcwd()` via `git.get_repo_root()` (already cached). Without
this,
   the parser can't resolve filetypes for files in Neogit buffers.

Neogit's expanded diffs use standard unified diff format, so the parser
handles
them without modification.

Closes #110.
2026-02-14 17:12:01 -05:00
3990014a93
feat: add support for diff and other filetypes 2026-02-12 18:04:47 -05:00
Barrett Ruth
9a0b812f69
performance improvements (#116)
closes #111
2026-02-12 16:59:13 -05:00
Barrett Ruth
35067151e4
fix: pre-release cleanup for v0.2.0 (#102)
## Problem

Three minor issues remain before the v0.2.0 release:

1. Git quotes filenames containing spaces, unicode, or special
characters
   in the fugitive status buffer. `parse_file_line` passed the quotes
   through verbatim, causing file-not-found errors on diff operations.

2. Navigation wrap-around in both conflict and merge modules was silent,
giving no indication when jumping past the last/first item back to the
   beginning/end.

3. `resolved_hunks` and `(resolved)` virtual text in the merge module
persisted across buffer re-reads, showing stale markers for hunks that
   were no longer resolved.

## Solution

1. Add an `unquote()` helper to fugitive.lua that strips surrounding
   quotes and unescapes `\\`, `\"`, `\n`, `\t`, and octal `\NNN`
   sequences. Applied to both return paths in `parse_file_line`.

2. Add `vim.notify` before the wrap-around jump in all four navigation
   functions (`goto_next`/`goto_prev` in conflict.lua and merge.lua).

3. Clear `resolved_hunks[bufnr]` and the merge namespace at the top of
   `setup_keymaps` so each buffer init starts fresh.

Closes #66
2026-02-09 15:08:36 -05:00
Barrett Ruth
b5d28e9f2b
feat(conflict): add virtual text formatting and action lines (#101)
## Problem

Conflict resolution virtual text only showed plain "current" /
"incoming"
labels with no keymap hints. Users had no way to discover available
resolution keymaps without reading docs.

## Solution

Default virtual text labels now include keymap hints: `(current — doo)`
and
`(incoming — dot)`. A new `format_virtual_text` config option lets users
customize or hide labels entirely. A new `show_actions` option (off by
default) renders a codelens-style action line above each `<<<<<<<`
marker
listing all enabled resolution keymaps. Merge diff views also gain hunk
hints on `@@` header lines showing available keymaps.

New config fields: `conflict.format_virtual_text` (function|nil),
`conflict.show_actions` (boolean). New highlight group:
`DiffsConflictActions`.
2026-02-09 13:55:13 -05:00
Barrett Ruth
a2053a132b
feat: unified diff conflict resolution for unmerged files (#99)
## Problem

Pressing `du` on a `UU` (unmerged) file in the fugitive status buffer
had no
effect. There was no way to see a proper ours-vs-theirs diff with syntax
highlighting and intra-line changes, or to resolve conflicts from within
a
unified diff view.

Additionally, pressing `du` on a section header containing only unmerged
files
showed "no changes in section" because `git diff` produces combined
(`diff --cc`)
output for unmerged files, which was stripped entirely.

## Solution

Fetch `:2:` (ours) and `:3:` (theirs) from the git index and generate a
standard
unified diff. The existing highlight pipeline (treesitter + intra-line)
applies
automatically. Resolution keymaps (`doo`/`dot`/`dob`/`don`) on hunks in
the diff
view write changes back to the working file's conflict markers.
Navigation
(`]x`/`[x`) jumps between unresolved conflict hunks.

For section diffs, combined diff entries are now replaced with generated
ours-vs-theirs unified diffs instead of being stripped.

Works for merge, cherry-pick, and rebase conflicts — git populates
`:2:`/`:3:`
the same way for all three.

Closes #61
2026-02-09 12:21:13 -05:00
Barrett Ruth
49fc446aae
doc: add plug mappings for merge conflict resolution (#98) 2026-02-08 16:29:39 -05:00
74c2dd4c7a docs: document conflict resolution config and highlight groups 2026-02-07 17:39:35 -05:00
6b4953bf41 docs: document q keymap and window reuse behavior 2026-02-07 16:54:54 -05:00
a0870a7892 feat(highlight): add highlights.overrides config table
Problem: users had no config-level way to override computed highlight
groups and had to call nvim_set_hl externally.

Solution: add highlights.overrides table that maps group names to
highlight definitions. Overrides are applied after all computed groups
without default = true, so they always win over both computed defaults
and colorscheme definitions.
2026-02-07 15:49:56 -05:00
b7477e3af2 feat(highlight): add configurable blend alpha
Problem: the character-level blend intensity was hardcoded to 0.6,
giving users no way to tune how strongly changed characters stand out
from the line-level background.

Solution: add highlights.blend_alpha config option (number, 0-1,
default 0.6) with type validation and range check.
2026-02-07 15:46:47 -05:00
8e0c41bf6b fix(highlight): add default flag to DiffsDiff* groups
Problem: DiffsDiff* highlight groups lacked default = true, making them
impossible for colorschemes to override, inconsistent with the fugitive
unified diff groups which already had it.

Solution: add default = true to all four DiffsDiffAdd, DiffsDiffDelete,
DiffsDiffChange, and DiffsDiffText nvim_set_hl calls.
2026-02-07 15:45:34 -05:00
bcc70280fb docs: fix vim.max_lines default in config example
Problem: the vimdoc config example showed max_lines = 500 under vim,
but the actual default in init.lua is 200.

Solution: change the example to match the real default.
2026-02-07 15:44:56 -05:00
5cfa91039b fix(highlight): use correct line number gutter colors
Problem: DiffsAddNr/DiffsDeleteNr used raw diffAdded/diffRemoved
foreground and the word-level blended background, instead of matching
the line-level and character-level highlight groups.

Solution: set gutter bg to the line-level blend (DiffsAdd/DiffsDelete)
and fg to the character-level blend (DiffsAddText/DiffsDeleteText).
2026-02-07 15:29:19 -05:00
d10eaed6ac fix(highlight): reduce word-level blend alpha and match line number bg
Problem: word-level diff highlights were too intense at 70% alpha, and
line number backgrounds used the line-level blend instead of matching
the word-level highlights.

Solution: reduce DiffsAddText/DiffsDeleteText blend alpha from 0.7 to
0.6 and use the same blended background for DiffsAddNr/DiffsDeleteNr.
2026-02-07 15:23:14 -05:00
f6c0738384 docs: credit phanen for treesitter injection support 2026-02-07 14:32:04 -05:00
97a6fb2bd7 feat: add <Plug> mappings
Problem: users who want keybindings must wrap commands in closures.
There is no stable public API for key binding.

Solution: define <Plug> mappings in the plugin file and document them
in a new MAPPINGS section in the vimdoc.
2026-02-07 14:12:49 -05:00
9e32384f18 refactor: change highlights.context config to table structure
Problem: highlights.context was a plain integer, inconsistent with the
table structure used by treesitter, vim, and intra sub-configs.

Solution: change to { enabled = true, lines = 25 } with full
vim.validate() coverage matching the existing pattern.
2026-02-07 13:16:34 -05:00
2e1ebdee03 feat(highlight): add treesitter context padding from disk
Problem: treesitter parses each diff hunk in isolation, so incomplete
syntax constructs at hunk boundaries (e.g., a function definition with
no body) produce ERROR nodes and drop captures.

Solution: read N lines from the on-disk file before/after each hunk and
prepend/append them as unmapped padding lines. The line_map guard in
highlight_treesitter skips extmarks for unmapped lines, so padding
provides syntax context without visual output. Controlled by
highlights.context (default 25, 0 to disable). Also applies to the vim
syntax fallback path via a leading_offset filter.
2026-02-07 13:05:53 -05:00
10af59a70d feat(config): replace algorithm 'auto'/'native' with 'default'/'vscode'
'default' inherits algorithm and linematch from diffopt, 'vscode' uses
the FFI library. Removes the need for diffs.nvim to duplicate settings
that users already control globally.
2026-02-06 21:23:40 -05:00
f1c13966ba fix(highlight): use diffAdded/diffRemoved fg for char-level backgrounds
The previous 70% alpha blend of DiffAdd bg was nearly identical to the
40% line-level blend, making char-level highlights invisible. Now blends
the bright diffAdded/diffRemoved foreground color (same base as line
number fg) into the char-level bg, matching GitHub/VSCode intensity.

Also bumps intra.max_lines default from 200 to 500.
2026-02-06 14:43:23 -05:00
997bc49f8b feat(highlight): add character-level intra-line diff highlighting
Line-level backgrounds (DiffsAdd/DiffsDelete) now get a second tier:
changed characters within modified lines receive an intense background
overlay (DiffsAddText/DiffsDeleteText at 70% alpha vs 40% for lines).
Treesitter foreground colors show through since the extmarks only set bg.

diff.lua extracts contiguous -/+ change groups from hunk lines and diffs
each group byte-by-byte using vim.diff(). An optional libvscodediff FFI
backend (lib.lua) auto-downloads the .so from codediff.nvim releases and
falls back to native if unavailable.

New config: highlights.intra.{enabled, algorithm, max_lines}. Gated by
max_lines (default 200) to avoid stalling on huge hunks. Priority 201
sits above treesitter (200) so the character bg always wins.

Closes #60
2026-02-06 13:53:58 -05:00
d8332895f3 docs: add fugitive status buffer keymaps documentation
Document the du/dU keymaps for unified diffs in vim-fugitive status
buffers, including behavior by file status and configuration options.
2026-02-04 23:37:39 -05:00
045a9044b5 feat: add :Gdiff, :Gvdiff, :Ghdiff commands for unified diff view
Compares current buffer against any git revision (default HEAD), opens result
with full diffs.nvim syntax highlighting. Follows fugitive convention:
:Gdiff/:Gvdiff open vertical split, :Ghdiff opens horizontal split.
2026-02-04 19:52:17 -05:00
a25f1e9d84 feat: treesitter highlighting for diff headers
Apply treesitter highlighting to diff metadata lines (diff --git, index,
---, +++) using the diff language parser. Header info is attached only
to the first hunk of each file to avoid duplicate highlighting.

Based on PR #52 by @phanen with fixes:
- header_lines now only contains diff metadata, not hunk content
- header info attached only to first hunk per file
- removed arbitrary hunk count restriction
2026-02-04 15:11:35 -05:00
da7b76555a docs: add incomplete syntax context as known limitation
Treesitter parses diff hunks in isolation without surrounding code
context, which can cause incorrect highlighting when hunks show partial
blocks (e.g., adding lines inside `return { ... }` without seeing the
`return`). Document this as a known limitation in README and vimdoc.
2026-02-04 13:16:22 -05:00
2b38874699 feat(config): use vim.g over .setup() 2026-02-03 16:18:55 -05:00
f71b0f54c5 fix: remove useless enabled flag 2026-02-03 02:50:25 -05:00
2e5400f9c0 fix(doc): move hl documentation to the vimdoc 2026-02-03 01:33:31 -05:00
188de47d77 feat: docs update (vim-fugitive is optional) 2026-02-03 01:07:37 -05:00
67116f38bc feat: rename everything 2026-02-02 22:09:13 -05:00
f865c894a5 fix(config): remove useless config option 2026-02-02 18:05:31 -05:00
ec028dd0e5 feat(doc): more updates 2026-02-02 16:51:48 -05:00
e2a62a6aa5 feat: doc updates and cleanups 2026-02-02 16:39:37 -05:00
a082b9c4b3 feat: update 2026-02-02 15:34:37 -05:00
69943a09c4 feat: cleanup config options 2026-02-02 15:18:25 -05:00
dabf2e2cc9 feat: highlight improvemnets 2026-02-02 13:53:43 -05:00
6a64a380b0 conceal back to level 1 2026-02-02 13:26:19 -05:00