Colors in `vterm` do not update after loading a new theme
Description
When I switch themes in Emacs using auto-dark, the colors in vterm do not update to reflect the new theme's color scheme. The vterm-color-* faces appear to retain the old theme's colors until I trigger some external action, like resizing the window, which forces a refresh and updates the colors correctly.
I've tried adding hooks to after-load-theme-hook to refresh or redraw vterm buffers programmatically, but none of the solutions I've attempted have worked reliably. Some of these approaches include:
- Adjusting
vterm-color-*faces directly. - Triggering a redisplay using
force-window-updateorredisplay. - Attempting to resize the
vtermbuffer programmatically.
However, these methods either fail to refresh the colors or result in unexpected issues, such as loss of terminal content.
Question
Is there an existing way to programmatically make vterm refresh its display and adjust its colors after switching themes? If not, could you suggest a workaround or a direction for resolving this issue?
Steps to Reproduce
- Open a
vtermbuffer. - Load a new theme with
M-: (load-theme 'theme-name). - Observe that the colors in the
vtermbuffer do not update until a manual action (e.g., resizing the window) is performed.
Expected Behavior
The vterm colors should automatically adjust to match the new theme when the theme is switched.
Actual Behavior
The vterm colors do not update, and the old theme's colors persist until the buffer is redrawn by resizing or other indirect means.
Environment
- Emacs Version: 29.4
- OS: Fedora 41 Workstation
- vterm Version: fd50624
- Theme(s): modus-themes, leuven
Additional Notes
If a solution or workaround exists, I would be happy to implement it. Alternatively, if this is a missing feature, I’d be glad to contribute by testing or providing additional details if needed.
@adonig I got some workaround working via triggering the buffer size. The thing is that is_invalidate flag tracked on the C module side and it will ignore any redisplay requests if it thinks buffer isn't changed. There are few ways to trigger it and seems like term_resize is the safest one.
(add-hook 'enable-theme-functions
(lambda (_theme)
(dolist (buf (buffer-list))
(with-current-buffer buf
(when (derived-mode-p 'vterm-mode)
(let* ((inhibit-read-only t)
(height (window-body-height))
(width (window-body-width)))
(vterm--set-size vterm--term (1- height) width)
(vterm--set-size vterm--term height width)))))))