Add gutter signs support - #451
Open
richardgill wants to merge 18 commits into
Open
Conversation
This reverts commit 81e0032.
…to native-gutter-signs
# Conflicts: # doc/tags # lua/codediff/ui/core.lua # lua/codediff/ui/move.lua # lua/codediff/ui/view/side_by_side.lua
# Conflicts: # tests/ui/highlights_spec.lua
…to native-gutter-signs
richardgill
marked this pull request as ready for review
July 27, 2026 05:44
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR adds configurable gutter signs and changed-line number highlighting.
This allows users to:
+and-signs in the sign column.This PR uses ordinary persistent ranged extmarks. Changed signs and optional blank blocker signs can hide lower-priority signs from other plugins without modifying their settings or extmarks.
Persistent signs belong to the buffer and are visible in every window displaying the buffer. This implementation clears the signs when its tab is left or the diff is closed, then renders them again when its tab is re-entered.
Screenshots
Both screenshots compare the same
BASErevision to the working tree with an identical fixture, viewport, colorscheme, and cursor position. The unchangedgetStatusline differs fromHEAD, so Gitsigns marks it even though CodeDiff considers it unchanged. ThegetMessagereplacement demonstrates the changed-line gutter formatting.Before
The lower-priority Gitsigns marker remains visible in the right pane.
After
The unchanged-line blocker hides the Gitsigns marker. The replacement hunk shows the insert/delete signs, sign-column backgrounds, and changed line-number foregrounds.
None of these approaches can attach a sign to an individual
virt_linesrow because virtual rows do not have their own buffer coordinates. I've filed an issue in neovim/neovim#40987. The PR therefore does not render gutter signs in inline diff layouts.Other options considered
Ephemeral extmarks
A decoration provider could create extmarks only for the current redraw, making signs window-local without storing or clearing them.
This approach cannot implement the requested gutter behavior today. Neovim ignores
sign_text,sign_hl_group,line_hl_group, andnumber_hl_groupon ephemeral extmarks, so it cannot render the signs and number highlights requested by #454 or the blank blocker signs used to override lower-priority signs for #473. This is tracked in neovim/neovim#32936 and was reproduced on Neovim 0.11.5 and 0.12.2.Fixing #32936 would make ephemeral extmarks suitable for real buffer lines, including blocker signs. It would still not allow signs on individual virtual lines.
Window-scoped extmark namespaces
Neovim 0.11 introduced
nvim__ns_set(namespace, { wins = { winid } }), which can restrict persistent extmarks to selected windows. Combined with persistent signs and blockers, this could implement #454 and #473 on real buffer lines without displaying CodeDiff signs in unrelated windows.CodeDiff does not use this approach because the API is explicitly experimental and unstable, and depending on it would raise CodeDiff's current Neovim 0.9 requirement. Namespace scoping also does not suppress signs from other plugins by itself: #473 still requires higher-priority CodeDiff signs and blank blocker signs. It also cannot place signs on individual virtual lines.
This approach can be reconsidered if Neovim exposes a stable supported mechanism.
Fixes #454
Fixes #473