Themes

Doric Themes

Prot’s new doric-themes are worth exploring

(use-package doric-themes :ensure t)

Modus Themes

The excellent modus-themes are available out of the box in recent Emacs versions.

emacs/lisp/alc-theme.el
(require 'dbus) ; needed for later
;; Use `setopt' since modus supports automatically reloading the theme when these
;; are changed via the `customize' framework
(setopt modus-themes-bold-constructs t
        modus-themes-italic-constructs t
        modus-themes-prompts '(bold italic)
        modus-themes-variable-pitch-ui nil)

Loading them seems slighty complicated though?

I want to run one of the modus-themes-load-<variant> functions so that the modus-themes-after-load-theme-hook hook is run however, these functions are not initially loaded by Emacs. (require 'modus-themes) does not work either, so I first have to run (load-theme 'modus-<variant> t) which will load the relevant module and then load the theme a second time with (modus-themes-load-<variant>).

emacs/lisp/alc-theme.el
(defun alc-theme-load-theme (variant)
  "Load the light or dark theme according to VARIANT."
  (require-theme 'modus-themes t)
  (if (eq 1 variant)
     (progn
       (modus-themes-load-theme 'modus-vivendi))
    (modus-themes-load-theme 'modus-operandi)))

Specifics of theme loading aside, let’s pick a variant based on the current system theme. (Thanks to auto-dark-emacs for the DBus specifics.)

emacs/lisp/alc-theme.el
(defun alc-theme-sync-to-system-theme (_frame)
  "Choose a light/dark theme based on the current system preference."
  (alc-theme-load-theme
    (caar (dbus-call-method
           :session
           "org.freedesktop.portal.Desktop"
           "/org/freedesktop/portal/desktop"
           "org.freedesktop.portal.Settings" "Read"
           "org.freedesktop.appearance" "color-scheme"))))

Also, set up a listener so that Emacs automatically updates if the preference changes (again, thanks to auto-dark-emacs for the DBus incantation)

(when (display-graphic-p)
   (setq alc-theme-dbus-listener
         (dbus-register-signal
          :session
          "org.freedesktop.portal.Desktop"
          "/org/freedesktop/portal/desktop"
          "org.freedesktop.portal.Settings"
          "SettingChanged"
          (lambda (path var val)
            (when (and (string= path "org.freedesktop.appearance")
                       (string= var "color-scheme"))
              (alc-theme-load-theme (car val)))))))

If I ever need to, the listener can be disabled by running (dbus-unregister-object alc-theme-dbus-listener)

However, the dbus code fails when I am SSH-ing into my Raspberry Pi so in that case we just want a theme loaded and be done with it.

emacs/lisp/alc-theme.el
(unless (display-graphic-p)
  (alc-theme-load-theme 1)) ; dark

(provide 'alc-theme)