From 7b982b1984dd37af42a2dfc9f4c3e52b27102860 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Fri, 14 Nov 2025 02:25:19 -0600 Subject: fix(ui): Fix cursor color updates with post-command-hook MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- modules/ui-config.el | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) (limited to 'modules/ui-config.el') 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) -- cgit v1.2.3