diff options
| author | Craig Jennings <c@cjennings.net> | 2026-05-03 23:30:28 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-05-03 23:41:48 -0500 |
| commit | 9c7654e0e0f4777176ad5a9ea30075431e931c02 (patch) | |
| tree | 4442c7e65a646bb83efc746825c5e9cd3c830086 /modules | |
| parent | b2d44d70374db0ab801d18f8c04d1b021396ea46 (diff) | |
| download | dotemacs-9c7654e0e0f4777176ad5a9ea30075431e931c02.tar.gz dotemacs-9c7654e0e0f4777176ad5a9ea30075431e931c02.zip | |
refactor: move and test theme persistence behavior
Diffstat (limited to 'modules')
| -rw-r--r-- | modules/ui-theme.el | 88 |
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 |
