diff options
| author | Craig Jennings <c@cjennings.net> | 2025-11-14 02:25:19 -0600 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2025-11-14 02:25:19 -0600 |
| commit | 7b982b1984dd37af42a2dfc9f4c3e52b27102860 (patch) | |
| tree | 95ff3ba5c3ab2da2a889530432d75e69ed993efa /modules | |
| parent | fd1a5d308e730bad2936adb2384897bb620458be (diff) | |
fix(ui): Fix cursor color updates with post-command-hook
The cursor color was not updating correctly when switching buffers
or modifying files. The original implementation used window-buffer-change
and other specific hooks, but these were insufficient and internal
buffers were interfering with cursor color updates.
Root cause:
- Cursor color is global (one cursor for all of Emacs)
- Previous hooks fired in internal buffer contexts (*Echo Area*, *temp*)
- This caused cursor to be set to white (unmodified) even when in
read-only buffers like dashboard
Solution:
- Use post-command-hook which runs after every command in current buffer
- Ignore internal buffers (names starting with space)
- Cache optimization prevents redundant set-cursor-color calls
Behavior now:
- Dashboard (read-only): Red cursor
- Unmodified file: White cursor
- Modified file: Green cursor
- After save: White cursor
Tests:
- Added 9 integration tests in test-ui-cursor-color-integration.el
- Tests verify hook installation, buffer switching, modification tracking
- All 27 tests passing (18 unit + 9 integration)
Integration tests catch issues that unit tests miss:
- Unit tests verified state detection logic (β)
- Integration tests verify hooks fire at right times (β now)
- Integration tests verify real buffer switching behavior (β now)
Cleanup:
- Removed debug code from init.el
- Removed debug-cursor-color.el temporary file
π€ Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Diffstat (limited to 'modules')
| -rw-r--r-- | modules/ui-config.el | 43 |
1 files changed, 21 insertions, 22 deletions
diff --git a/modules/ui-config.el b/modules/ui-config.el index 3e065370..775aefb2 100644 --- a/modules/ui-config.el +++ b/modules/ui-config.el @@ -97,28 +97,27 @@ When `cj/enable-transparency' is nil, reset alpha to fully opaque." "Last buffer name where cursor color was applied.") (defun cj/set-cursor-color-according-to-mode () - "Change cursor color according to buffer state (modified, read-only, overwrite)." - (let* ((state (cond - (buffer-read-only 'read-only) - (overwrite-mode 'overwrite) - ((buffer-modified-p) 'modified) - (t 'unmodified))) - (color (alist-get state cj/buffer-status-colors))) - (unless (and (string= color cj/-cursor-last-color) - (string= (buffer-name) cj/-cursor-last-buffer)) - (set-cursor-color color) - (setq cj/-cursor-last-color color - cj/-cursor-last-buffer (buffer-name))))) - -;; Use more efficient hooks instead of post-command-hook for better performance -(add-hook 'window-buffer-change-functions - (lambda (_window) (cj/set-cursor-color-according-to-mode))) -(add-hook 'read-only-mode-hook #'cj/set-cursor-color-according-to-mode) -(add-hook 'overwrite-mode-hook #'cj/set-cursor-color-according-to-mode) -;; Add hook to update cursor color when buffer is modified/saved -(add-hook 'after-change-functions - (lambda (&rest _) (cj/set-cursor-color-according-to-mode))) -(add-hook 'after-save-hook #'cj/set-cursor-color-according-to-mode) + "Change cursor color according to buffer state (modified, read-only, overwrite). +Only updates for real user buffers, not internal/temporary buffers." + ;; Only update cursor for real buffers (not internal ones like *temp*, *Echo Area*, etc.) + (unless (string-prefix-p " " (buffer-name)) ; Internal buffers start with space + (let* ((state (cond + (buffer-read-only 'read-only) + (overwrite-mode 'overwrite) + ((buffer-modified-p) 'modified) + (t 'unmodified))) + (color (alist-get state cj/buffer-status-colors))) + ;; Only skip if BOTH color AND buffer are the same (optimization) + ;; This allows color to update when buffer state changes + (unless (and (string= color cj/-cursor-last-color) + (string= (buffer-name) cj/-cursor-last-buffer)) + (set-cursor-color color) + (setq cj/-cursor-last-color color + cj/-cursor-last-buffer (buffer-name)))))) + +;; Use post-command-hook to update cursor color after every command +;; This ensures cursor color always matches the current buffer's state +(add-hook 'post-command-hook #'cj/set-cursor-color-according-to-mode) ;; Donβt show a cursor in non-selected windows: (setq cursor-in-non-selected-windows nil) |
