From fd1a5d308e730bad2936adb2384897bb620458be Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Fri, 14 Nov 2025 01:53:30 -0600 Subject: feat(ui): Add buffer modification state to color indicators MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change modeline filename and cursor colors to indicate buffer modification status, not just read-only/overwrite state. Color scheme changes: - White (#ffffff): Unmodified writeable buffer - Green (#64aa0f): Modified writeable buffer (unsaved changes) - Red (#f06a3f): Read-only buffer - Gold (#c48702): Overwrite mode active Previously: All writeable buffers were green regardless of modification Now: White when clean, green when dirty (better visual feedback) Implementation: - Updated cj/buffer-status-colors in user-constants.el: - Changed 'normal' β†’ 'unmodified' (white) - Added new 'modified' state (green) - Updated state detection in modeline-config.el: - Now checks (buffer-modified-p) before defaulting to unmodified - Updated cursor color logic in ui-config.el: - Same state detection as modeline for consistency - Added after-change-functions hook for real-time updates - Added after-save-hook to update on save Priority order (highest to lowest): 1. Read-only (red) - takes precedence over everything 2. Overwrite mode (gold) - takes precedence over modified state 3. Modified (green) - buffer has unsaved changes 4. Unmodified (white) - default for clean writeable buffers Tests: - 18 comprehensive tests in test-ui-buffer-status-colors.el - Tests state detection logic and priority order - Tests color constant definitions and mappings - Tests integration with cursor and modeline - All tests passing πŸ€– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- modules/modeline-config.el | 11 ++++++----- modules/ui-config.el | 13 +++++++++---- modules/user-constants.el | 7 ++++--- 3 files changed, 19 insertions(+), 12 deletions(-) (limited to 'modules') diff --git a/modules/modeline-config.el b/modules/modeline-config.el index f2b80561..a5e23dd0 100644 --- a/modules/modeline-config.el +++ b/modules/modeline-config.el @@ -56,9 +56,10 @@ Example: `my-very-long-name.el' β†’ `my-ver...me.el'" (defvar-local cj/modeline-buffer-name '(:eval (let* ((state (cond - (buffer-read-only 'read-only) - (overwrite-mode 'overwrite) - (t 'normal))) + (buffer-read-only 'read-only) + (overwrite-mode 'overwrite) + ((buffer-modified-p) 'modified) + (t 'unmodified))) (color (alist-get state cj/buffer-status-colors)) (name (buffer-name)) (truncated-name (cj/modeline-string-cut-middle name))) @@ -73,8 +74,8 @@ Example: `my-very-long-name.el' β†’ `my-ver...me.el'" (define-key map [mode-line mouse-1] 'previous-buffer) (define-key map [mode-line mouse-3] 'next-buffer) map)))) - "Buffer name colored by read-only/read-write status. -Green = writeable, Red = read-only, Gold = overwrite. + "Buffer name colored by modification and read-only status. +White = unmodified, Green = modified, Red = read-only, Gold = overwrite. Truncates in narrow windows. Click to switch buffers.") (defvar-local cj/modeline-position diff --git a/modules/ui-config.el b/modules/ui-config.el index 3922ce2a..3e065370 100644 --- a/modules/ui-config.el +++ b/modules/ui-config.el @@ -97,11 +97,12 @@ 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-read-only or \\='overwrite state." + "Change cursor color according to buffer state (modified, read-only, overwrite)." (let* ((state (cond - (buffer-read-only 'read-only) - (overwrite-mode 'overwrite) - (t 'normal))) + (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)) @@ -114,6 +115,10 @@ When `cj/enable-transparency' is nil, reset alpha to fully opaque." (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) ;; Don’t show a cursor in non-selected windows: (setq cursor-in-non-selected-windows nil) diff --git a/modules/user-constants.el b/modules/user-constants.el index 2a6d0ca2..eafd08e8 100644 --- a/modules/user-constants.el +++ b/modules/user-constants.el @@ -41,9 +41,10 @@ Example: (setq cj/debug-modules '(org-agenda mail)) ;; ---------------------------- Buffer Status Colors --------------------------- (defconst cj/buffer-status-colors - '((read-only . "#f06a3f") ; red – buffer is read-only - (overwrite . "#c48702") ; gold – overwrite mode - (normal . "#64aa0f")) ; green – insert & read/write + '((read-only . "#f06a3f") ; red – buffer is read-only + (overwrite . "#c48702") ; gold – overwrite mode + (modified . "#64aa0f") ; green – modified & writeable + (unmodified . "#ffffff")) ; white – unmodified & writeable "Alist mapping buffer states to their colors. Used by cursor color, modeline, and other UI elements.") -- cgit v1.2.3