Alect is a package that provides (rather low contrast but colourful enough) configurable light, dark and black color themes for GNU Emacs 24 or later. The themes are intended to be used with GUI (see Class of terminals).
Along with the general basic faces, the following modes and packages are supported (themed):
- Built-in packages (part of Emacs):
- aurel
- auto-complete
- Caml packages: tuareg, merlin, utop
- company
- cperl
- debbugs
- diff-hl
- dictem
- EMMS
- Geiser
- google-translate
- Emacs-Guix
- Helm (partial support)
- Hydra
- indent-guide
- ivy
- Magit
- markdown
- mu4e
- org-transclusion
- powerline
- realgud
- rubik
- sauron
- slime
- sunrise-commander
- syslog
- tabbar
- transient
- w3m
- which-key
- winum
The other packages are not supported yet even if there are some customized faces (these faces left from other themes). So if you see some ugly faces or if you would like some mode to be supported, you may mail me or open an issue.
Add this to your init file (~/.emacs.d/init.el
or ~/.emacs
):
(add-to-list 'load-path "/path/to/alect-themes")
(add-to-list 'custom-theme-load-path "/path/to/alect-themes")
The package can be installed from MELPA (with M-x package-install
or M-x list-packages
).
If you want to enable (see Usage section) any theme installed with a package system on Emacs start, you should know the following: Emacs loads packages after processing the init file, so loading a theme will fail because the path to a theme is not known yet. That's why you need to initialize the package system before loading the theme:
(setq package-enable-at-startup nil)
(package-initialize)
...
(load-theme ...)
For further details, see (info "(emacs) Package Installation")
.
To activate a theme interactively use customize-themes
or load-theme
:
M-x load-theme RET alect-light
To load a theme on Emacs start, add this to your init file:
(load-theme 'alect-light t)
Note: For quick switching between themes (with unloading the previous
one), I use al/load-theme
command from my
emacs-config.
You can find the names and values of all colors used by alect-themes in
alect-colors
variable. Also you can open
colors
file in Emacs to get an idea about the used color palette.
There are several ways for configuring the themes:
- modifying palette (
alect-colors
variable); - ignoring faces and variables;
- overriding face specifications;
- configuring other alect variables.
By default only graphical terminals are supported, i.e. if you enable a
theme, you will see themed faces in GUI and default faces in text-only
terminals. So if you use emacs --daemon
, you will not be disturbed by
the ugly colors when you are in a non-graphical terminal.
You can add support for other terminals by setting alect-display-class
variable. For example, if you want to enable alect-themes in 256-colors
terminals, use the following:
(setq alect-display-class '((class color) (min-colors 256)))
See (info "(elisp) Defining Faces")
for how a class of terminals
should be specified.
If you don't like how some colors look, you can change alect-colors
variable by customizing it or by using alect-generate-colors
function
(see how the variable is defined in the code).
However those methods redefine the whole variable, so if the palette will be changed in future (it happens sometimes) or a new theme will be added, you may not notice that. So you can use another approach if you want to modify only some colors.
Let's say, you don't like cyan-2
color for the light theme as it's too
light and bg-1
color for the dark theme as you prefer black color for
the background. You can change those colors by putting this into your
.emacs
(before loading an alect-theme if you use it on Emacs start):
(with-eval-after-load 'alect-themes
(alect-set-color 'light 'cyan-2 "#00a8a8")
(alect-set-color 'dark 'bg-1 "black"))
The function alect-set-color
is just a convenient way for modifying
alect-colors
variable, so if you are playing with it, don't forget to
reload an alect-theme for the changes to take effect.
By default along with a lot of faces, an alect-theme
customizes
several variables that contain color information,
e.g. ansi-color-names-vector
(see also
Emacs bug in themed variables). You
can disable theming of faces and variables with alect-ignored-faces
and alect-ignored-variables
variables.
For example, if you prefer the default appearance of the titles in
Info-mode
and of the minibuffer prompt, and if you want to disable
modifying the variables at all, use the following:
(setq alect-ignored-variables t
alect-ignored-faces
'(minibuffer-prompt
info-title-1 info-title-2
info-title-3 info-title-4))
If you don't like how particular faces look, you can change those by
modifying alect-overriding-faces
variable. The real power here is
that you can use themed color names from alect-colors
along with the
usual strings with hex values or defined color names (available with
M-x list-colors-display
).
Let's say, you want green strings, gray comments, more distinguishable
mode-line, and of course you don't like those pink (magenta-1
) prompts
everywhere (minibuffer, comint, ...). Just set that variable like this:
(setq
alect-overriding-faces
'((alect-prompt ((t :foreground blue :weight bold)))
(font-lock-string-face ((t :foreground green-1)))
(font-lock-doc-face ((t :inherit font-lock-string-face)))
(font-lock-comment-face ((t :foreground gray)))
(mode-line-buffer-id ((t :foreground "yellow" :weight bold)))
(mode-line ((((background light))
:foreground fg+1 :background "#ffaaaa"
:box (:line-width 2 :color bg-2 :style nil))
(((background dark))
:foreground fg+1 :background "firebrick3"
:box (:line-width 2 :color bg-2 :style nil))))))
See these screenshots to compare the original and modified themes.
Along with 3 original light, dark and black themes, the package provides
inverted (alternative) themes (alect-light-alt
and alect-dark-alt
).
They use the same color palettes, so they look very similar to the
original ones. The difference (by default) is that dark and bright
colors are reversed.
There is an additional way of configuring alternative themes: with
alect-inverted-color-regexp
variable (for details, see docstrings of
this variable and alect-get-color
function). For example, you may set
this variable to invert background colors:
(setq alect-inverted-color-regexp "^\\(bg\\)\\([-+]\\)\\([012]\\)$")
See these screenshots for the result.
Many headers and titles are themed and you may not like their height. The following 3 variables may be useful:
alect-header-height
alect-single-title-height
alect-multiple-titles-height
For example, if you want to have a normal height for org
and
markdown
titles, use this (put it in .emacs
before loading an
alect-theme):
(setq alect-multiple-titles-height 1.0)
Note: 1.0
and 1
are different values. You can play with Height
in Custom buffer (M-x customize-face RET <any-face>
) to see how
integers and floats are treated.
There are other settings that may affect a visual appearance. For
example GNUS uses widgets in article buffers. And widget-button
face
looks like a real button in alect-themes
. I find such buttons not
very attractive in articles but I also don't want to modify
widget-button
face, so I use the following to get rid of button faces
only in GNUS articles:
(add-hook 'gnus-article-mode-hook
(lambda () (setq-local widget-button-face nil)))
While using any theme (not only from this package), you may meet
faces that do not look how they should (intended by the theme). For
example, if you enable alect-light
theme, you can see ugly gray
buttons and other faces in the Custom-mode
(the left picture)
instead of the themed colored buttons (the right picture):
This happens because Emacs applies default face settings even for a themed face. This behaviour is changed in the new versions of Emacs: since 24.4 you will always get pure themes without unintended face settings. If you use a previous version, you can try the following workaround to achieve the new behaviour:
(when (version< emacs-version "24.3.50")
(defun face-spec-recalc-new (face frame)
"Improved version of `face-spec-recalc'."
(while (get face 'face-alias)
(setq face (get face 'face-alias)))
(face-spec-reset-face face frame)
;; If FACE is customized or themed, set the custom spec from
;; `theme-face' records, which completely replace the defface spec
;; rather than inheriting from it.
(let ((theme-faces (get face 'theme-face)))
(if theme-faces
(dolist (spec (reverse theme-faces))
(face-spec-set-2 face frame (cadr spec)))
(face-spec-set-2 face frame (face-default-spec face))))
(face-spec-set-2 face frame (get face 'face-override-spec)))
(defadvice face-spec-recalc (around new-recalc (face frame) activate)
"Use `face-spec-recalc-new' instead."
(face-spec-recalc-new face frame)))
That version of face-spec-recalc
(wrapped with advice) is one of the
development variants from 24.3.50.1. It works good except of one
particular case: if you try to use that workaround and enable a theme in
an unsupported (by the theme) terminal (e.g. alect-theme in a text
terminal), your monitor may suddenly explode. Currently
faces.el
is changed a lot (comparing to 24.3) and I don't know a better
workaround.
Summary: alect-themes
use inheriting a lot and because of the nature
of faces in Emacs 24.3, many of them look ugly. With Emacs 24.4 or
with the above workaround (use it only with GUI), the themes look how
they should.
Emacs has a bug
(#16266) that
doesn't allow to set undefined variables. For example, if a theme
customizes a color for emms icon and you load the theme before emms,
then emms icon will use a default color instead of the themed one. This
bug takes effect only on defvar
-ed variables, defcustom
-ed variables
are safe.
The range of such variables (effected by the bug) suitable for
colorizing is very limited. For alect themes, the following variables
are themed: emms-mode-line-icon-image-cache
,
gnus-mode-line-image-cache
and gnus-logo-colors
.
You can use this workaround to avoid the bug:
(defadvice custom-theme-set-variables
(around fix-inhibit-bug activate)
"Allow setting of undefined variables in themes."
(let (custom--inhibit-theme-enable)
ad-do-it))
You can see the following and other screenshots in this imgur album.
Themes: alect-light, alect-dark
Font: Terminus-12
Themes: alect-light, alect-black
Font: DejaVu Sans Mono-12
Themes: alect-light, alect-dark
Font: Anonymous Pro-13
Themes: alect-dark (default), alect-dark (modified) – the original dark theme and a dark theme with some changed faces (see overriding faces)
Font: Liberation Mono-12
Themes: alect-light-alt (modified), alect-dark-alt (modified) – alternative themes, configured to invert background (see configuring alternative themes)
Font: Anonymous Pro-13
At first I had only a light theme – it was just a set of customized faces. Then I realized that at night it's better for eyes to use a dark theme (it was derived from zenburn-theme initially, but then the colors were modified a lot). The idea of creating two themes with different colors and the same code base came from solarized-theme. The code of solarized and zenburn themes was used hardly. Many thanks to their authors.
The following people helped to improve the themes:
- Davor Rotim
- Rocky Bernstein
- Thomas S. Dye