bug: header line backgrounds don't cover quote prefix on email-quoted diffs #64

Closed
opened 2026-09-21 18:11:54 +00:00 by barrettruth · 3 comments
Owner

Original issue: barrettruth/diffs.nvim#142
Original author: barrettruth
Original date: 2026-03-04T05:59:37Z

Problem

When parsing email-quoted diffs (> diff --git ...), the diff treesitter grammar applies @diff.plus.diff and @diff.minus.diff captures to +++/--- header lines. These captures start at col = quote_width (e.g. col 2 for > prefix), leaving the quote prefix area (col 0–1) with no background highlight.

The non-quoted version covers the full line (col 0 to EOL), so the visual difference is jarring — the quoted header lines have a colored background on only part of the line.

Affected lines: > --- a/..., > +++ b/....

Proposed fix

When quote_width > 0, detect ---/+++ header lines and add a full-line background extmark (hl_eol = true, col 0) matching the @diff.plus/@diff.minus highlight, just like hunk body lines already get DiffsAdd/DiffsDelete line backgrounds. The > prefix stays visible in the buffer — buffers should show their actual content — but the background covers the full line.

Conceal is the wrong approach. Hiding the quote prefix, if desired, should be opt-in via hide_prefix, not forced.

Context

Introduced by the email-quoted diff parsing feature (#141). The core parsing and highlight offset logic works correctly — this is a visual polish issue specific to header lines.

> Original issue: barrettruth/diffs.nvim#142 > Original author: `barrettruth` > Original date: 2026-03-04T05:59:37Z ## Problem When parsing email-quoted diffs (`> diff --git ...`), the diff treesitter grammar applies `@diff.plus.diff` and `@diff.minus.diff` captures to `+++`/`---` header lines. These captures start at `col = quote_width` (e.g. col 2 for `> ` prefix), leaving the quote prefix area (col 0–1) with no background highlight. The non-quoted version covers the full line (col 0 to EOL), so the visual difference is jarring — the quoted header lines have a colored background on only part of the line. Affected lines: `> --- a/...`, `> +++ b/...`. ## Proposed fix When `quote_width > 0`, detect `---`/`+++` header lines and add a full-line background extmark (`hl_eol = true`, col 0) matching the `@diff.plus`/`@diff.minus` highlight, just like hunk body lines already get `DiffsAdd`/`DiffsDelete` line backgrounds. The `> ` prefix stays visible in the buffer — buffers should show their actual content — but the background covers the full line. Conceal is the wrong approach. Hiding the quote prefix, if desired, should be opt-in via `hide_prefix`, not forced. ## Context Introduced by the email-quoted diff parsing feature (#141). The core parsing and highlight offset logic works correctly — this is a visual polish issue specific to header lines.
barrettruth 2026-09-21 18:11:54 +00:00
  • closed this issue
  • added the
    bug
    label
Author
Owner

Original comment: barrettruth/diffs.nvim#142, comment 3995757027
Original author: barrettruth
Original date: 2026-03-04T07:19:32Z

Progress

Investigated and partially fixed. The issue was deeper than just header line backgrounds.

Root cause

DiffsClear only defined fg (Normal foreground). In Neovim's extmark priority model, each highlight attribute (fg, bg, bold, etc.) is resolved independently across the priority stack. A higher-priority extmark that only defines fg does not suppress a lower-priority extmark's bg. This meant native treesitter's wrong backgrounds (from misinterpreting > -prefixed lines) bled through everywhere DiffsClear was applied.

Fixes applied

  1. DiffsClear now defines both fg and bg (init.lua) — suppresses native treesitter backgrounds
  2. Header lines get DiffsClear at col 0 when qw > 0 — clears native TS before re-applying diff grammar treesitter at elevated priority (199 vs default 100)
  3. @@ line gets explicit highlighting when qw > 0 — was previously unhandled (not in header_lines, not a body line), now gets DiffsClear + diff grammar treesitter
  4. Body line > prefix gets DiffsClear (col 0→qw) — suppresses native TS on the quote prefix

Remaining issues

  1. 1-col gap at col qw on context lines: Between prefix DiffsClear (0→qw) and content DiffsClear (pw+qw→EOL), context body lines have a 1-column gap where native TS bg can bleed through. Masked on +/- lines by DiffsAdd/DiffsDelete at p200.
  2. Bare > context lines: May not get full DiffsClear coverage (line_len ≤ pw so content DiffsClear never fires).
  3. Diff prefix marker color: +/- at col qw lacks diff-grammar fg in quoted mode (native TS can't parse > +...).

Config option idea

Should there be a config option to hide the > quote prefix (via hide_prefix or a new hide_quote_prefix)? The buffer content stays unchanged, but the prefix would be visually concealed. This is separate from the background fix.

> Original comment: barrettruth/diffs.nvim#142, comment 3995757027 > Original author: `barrettruth` > Original date: 2026-03-04T07:19:32Z ## Progress Investigated and partially fixed. The issue was deeper than just header line backgrounds. ### Root cause `DiffsClear` only defined `fg` (Normal foreground). In Neovim's extmark priority model, each highlight attribute (fg, bg, bold, etc.) is resolved independently across the priority stack. A higher-priority extmark that only defines `fg` does **not** suppress a lower-priority extmark's `bg`. This meant native treesitter's wrong backgrounds (from misinterpreting `> `-prefixed lines) bled through everywhere `DiffsClear` was applied. ### Fixes applied 1. **`DiffsClear` now defines both `fg` and `bg`** (init.lua) — suppresses native treesitter backgrounds 2. **Header lines get `DiffsClear` at col 0** when `qw > 0` — clears native TS before re-applying diff grammar treesitter at elevated priority (199 vs default 100) 3. **`@@` line gets explicit highlighting** when `qw > 0` — was previously unhandled (not in `header_lines`, not a body line), now gets `DiffsClear` + diff grammar treesitter 4. **Body line `> ` prefix gets `DiffsClear`** (col 0→qw) — suppresses native TS on the quote prefix ### Remaining issues 1. **1-col gap at col `qw` on context lines**: Between prefix DiffsClear (0→qw) and content DiffsClear (pw+qw→EOL), context body lines have a 1-column gap where native TS bg can bleed through. Masked on +/- lines by DiffsAdd/DiffsDelete at p200. 2. **Bare `>` context lines**: May not get full DiffsClear coverage (line_len ≤ pw so content DiffsClear never fires). 3. **Diff prefix marker color**: `+`/`-` at col `qw` lacks diff-grammar fg in quoted mode (native TS can't parse `> +...`). ### Config option idea Should there be a config option to hide the `> ` quote prefix (via `hide_prefix` or a new `hide_quote_prefix`)? The buffer content stays unchanged, but the prefix would be visually concealed. This is separate from the background fix.
Author
Owner

Original comment: barrettruth/diffs.nvim#142, comment 3995763970
Original author: barrettruth
Original date: 2026-03-04T07:21:17Z

NOTE: we see a green bg flash on the second code portion of

This is a normal diff (parses fine):

diff --git a/foo.py b/foo.py
index 3c507e6..a41a179 100644
--- a/foo.py
+++ b/foo.py
@@ -1,4 +1,5 @@
 from typing import Annotated

 class Foo:
-    p
+    def bar(self) -> None:
+        pass

---

This is the same diff in an email reply (currently produces 0 hunks):

Looks good, one nit:

> diff --git a/foo.py b/foo.py
> index 3c507e6..a41a179 100644
> --- a/foo.py
> +++ b/foo.py
> @@ -1,4 +1,5 @@
>  from typing import Annotated
>
>  class Foo:
> -    p
> +    def bar(self) -> None:
> +        pass

Maybe rename `p` to something descriptive?

in the current impl, indicating inconsistent hl (this not seen in section 1) and possibly related to #143

> Original comment: barrettruth/diffs.nvim#142, comment 3995763970 > Original author: `barrettruth` > Original date: 2026-03-04T07:21:17Z NOTE: we see a green bg flash on the second code portion of ```diff This is a normal diff (parses fine): diff --git a/foo.py b/foo.py index 3c507e6..a41a179 100644 --- a/foo.py +++ b/foo.py @@ -1,4 +1,5 @@ from typing import Annotated class Foo: - p + def bar(self) -> None: + pass --- This is the same diff in an email reply (currently produces 0 hunks): Looks good, one nit: > diff --git a/foo.py b/foo.py > index 3c507e6..a41a179 100644 > --- a/foo.py > +++ b/foo.py > @@ -1,4 +1,5 @@ > from typing import Annotated > > class Foo: > - p > + def bar(self) -> None: > + pass Maybe rename `p` to something descriptive? ``` in the current impl, indicating inconsistent hl (this not seen in section 1) and possibly related to #143
Author
Owner

Original comment: barrettruth/diffs.nvim#142, comment 4005907383
Original author: barrettruth
Original date: 2026-03-05T15:31:37Z

closed in #149

> Original comment: barrettruth/diffs.nvim#142, comment 4005907383 > Original author: `barrettruth` > Original date: 2026-03-05T15:31:37Z closed in #149
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
barrettruth/diffs.nvim#64
No description provided.