/theme-anchor

Apply a custom theme to current Emacs buffer only

Primary LanguageEmacs LispGNU General Public License v3.0GPL-3.0

theme-anchor

https://melpa.org/packages/theme-anchor-badge.svg

This package provides

  • functions to apply an emacs custom theme to current buffer only
  • a macro to generate side-effect only functions as mode hooks
  • a advice function to report attributes of a face in the current buffer, or fallback’s to the same face of the current frame

The following screenshot shows one frame splits into 4 buffers (as windows in emacs’s defintion), each buffer shows its own theme.

./Emacs-with-theme-anchors-0.png

Configuration

theme-anchor can be configured using use-package:

(use-package theme-anchor
  :config
  (setq face-impute-alist '((mode-line-active . mode-line))))

The variable face-impute-alist is for the situation that the theme you want to apply does not specify some face’s attributes (for example, Emacs 29 has a new face mode-line-active, which acts like de facto replacement of mode-line face, are not supported by most available theme packages at this moment (September 2022). In cases like this one, you can use face-impute-alist alist to specify as ((face-not-specified-in-theme . face-to-be-used-as-a-proxy)).

Functions and macro

theme-anchor-buffer-local

This function applies a theme to the current buffer without affecting other buffers.

The following example makes tango theme effective in current buffer without changing any face settings in other buffers.

(theme-anchor-buffer-local 'tango)

This function supports interactive mode through M-x theme-anchor-buffer-local

theme-anchor-hook-gen

This macro generates functions those can setup mode-specific buffer appearance as well as turn on/off some applicable features.

The following example shows how one can use this function to generate a mode hook function for emacs-lisp-mode

(add-hook 'emacs-lisp-mode-hook
	       (theme-anchor-hook-gen 'adwaita
                                 (show-paren-mode t)
                                 (setq-local show-paren-style 'expression)
                                 (electric-pair-local-mode t)))

Other functions

theme-anchor-get-faces

This function extracts theme-face’s from a custom theme

theme-anchor-spec-choose

This function detects what settings are applicable in a face specification like:

(theme-face default base16-default-light
            ((((type graphic))
              (:foreground "#383838" :background "#f8f8f8"))
             (((min-colors 256))
              (:foreground "white" :background "black"))
              (t
               (:foreground "white" :background "black"))))

If the emacs process runs in a GUI environment, the first specification will be used as the (type graphic) requirement is satisified ; if it runs in a tty terminal that only supports up to 16 colors, the third specification will be used due to even the second condition (min-colors 256) is not fulfilled.

Some themes may have some theme-face mis-specified like the following example, which more likely to be theme-value rather than theme-face

(theme-face an-uncommon-face invalid-theme '(["#FFFFFA" "#AABBCC"]))

If an invalid face specification is detected, this function will report an error and aborts any further execution of the function.

theme-anchor-get-values

Get theme-values’s from a theme

theme-anchor-set-values

Use setq-local to set theme-value’s extracted from the them in the current buffer only

Limitations

  • Current implementation is unable to process inherited face attributes
  • The ~theme-anchor-buffer-local~ currently does not support interactivefunction call yet
  • This package can only process ~theme-face~. ~theme-value~, which should be only changed via customization interface and that is out of this package’s scope See Issue #1
  • This package does not work well with modes basde on ~emacs-modules~ such as vterm using mode-hook mechanism to set themes. Interactively invoke ~theme-anchor-buffer-local~ still works, but it requires manual operation for the time being. Note that setting ANSI color seems not working in vterm when using fish that is due to fish’s setting. Other shells, such as, Bash, do work partially. However, setting term and term-color-* via face-remap-set-base or face-remap-add-relative seems not helpful in ansi-term and vterm. eshell is less an issue as it has its own faces rather than inherits from term. Also see Issue #1.
  • This package currently does not work well with some add-on themes such as airline-themes

Etymology

This package and its functions’ theme-anchor name prefix is chosen as a theme gets anchored on a buffer rather than makes the entire Emacs session looks monotonic in style.

The function theme-anchor-buffer-local’s name suffix -buffer-local is borrowed from load-theme-buffer-local (which is unfortunately orphaned/looking for maintainer now) that I had used since Emacs version 26.1. load-theme-buffer-local relies on flet for dynamic binding but the deprecation of flet in recent Emacs releases and development branches prevents it from working properly even with noflet. This package aims to solve the same problem load-theme-buffer-local aimed to solve but without use of dynamic binding as well as any third-party package dependency.

LICENSE

The use of this package is granted under Free Software Foundation’s GNU General Public License, Version 3 (or newer).