diff options
| author | Craig Jennings <c@cjennings.net> | 2026-05-25 11:54:39 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-05-25 11:54:39 -0500 |
| commit | 32cfe216b4f5917b1a979e0372edf9b8f1ab62ea (patch) | |
| tree | 7fe70b4d8a120dd8402d19faa3546f388d8e17cf | |
| parent | 56da3d940b26a51102bce39b3b82dfbbc2b391fd (diff) | |
| download | dotemacs-32cfe216b4f5917b1a979e0372edf9b8f1ab62ea.tar.gz dotemacs-32cfe216b4f5917b1a979e0372edf9b8f1ab62ea.zip | |
fix(theme): register dupre faces so org status colors are themed
The dupre theme defined its own faces (dupre-accent, the headings, and the org status faces) only through custom-theme-set-faces, never defface. That leaves them unregistered, so they render through :inherit but silently fail when applied directly as a text property. org-todo-keyword-faces and org-priority-faces apply faces that way, so the org keyword and priority colors never showed as dupre tones.
I added a defface registration block to dupre-faces.el for all of dupre's own faces, so they're real faces. The theme still sets their colors. Then I pointed org-todo-keyword-faces and org-priority-faces (in org-config.el) at named dupre-org-* faces, each the closest palette color to its former hard-coded name, and gave each a dimmed variant that auto-dim-config.el swaps in for unfocused windows. A keyword in a dimmed window now shows a darker shade of its own color rather than flat gray or full brightness.
A regression test asserts dupre's faces stay registered, since that was the latent bug behind all of this.
| -rw-r--r-- | modules/auto-dim-config.el | 18 | ||||
| -rw-r--r-- | modules/org-config.el | 32 | ||||
| -rw-r--r-- | tests/test-dupre-theme.el | 19 | ||||
| -rw-r--r-- | themes/dupre-faces.el | 60 |
4 files changed, 114 insertions, 15 deletions
diff --git a/modules/auto-dim-config.el b/modules/auto-dim-config.el index 83c5b17c..5ce426d2 100644 --- a/modules/auto-dim-config.el +++ b/modules/auto-dim-config.el @@ -54,7 +54,23 @@ (font-lock-constant-face . (auto-dim-other-buffers . nil)) (font-lock-builtin-face . (auto-dim-other-buffers . nil)) (font-lock-preprocessor-face . (auto-dim-other-buffers . nil)) - (font-lock-warning-face . (auto-dim-other-buffers . nil)))) + (font-lock-warning-face . (auto-dim-other-buffers . nil)) + ;; Org TODO-keyword + priority faces dim to their own -dim variant + ;; (a darker shade of the same colour) rather than the flat gray, so + ;; a dimmed window's keywords stay recognizable. Faces are defined + ;; in themes/dupre-faces.el and wired in modules/org-config.el. + (dupre-org-todo . (dupre-org-todo-dim . nil)) + (dupre-org-project . (dupre-org-project-dim . nil)) + (dupre-org-doing . (dupre-org-doing-dim . nil)) + (dupre-org-waiting . (dupre-org-waiting-dim . nil)) + (dupre-org-verify . (dupre-org-verify-dim . nil)) + (dupre-org-stalled . (dupre-org-stalled-dim . nil)) + (dupre-org-failed . (dupre-org-failed-dim . nil)) + (dupre-org-done . (dupre-org-done-dim . nil)) + (dupre-org-priority-a . (dupre-org-priority-a-dim . nil)) + (dupre-org-priority-b . (dupre-org-priority-b-dim . nil)) + (dupre-org-priority-c . (dupre-org-priority-c-dim . nil)) + (dupre-org-priority-d . (dupre-org-priority-d-dim . nil)))) (auto-dim-other-buffers-mode 1)) (provide 'auto-dim-config) diff --git a/modules/org-config.el b/modules/org-config.el index 01586a9e..90dd09b0 100644 --- a/modules/org-config.el +++ b/modules/org-config.el @@ -101,25 +101,29 @@ "DELEGATED(x)" "|" "FAILED(f!)" "DONE(d!)" "CANCELLED(c!)"))) + ;; Keyword and priority colors come from the active theme's dupre-org-* + ;; faces (themes/dupre-faces.el) rather than hard-coded color names, so they + ;; match the palette and dim with the rest of an unfocused window + ;; (auto-dim-config.el remaps each to its -dim variant). (setq org-todo-keyword-faces - '(("TODO" . "green") - ("PROJECT" . "blue") - ("DOING" . "yellow") - ("WAITING" . "white") - ("VERIFY" . "orange") - ("STALLED" . "light blue") - ("DELEGATED" . "green") - ("FAILED" . "red") - ("DONE" . "dark grey") - ("CANCELLED" . "dark grey"))) + '(("TODO" . dupre-org-todo) + ("PROJECT" . dupre-org-project) + ("DOING" . dupre-org-doing) + ("WAITING" . dupre-org-waiting) + ("VERIFY" . dupre-org-verify) + ("STALLED" . dupre-org-stalled) + ("DELEGATED" . dupre-org-todo) + ("FAILED" . dupre-org-failed) + ("DONE" . dupre-org-done) + ("CANCELLED" . dupre-org-done))) (setq org-highest-priority ?A) (setq org-lowest-priority ?D) (setq org-default-priority ?D) - (setq org-priority-faces '((?A . (:foreground "Cyan" :weight bold)) - (?B . (:foreground "Yellow")) - (?C . (:foreground "Green")) - (?D . (:foreground "Grey")))) + (setq org-priority-faces '((?A . dupre-org-priority-a) + (?B . dupre-org-priority-b) + (?C . dupre-org-priority-c) + (?D . dupre-org-priority-d))) (setq org-enforce-todo-dependencies t) (setq org-enforce-todo-checkbox-dependencies t) diff --git a/tests/test-dupre-theme.el b/tests/test-dupre-theme.el index 32fa437e..dec648d1 100644 --- a/tests/test-dupre-theme.el +++ b/tests/test-dupre-theme.el @@ -204,5 +204,24 @@ (load-theme 'dupre t) (should (string= (face-attribute 'success :foreground) "#a4ac64"))) +;;; Face registration + +(ert-deftest dupre-semantic-faces-are-registered () + "Dupre's own faces must be real faces, not just theme specs. +An unregistered face renders only through `:inherit'; applied directly as +a text property (e.g. via `org-todo-keyword-faces') it silently fails. +The defface registration in dupre-faces.el is what makes direct use work." + (load-theme 'dupre t) + (dolist (face '(dupre-accent dupre-heading-1 + dupre-org-todo dupre-org-todo-dim + dupre-org-failed dupre-org-priority-a + dupre-org-priority-a-dim)) + (should (facep face))) + ;; and the theme colours them from the palette + (should (string= (face-attribute 'dupre-org-todo :foreground nil 'default) + "#a4ac64")) + (should (string= (face-attribute 'dupre-org-todo-dim :foreground nil 'default) + "#869038"))) + (provide 'test-dupre-theme) ;;; test-dupre-theme.el ends here diff --git a/themes/dupre-faces.el b/themes/dupre-faces.el index 648fded3..d7b6e07b 100644 --- a/themes/dupre-faces.el +++ b/themes/dupre-faces.el @@ -13,6 +13,34 @@ (require 'dupre-palette) +(defgroup dupre-faces nil + "Semantic faces owned by the dupre theme." + :group 'faces) + +;; Register dupre's own faces so they are real faces (facep t): customizable, +;; usable via `:inherit', and -- importantly -- applicable directly as a text +;; property (which `org-todo-keyword-faces' and `org-priority-faces' do). +;; `custom-theme-set-faces' below sets their colours; this only declares them. +;; Without this, the faces existed only as theme specs and rendered only +;; through `:inherit', silently failing wherever a face was applied directly. +(dolist (face '(dupre-accent dupre-err dupre-warning dupre-success dupre-info + dupre-heading-1 dupre-heading-2 dupre-heading-3 dupre-heading-4 + dupre-org-todo dupre-org-todo-dim + dupre-org-project dupre-org-project-dim + dupre-org-doing dupre-org-doing-dim + dupre-org-waiting dupre-org-waiting-dim + dupre-org-verify dupre-org-verify-dim + dupre-org-stalled dupre-org-stalled-dim + dupre-org-failed dupre-org-failed-dim + dupre-org-done dupre-org-done-dim + dupre-org-priority-a dupre-org-priority-a-dim + dupre-org-priority-b dupre-org-priority-b-dim + dupre-org-priority-c dupre-org-priority-c-dim + dupre-org-priority-d dupre-org-priority-d-dim)) + (custom-declare-face + face '((t)) "Dupre theme face; colour set by `dupre-theme-set-faces'." + :group 'dupre-faces)) + (defun dupre-theme-set-faces () "Set all faces for dupre-theme." (dupre-with-colors @@ -181,6 +209,38 @@ `(org-done ((t (:foreground ,green :weight bold)))) `(org-headline-done ((t (:foreground ,gray)))) `(org-headline-todo ((t (:foreground ,fg)))) + +;;;;; Org TODO-keyword and priority status faces + ;; Focused colours (closest dupre palette to the former hard-coded + ;; names in org-config.el) plus a dimmed variant per status, for + ;; non-selected windows. org-config.el points org-todo-keyword-faces and + ;; org-priority-faces at the focused faces; auto-dim-config.el remaps each + ;; focused face to its -dim variant in unfocused windows. + `(dupre-org-todo ((t (:foreground ,green :weight bold)))) + `(dupre-org-todo-dim ((t (:foreground ,green-1 :weight bold)))) + `(dupre-org-project ((t (:foreground ,blue :weight bold)))) + `(dupre-org-project-dim ((t (:foreground "#3d4a5a" :weight bold)))) + `(dupre-org-doing ((t (:foreground ,yellow :weight bold)))) + `(dupre-org-doing-dim ((t (:foreground ,yellow-2 :weight bold)))) + `(dupre-org-waiting ((t (:foreground ,fg :weight bold)))) + `(dupre-org-waiting-dim ((t (:foreground ,gray :weight bold)))) + `(dupre-org-verify ((t (:foreground ,red :weight bold)))) + `(dupre-org-verify-dim ((t (:foreground ,red-1 :weight bold)))) + `(dupre-org-stalled ((t (:foreground ,blue+1 :weight bold)))) + `(dupre-org-stalled-dim ((t (:foreground ,blue :weight bold)))) + `(dupre-org-failed ((t (:foreground ,intense-red :weight bold)))) + `(dupre-org-failed-dim ((t (:foreground ,red :weight bold)))) + `(dupre-org-done ((t (:foreground ,gray-2 :weight bold)))) + `(dupre-org-done-dim ((t (:foreground ,bg+2 :weight bold)))) + `(dupre-org-priority-a ((t (:foreground ,blue+1 :weight bold)))) + `(dupre-org-priority-a-dim ((t (:foreground ,blue :weight bold)))) + `(dupre-org-priority-b ((t (:foreground ,yellow)))) + `(dupre-org-priority-b-dim ((t (:foreground ,yellow-2)))) + `(dupre-org-priority-c ((t (:foreground ,green)))) + `(dupre-org-priority-c-dim ((t (:foreground ,green-1)))) + `(dupre-org-priority-d ((t (:foreground ,gray)))) + `(dupre-org-priority-d-dim ((t (:foreground ,gray-1)))) + `(org-date ((t (:foreground ,gray :underline t)))) `(org-link ((t (:foreground ,blue :underline t)))) `(org-code ((t (:foreground ,green :background ,bg+1)))) |
