Custom Emacs functions No. 4 - UI

The intro

Every Emacs user that I know changes the hell out of the look and feel of their UI. I am no different here.

The following is a list of the function, that use in my module timu-ui.el.

Of course feel free to browse my .emacs.d for context ;).

The functions

timu-ui-with-face

A very simple function to propertize a string with face property lists similar to set-face-attribute.

(defun timu-ui-with-face (str &rest face-plist)
  "Propertize STR with FACE-PLIST."
  (propertize str 'face face-plist))

Example from my eshell prompt customization:

(timu-ui-with-face "$" :inherit font-lock-preprocessor-face)

timu-ui-load-theme

Emacs has an interactive function to load a theme, load-theme. However in my experience, some face attributes of the last active theme custom-enabled-themes remain visible, depending on the themes. I don’t like it.

This function does remedy the issue by first disabling the last enabled theme.

(defun timu-ui-load-theme ()
  "`load-theme' without confirmation and with completion.
Disables the `custom-enabled-themes' first to start with a blank canvas."
  (interactive)
  (let ((next-theme
         (completing-read "Load custom theme: "
                                  (custom-available-themes))))
    (mapc #'disable-theme custom-enabled-themes)
    (load-theme (intern next-theme) t)))

timu-ui-flash-mode-line

Remember the bell that goes of on when an “exception” occurs? Annoying right? You can of course set the variable visible-bell to t to flash the frame instead. However I find even that to be vexing.

This function makes just the modeline flash, …

(defun timu-ui-flash-mode-line ()
  "Flash the modeline on error or warning instead of the bell."
  (invert-face 'mode-line)
  (run-with-timer 0.1 nil #'invert-face 'mode-line))

… when set as:

(customize-set-variable 'ring-bell-function 'timu-ui-flash-mode-line)

Just for macOS

I use the either emacs-mac or the emacs-plus port of Emacs. These are ports of Emacs, that are better adapted to macOS. These bring different facilities to automatically switch to dark or light mode with the OS. Hence the following functions.

Emacs uses the variable ns-system-appearance-change-functions (emacs-plus) or the hook mac-effective-appearance-change-hook (emacs-mac) respectively. These are keep track with the macOS state to run the hook/function.

timu-ui-theme-hook

The hook that gets automatically applied on the change to either dark or light mode in macOS.

   (defun timu-ui-theme-hook (&optional appearance)
     "Hook to change the theme to light or dark.

Check the systems APPEARANCE in `ns-system-appearance'.
Or get by getting the APPEARANCE value of (`mac-application-state').

Set the variable `timu-macos-flavour' to \"light\" or \"dark\" accordingly.
This is for the case the `timu-macos-theme' is used.

Disable all `custom-enabled-themes' and load the theme in:
either `timu-ui-custom-light-theme' or `timu-ui-custom-dark-theme'."
     (if (boundp 'ns-system-appearance-change-functions)
         ;; for emacs-plus:
         (progn
           (pcase appearance
             ('light (progn (customize-set-variable 'timu-spacegrey-flavour "light")
                            (mapc #'disable-theme custom-enabled-themes)
                            (load-theme timu-ui-custom-light-theme t)))
             ('dark (progn (customize-set-variable 'timu-spacegrey-flavour "dark")
                           (mapc #'disable-theme custom-enabled-themes)
                           (load-theme timu-ui-custom-dark-theme t)))))
       ;; for emacsmacport:
       (let ((mac-mode (plist-get (mac-application-state) :appearance)))
         (cond ((equal mac-mode "NSAppearanceNameAqua")
                (progn (customize-set-variable 'timu-spacegrey-flavour "light")
                       (mapc #'disable-theme custom-enabled-themes)
                       (load-theme timu-ui-custom-light-theme t)))
               ((equal mac-mode "NSAppearanceNameDarkAqua")
                (progn (customize-set-variable 'timu-spacegrey-flavour "dark")
                       (mapc #'disable-theme custom-enabled-themes)
                       (load-theme timu-ui-custom-dark-theme t)))))))

timu-ui-load-theme-hook

Well this runs the aforementioned hook function.

(defun timu-ui-load-theme-hook ()
     "Function to add `timu-ui-theme-hook' as a hook.
Change theme with `ns-system-appearance-change-functions' for emacs-plus.
Or change theme with `mac-effective-appearance-change-hook' for emacsmacport."
     (if (boundp 'ns-system-appearance-change-functions)
         (add-to-list 'ns-system-appearance-change-functions 'timu-ui-theme-hook)
       (progn
         (add-hook 'mac-effective-appearance-change-hook #'timu-ui-theme-hook)
         (add-hook 'after-init-hook #'timu-ui-theme-hook))))

ET VOILÀ.