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.
This commit is contained in:
Barrett Ruth 2026-02-07 13:05:53 -05:00
parent ba1f830629
commit 2e1ebdee03
7 changed files with 308 additions and 24 deletions

View file

@ -56,6 +56,7 @@ Configuration is done via `vim.g.diffs`. Set this before the plugin loads:
highlights = {
background = true,
gutter = true,
context = 25,
treesitter = {
enabled = true,
max_lines = 500,
@ -113,6 +114,16 @@ Configuration is done via `vim.g.diffs`. Set this before the plugin loads:
Highlight line numbers with matching colors.
Only visible if line numbers are enabled.
{context} (integer, default: 25)
Number of lines to read from the source file
before and after each hunk for syntax parsing
context. Improves accuracy at hunk boundaries
where incomplete constructs (e.g., a function
definition with no body) would otherwise confuse
the parser. Set to 0 to disable. Lines are read
from disk with early exit — cost scales with the
context value, not file size.
{treesitter} (table, default: see below)
Treesitter highlighting options.
See |diffs.TreesitterConfig| for fields.
@ -305,14 +316,15 @@ KNOWN LIMITATIONS *diffs-limitations*
Incomplete Syntax Context ~
*diffs-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 or unusual highlighting.
Treesitter parses each diff hunk in isolation. To provide surrounding code
context, diffs.nvim reads lines from disk before and after each hunk
(controlled by `highlights.context`, default 25). This resolves most boundary
issues where incomplete constructs (e.g., a function definition at the edge
of a hunk with no body) would confuse the parser.
This is inherent to parsing code fragments. No diff tooling solves this
problem without significant complexity—the parser simply doesn't have enough
information to understand the full syntactic structure.
Set `highlights.context = 0` to disable context padding and restore the
previous behavior. In rare cases, context padding may not help if the
relevant surrounding code is very far from the hunk boundaries.
Syntax Highlighting Flash ~
*diffs-flash*