Skip to content

Commit 55cd451

Browse files
committed
Merge pull request emacsorphanage#247 from alberti42/fix/git-gutter-faces
docs: theming the gutter column background
2 parents ec7d71b + 8f75b24 commit 55cd451

1 file changed

Lines changed: 116 additions & 0 deletions

File tree

‎README.md‎

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,122 @@ Default value of `git-gutter:separator-sign` is `nil`.
324324
Please set `git-gutter:always-show-separator` to non-nil, if you want to show
325325
separator always.
326326

327+
### Theming the gutter column background
328+
329+
Many modern themes — for example the built-in `modus-operandi` and
330+
`modus-vivendi` (see https://github.com/protesilaos/modus-themes) — give the
331+
line-number column a background color that differs from the main buffer
332+
background. git-gutter places its change indicators in that same left-margin
333+
area, so when a theme colors the line numbers, the gutter should share that
334+
background for the column to look uniform.
335+
336+
git-gutter uses a dedicated face for each type of change: `git-gutter:added`
337+
for added lines, `git-gutter:modified` for modified lines, and
338+
`git-gutter:deleted` for deleted lines. On those rows, the sign character
339+
configured under [Look and feel](#look-and-feel) (e.g. `git-gutter:added-sign`)
340+
is drawn in the foreground color of the corresponding face, against that face's
341+
background color.
342+
343+
How the *remaining* rows — those with no changes — get their background
344+
depends on your Emacs version.
345+
346+
#### Emacs 31.1 and later: use the built-in `margin` face
347+
348+
Emacs 31.1 introduced a new basic face called `margin` (see
349+
[bug #80693](https://debbugs.gnu.org/cgi/bugreport.cgi?bug=80693)). The
350+
display engine fills every empty cell in the left and right window margins
351+
with this face's background. Content written into the margin (such as a
352+
git-gutter sign) is drawn with its own face, but where that face does not
353+
specify a background of its own, it inherits from the `margin` face. So,
354+
configuring `margin` once yields a visually uniform gutter column background,
355+
without any per-package further customization.
356+
357+
Note that the line-number area is a separate display column with its own
358+
face (`line-number`); the `margin` face does not affect it. Most users will
359+
want the two backgrounds to match visually, when the line numbers are displayed.
360+
This is something themes can arrange and the example below does explicitly.
361+
The `margin` face was added in May 2026, so it will take time before third-party
362+
themes ship explicit support — until then, customizing it yourself is the way to go.
363+
364+
To match the line-number column without hardcoding a color:
365+
366+
```lisp
367+
(defun my/margin-update-face ()
368+
(let ((bg (face-background 'line-number nil t)))
369+
(when bg
370+
(set-face-background 'margin bg))))
371+
372+
(add-hook 'enable-theme-functions (lambda (&rest _) (my/margin-update-face)))
373+
(my-margin-update-face)
374+
```
375+
376+
With this in place, you do **not** need to set `git-gutter:unchanged-sign` or
377+
`git-gutter:always-show-separator` just to fill the gutter background — and
378+
on large files you should actively *avoid* them for that purpose, because
379+
each requires git-gutter to install an overlay on every line of the buffer.
380+
That cost becomes prohibitive on files with tens of thousands of lines (e.g.
381+
Emacs' own `xdisp.c`); the `margin` face approach moves the work to the C
382+
display loop, where it costs nothing per line.
383+
384+
If you want a visual gap between the change indicator and the buffer text,
385+
the right approach on 31.1+ is to widen the gutter — for example
386+
`(setq git-gutter:window-width 2)` — and let the `margin` face fill the
387+
extra column for free. `git-gutter:unchanged-sign` and
388+
`git-gutter:separator-sign` retain their original meaning only when you
389+
actually want a visible character drawn on every unchanged line.
390+
391+
#### Emacs 30.x and earlier: fill via git-gutter's own faces
392+
393+
Before the `margin` face existed, an unwritten margin cell fell back to the
394+
default frame or terminal background. git-gutter had no way to influence
395+
cells it did not render into, so a uniform gutter background required filling
396+
those cells via git-gutter itself, using `git-gutter:unchanged` (when
397+
`git-gutter:unchanged-sign` is set) or `git-gutter:separator` (when
398+
`git-gutter:always-show-separator` is non-nil).
399+
400+
**Important gotcha:** `git-gutter:window-width` reserves space for the gutter
401+
column in every buffer, but on unchanged rows nothing is written into that space
402+
unless one of the two signs above is configured. A cell that is reserved but
403+
never written falls back to the default frame or terminal background — so
404+
setting a background color on `git-gutter:unchanged` or `git-gutter:separator`
405+
has no visible effect unless the corresponding sign is also set (even a single
406+
space `" "`). Once a sign is in place, those two faces control the background
407+
of every cell not covered by a diff sign, making them the key to a visually
408+
uniform column.
409+
410+
To keep the gutter background in sync with the active theme without hardcoding
411+
a color, derive it from the `line-number` face:
412+
413+
```lisp
414+
(defun my-git-gutter-update-faces ()
415+
(let ((bg (face-background 'line-number nil t)))
416+
(when bg
417+
;; All gutter cells share the same background as the line-number column.
418+
(dolist (face '(git-gutter:added git-gutter:modified git-gutter:deleted
419+
git-gutter:unchanged git-gutter:separator))
420+
(set-face-background face bg))
421+
;; Make unchanged and separator invisible by matching foreground to background.
422+
(dolist (face '(git-gutter:unchanged git-gutter:separator))
423+
(set-face-foreground face bg)))))
424+
425+
;; Re-run after every theme change (Emacs 29+).
426+
(add-hook 'enable-theme-functions (lambda (&rest _) (my-git-gutter-update-faces)))
427+
(my-git-gutter-update-faces)
428+
```
429+
430+
#### Recommendation for theme designers
431+
432+
On Emacs 31.1+, themes should set the background of the `margin` face —
433+
typically matching `line-number`'s background, or a related accent. This
434+
single setting covers every margin cell in every buffer.
435+
436+
For backward compatibility with Emacs ≤30.x, themes that include explicit
437+
support for git-gutter should additionally set the background of
438+
`git-gutter:unchanged` and `git-gutter:separator` to the same color. Leaving
439+
these backgrounds unspecified is the most common cause of a broken-looking
440+
gutter column on those older Emacs versions: an empty stripe drawn in the
441+
frame's default background, mismatched against the line-number column.
442+
327443
### Hide gutter if there are no changes
328444

329445
Hide gutter when there are no changes if `git-gutter:hide-gutter` is non-nil.

0 commit comments

Comments
 (0)