aboutsummaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-05-03 23:30:28 -0500
committerCraig Jennings <c@cjennings.net>2026-05-03 23:41:48 -0500
commit9c7654e0e0f4777176ad5a9ea30075431e931c02 (patch)
tree4442c7e65a646bb83efc746825c5e9cd3c830086 /modules
parentb2d44d70374db0ab801d18f8c04d1b021396ea46 (diff)
downloaddotemacs-9c7654e0e0f4777176ad5a9ea30075431e931c02.tar.gz
dotemacs-9c7654e0e0f4777176ad5a9ea30075431e931c02.zip
refactor: move and test theme persistence behavior
Diffstat (limited to 'modules')
-rw-r--r--modules/ui-theme.el88
1 files changed, 52 insertions, 36 deletions
diff --git a/modules/ui-theme.el b/modules/ui-theme.el
index bc526f38..f84d7231 100644
--- a/modules/ui-theme.el
+++ b/modules/ui-theme.el
@@ -17,10 +17,6 @@
;;; Code:
-(require 'user-constants)
-
-(eval-when-compile (defvar org-dir))
-
;; ----------------------------------- Themes ----------------------------------
;; theme choices and settings
@@ -39,8 +35,8 @@ Unloads any other applied themes before applying the chosen theme."
(let ((chosentheme (completing-read "Load custom theme: "
(mapcar #'symbol-name
(custom-available-themes)))))
- (mapc #'disable-theme custom-enabled-themes)
- (load-theme (intern chosentheme) t))
+ (cj/theme-disable-all)
+ (cj/theme-load-name chosentheme))
(cj/save-theme-to-file))
(keymap-global-set "M-S-l" #'cj/switch-themes) ;; was M-L, overrides downcase-word
@@ -48,18 +44,26 @@ Unloads any other applied themes before applying the chosen theme."
;; ----------------------------- Theme Persistence -----------------------------
;; persistence utility functions used by switch themes.
-(defvar theme-file (concat org-dir "emacs-theme.persist")
+(defgroup cj/ui-theme nil
+ "Theme persistence settings."
+ :group 'faces)
+
+(defcustom theme-file (expand-file-name ".emacs-theme" user-emacs-directory)
"The location of the file to persist the theme name.
If you want your theme change to persist across instances, put this in a
-directory that is sync'd across machines with this configuration.")
+directory that is sync'd across machines with this configuration."
+ :type 'file
+ :group 'cj/ui-theme)
-(defvar fallback-theme-name "modus-vivendi"
+(defcustom fallback-theme-name "modus-vivendi"
"The name of the theme to fallback on.
This is used when there's no file, or the theme name doesn't match
any of the installed themes. This should be a built-in theme. If theme name is
-`nil', there will be no theme.")
+`nil', there will be no theme."
+ :type 'string
+ :group 'cj/ui-theme)
-(defun cj/read-file-contents (filename)
+(defun cj/theme-read-file-contents (filename)
"Read FILENAME and return its content as a string.
If FILENAME isn't readable, return nil."
@@ -68,20 +72,49 @@ If FILENAME isn't readable, return nil."
(insert-file-contents filename)
(string-trim (buffer-string)))))
-(defun cj/write-file-contents (content filename)
+(defun cj/theme-write-file-contents (content filename)
"Write CONTENT to FILENAME.
If FILENAME isn't writeable, return nil. If successful, return t."
(when (file-writable-p filename)
(condition-case err
(progn
- (with-temp-buffer
- (insert content)
- (write-file filename))
+ (write-region content nil filename nil 'silent)
t)
(error
(message "Error writing to %s: %s" filename (error-message-string err))
nil))))
+(defun cj/theme-disable-all ()
+ "Disable all currently enabled custom themes."
+ (mapc #'disable-theme (copy-sequence custom-enabled-themes)))
+
+(defun cj/theme-load-name (theme-name)
+ "Load THEME-NAME without confirmation."
+ (load-theme (intern theme-name) t))
+
+(defun cj/theme-load-fallback (msg)
+ "Display MSG and load `fallback-theme-name'."
+ (message "%s Loading fallback theme %s" msg fallback-theme-name)
+ (cj/theme-load-name fallback-theme-name))
+
+(defun cj/theme-apply-persisted-name (theme-name)
+ "Apply persisted THEME-NAME.
+Nil or empty THEME-NAME loads the fallback theme. The literal string
+\"nil\" disables all themes without loading a replacement."
+ (cj/theme-disable-all)
+ (cond
+ ((or (null theme-name) (string-empty-p theme-name))
+ (cj/theme-load-fallback "Theme file not found or empty."))
+ ((string= theme-name "nil")
+ nil)
+ (t
+ (condition-case err
+ (cj/theme-load-name theme-name)
+ (error
+ (cj/theme-load-fallback
+ (format "Error loading theme %s: %s."
+ theme-name (error-message-string err))))))))
+
(defun cj/get-active-theme-name ()
"Return the name of the active UI theme as a string.
Returns fallback-theme-name if no theme is active."
@@ -91,38 +124,21 @@ Returns fallback-theme-name if no theme is active."
(defun cj/save-theme-to-file ()
"Save the string representing the current theme to the theme-file."
- (if (not (cj/write-file-contents (cj/get-active-theme-name) theme-file))
+ (if (not (cj/theme-write-file-contents (cj/get-active-theme-name) theme-file))
(message "Cannot save theme: %s is unwriteable" theme-file)
(message "%s theme saved to %s" (cj/get-active-theme-name) theme-file)))
(defun cj/load-fallback-theme (msg)
"Display MSG and load ui-theme fallback-theme-name.
Used to handle errors with loading persisted theme."
- (message "%s Loading fallback theme %s" msg fallback-theme-name)
- (load-theme (intern fallback-theme-name) t))
+ (cj/theme-disable-all)
+ (cj/theme-load-fallback msg))
(defun cj/load-theme-from-file ()
"Apply the theme name contained in theme-file as the active UI theme.
If the theme is nil, it disables all current themes. If an error occurs
loading the file name, the fallback-theme-name is applied and saved."
- (let ((theme-name (cj/read-file-contents theme-file)))
- ;; if theme-name is nil, unload all themes and load fallback theme
- (if (not theme-name)
- (progn
- (mapc #'disable-theme custom-enabled-themes)
- (cj/load-fallback-theme "Theme file not found or empty."))
- ;; Check if theme is 'nil' string
- (if (string= theme-name "nil")
- (mapc #'disable-theme custom-enabled-themes)
- ;; apply theme name or if error, load fallback theme
- (condition-case err
- (load-theme (intern theme-name) t)
- (error
- (cj/load-fallback-theme
- (format "Error loading theme %s: %s."
- theme-name (error-message-string err)))))))))
-
-(cj/load-theme-from-file)
+ (cj/theme-apply-persisted-name (cj/theme-read-file-contents theme-file)))
(provide 'ui-theme)
;;; ui-theme.el ends here