… but won’t if one has a custom theme loaded, as far as I can tell.
I don’t particularly like dark mode. Its use seems more preference than science, so for those who like it, cheers! However, from time to time dark mode would be good. In the evening when I’m simply reading my RSS feeds in elfeed, for example.
I wanted something that would make the switch without adding much weight. Here’s the journey:
- Looked at what Prot uses/recommends Modus Themes | Protesilaos Stavrou
- Led me to GitHub – guidoschmidt/circadian.el: Theme-switching for Emacs based on daytime
- That wasn’t gonna work for me. I realized I wanted this to happen in
early-init.elso a package-based option wasn’t right. - Light DDG-ing later and I found Emacs and Dark Mode
- That code would work but only on
emacs-plus. But the system signals other apps when to switch, soemacs-macmust have something too … - Dug around in the docs for
emacs-macand found some breadcrumbs. - Which led me to Custom Emacs functions No. 4 – UI | macOS & (open-source) Software
- Yes! Nearly there. Timu’s code is good but is customized to his use case. I want something more utilitarian.
- Stripped out the bits that work for
emacs-macand maybeemacs-plusand rebuilt it into this with a little help from the robot:
(defvar my/light-theme 'modus-operandi-tinted "Theme to use when system appearance is light.") (defvar my/dark-theme 'modus-vivendi-tinted "Theme to use when system appearance is dark.") (defun my/apply-theme-based-on-appearance (&optional appearance) "Switch between `my/light-theme` and `my/dark-theme` based on APPEARANCE. Handles both Emacs Plus (ns, using `appearance`) and Emacs Mac Port (mac, via `mac-application-state`)." (let ((mode (cond ;; Emacs Plus: appearance is passed as symbol ((boundp 'ns-system-appearance-change-functions) appearance) ;; Emacs Mac Port: detect from system plist ((plist-get (mac-application-state) :appearance))))) (pcase mode ((or 'light "NSAppearanceNameAqua") (mapc #'disable-theme custom-enabled-themes) (load-theme my/light-theme t)) ((or 'dark "NSAppearanceNameDarkAqua") (mapc #'disable-theme custom-enabled-themes) (load-theme my/dark-theme t))))) (defun my/setup-theme-switching () "Set up automatic theme switching on macOS appearance change." (if (boundp 'ns-system-appearance-change-functions) ;; Emacs Plus (add-to-list 'ns-system-appearance-change-functions #'my/apply-theme-based-on-appearance) ;; Emacs Mac Port (progn (add-hook 'mac-effective-appearance-change-hook #'my/apply-theme-based-on-appearance) (add-hook 'after-init-hook #'my/apply-theme-based-on-appearance)))) (my/setup-theme-switching)
This seems to check all the boxes:
- appropriate for
early-init.el - doesn’t call external scripts or tools
- relies on the OS and
emacs-macandemacs-plusbuilt-in capabilities - it works, for me at least
Some notes:
- Because this runs in
early-init.el, needs setting up with built-in themes that are available before the package system loads. Thankfully, Prot’smodus-themesare built-in now. - Any other GUI setup stuff like
initial-frame-alist,default-frame-alistandset-face-attributeneeds configuring before this (I think; maybe not?).
As always, YMMV. Please play around with this and let me know how it works for you. I’m working on my LISP coding skills, so buyer beware.
Reposts