diff options
author | Stefan Monnier <monnier@iro.umontreal.ca> | 2022-09-25 16:15:16 -0400 |
---|---|---|
committer | Stefan Monnier <monnier@iro.umontreal.ca> | 2022-09-25 16:15:16 -0400 |
commit | 650c20f1ca4e07591a727e1cfcc74b3363d15985 (patch) | |
tree | 85d11f6437cde22f410c25e0e5f71a3131ebd07d /doc/misc/modus-themes.org | |
parent | 8869332684c2302b5ba1ead4568bbc7ba1c0183e (diff) | |
parent | 4b85ae6a24380fb67a3315eaec9233f17a872473 (diff) | |
download | emacs-650c20f1ca4e07591a727e1cfcc74b3363d15985.tar.gz emacs-650c20f1ca4e07591a727e1cfcc74b3363d15985.tar.bz2 emacs-650c20f1ca4e07591a727e1cfcc74b3363d15985.zip |
Merge 'master' into noverlay
Diffstat (limited to 'doc/misc/modus-themes.org')
-rw-r--r-- | doc/misc/modus-themes.org | 6653 |
1 files changed, 6653 insertions, 0 deletions
diff --git a/doc/misc/modus-themes.org b/doc/misc/modus-themes.org new file mode 100644 index 00000000000..1b4bf88a0cc --- /dev/null +++ b/doc/misc/modus-themes.org @@ -0,0 +1,6653 @@ +#+title: Modus themes for GNU Emacs +#+author: Protesilaos Stavrou +#+email: info@protesilaos.com +#+language: en +#+options: ':t toc:nil author:t email:t num:t +#+startup: content +#+macro: stable-version 2.6.0 +#+macro: release-date 2022-08-19 +#+macro: development-version 2.7.0-dev +#+macro: file @@texinfo:@file{@@$1@@texinfo:}@@ +#+macro: space @@texinfo:@: @@ +#+macro: kbd @@texinfo:@kbd{@@$1@@texinfo:}@@ +#+texinfo_filename: modus-themes.info +#+texinfo_dir_category: Emacs misc features +#+texinfo_dir_title: Modus Themes: (modus-themes) +#+texinfo_dir_desc: Elegant, highly legible and customizable themes +#+texinfo_header: @set MAINTAINERSITE @uref{https://protesilaos.com,maintainer webpage} +#+texinfo_header: @set MAINTAINER Protesilaos Stavrou +#+texinfo_header: @set MAINTAINEREMAIL @email{info@protesilaos.com} +#+texinfo_header: @set MAINTAINERCONTACT @uref{mailto:info@protesilaos.com,contact the maintainer} + +#+texinfo: @insertcopying + +This manual, written by Protesilaos Stavrou, describes the customization +options for the ~modus-operandi~ and ~modus-vivendi~ themes, and provides +every other piece of information pertinent to them. + +The documentation furnished herein corresponds to stable version +{{{stable-version}}}, released on {{{release-date}}}. Any reference to a newer +feature which does not yet form part of the latest tagged commit, is +explicitly marked as such. + +Current development target is {{{development-version}}}. + ++ Homepage: https://protesilaos.com/emacs/modus-themes. ++ Git repository: https://git.sr.ht/~protesilaos/modus-themes. ++ Mailing list: https://lists.sr.ht/~protesilaos/modus-themes. + +#+toc: headlines 8 insert TOC here, with eight headline levels + +* COPYING +:properties: +:copying: t +:custom_id: h:b14c3fcb-13dd-4144-9d92-2c58b3ed16d3 +:end: + +Copyright (C) 2020-2022 Free Software Foundation, Inc. + +#+begin_quote +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.3 or +any later version published by the Free Software Foundation; with no +Invariant Sections, with the Front-Cover Texts being “A GNU Manual,” and +with the Back-Cover Texts as in (a) below. A copy of the license is +included in the section entitled “GNU Free Documentation License.” + +(a) The FSF’s Back-Cover Text is: “You have the freedom to copy and +modify this GNU manual.” +#+end_quote + +* Overview +:properties: +:custom_id: h:f0f3dbcb-602d-40cf-b918-8f929c441baf +:end: + +The Modus themes are designed for accessible readability. They conform +with the highest standard for color contrast between any given +combination of background and foreground values. This corresponds to +the WCAG AAA standard, which specifies a minimum rate of distance in +relative luminance of 7:1. + +Modus Operandi (~modus-operandi~) is a light theme, while Modus Vivendi +(~modus-vivendi~) is dark. Each theme's color palette is designed to meet +the needs of the numerous interfaces that are possible in the Emacs +computing environment. + +The overarching objective of this project is to always offer accessible +color combinations. There shall never be a compromise on this +principle. If there arises an inescapable trade-off between readability +and stylistic considerations, we will always opt for the former. + +To ensure that users have a consistently accessible experience, the +themes strive to achieve as close to full face coverage as possible +([[#h:a9c8f29d-7f72-4b54-b74b-ddefe15d6a19][Face coverage]]). + +Furthermore, the themes are designed to empower users with red-green +color deficiency (deuteranopia). This is achieved in three ways: + +1. The conformance with the highest legibility standard means that text + is always readable no matter the perception of its hue. + +2. Most contexts use colors on the blue-cyan-magenta-purple side of the + spectrum. Put differently, green and/or red are seldom used, thus + minimizing the potential for confusion. + + [[#h:0b26cb47-9733-4cb1-87d9-50850cb0386e][Why are colors mostly variants of blue, magenta, cyan?]]. + +3. In contexts where a red/green color-coding is unavoidable, we provide + a universal toggle to customize the themes so that a red/blue scheme + is used instead. + + [[#h:3ed03a48-20d8-4ce7-b214-0eb7e4c79abe][Option for red-green color deficiency or deuteranopia]]. + +Starting with version 0.12.0 and onwards, the themes are built into GNU +Emacs. + +** How do the themes look like +:properties: +:custom_id: h:69b92089-069c-4ba1-9d94-cc3415fc4f87 +:end: +#+cindex: Screenshots + +Check the web page with [[https://protesilaos.com/emacs/modus-themes-pictures/][the screen shots]]. There are lots of scenarios +on display that draw attention to details and important aspects in the +design of the themes. They also showcase the numerous customization +options. + +[[#h:bf1c82f2-46c7-4eb2-ad00-dd11fdd8b53f][Customization options]]. + +** Learn about the latest changes +:properties: +:custom_id: h:2cc37c36-6c1a-48b2-a010-1050b270ee18 +:end: +#+cindex: Changelog + +Please refer to the [[https://protesilaos.com/emacs/modus-themes-changelog][web page with the change log]]. It is comprehensive +and covers everything that goes into every tagged release of the themes. + +* Installation +:properties: +:custom_id: h:1af85373-7f81-4c35-af25-afcef490c111 +:end: + +The Modus themes are distributed with Emacs starting with version 28.1. +On older versions of Emacs, they can be installed using Emacs' package +manager or manually from their code repository. There also exist +packages for distributions of GNU/Linux. + +** Install manually from source +:properties: +:custom_id: h:da3414b7-1426-46b8-8e76-47b845b76fd0 +:end: + +In the following example, we are assuming that your Emacs files are +stored in =~/.emacs.d= and that you want to place the Modus themes in +=~/.emacs.d/modus-themes=. + +1. Get the source and store it in the desired path by running the + following in the command line shell: + +: $ git clone https://gitlab.com/protesilaos/modus-themes.git ~/.emacs.d/modus-themes + +2. Add that path to your known Elisp libraries' list, by placing this + snippet of Emacs Lisp in your init file (e.g. {{{file(init.el)}}}): + +#+begin_src emacs-lisp +(add-to-list 'load-path "~/.emacs.d/modus-themes") +#+end_src + +The themes are now ready to be used: [[#h:3f3c3728-1b34-437d-9d0c-b110f5b161a9][Enable and load]]. + +** Install from the archives +:properties: +:custom_id: h:c4b10085-149f-43e2-bd4d-347f33aee054 +:end: + +The ~modus-themes~ package is available from the GNU ELPA archive, which +is configured by default. + +Prior to querying any package archive, make sure to update the index, +with {{{kbd(M-x package-refresh-contents)}}}. Then all you need to do +is type {{{kbd(M-x package-install)}}} and specify the ~modus-themes~. + +Once installed, the themes are ready to be used: [[#h:3f3c3728-1b34-437d-9d0c-b110f5b161a9][Enable and load]]. + +** Install on GNU/Linux +:properties: +:custom_id: h:da640eb1-95dd-4e86-bb4e-1027b27885f0 +:end: + +The themes are also available from the archives of some distributions of +GNU/Linux. These should correspond to a tagged release rather than +building directly from the latest Git commit. It all depends on the +distro's packaging policies. + +*** Debian 11 Bullseye +:properties: +:custom_id: h:7e570360-9ee6-4bc5-8c04-9dc11418a3e4 +:end: + +The themes are part of Debian 11 Bullseye. Get them with: + +#+begin_src sh +sudo apt install elpa-modus-themes +#+end_src + +They are now ready to be used: [[#h:3f3c3728-1b34-437d-9d0c-b110f5b161a9][Enable and load]]. + +NOTE that Debian's package is severely out-of-date as of this writing +2022-07-24 09:57 +0300. + +*** GNU Guix +:properties: +:custom_id: h:a4ca52cd-869f-46a5-9e16-4d9665f5b88e +:end: + +Users of Guix can get the themes with this command: + +#+begin_src sh +guix package -i emacs-modus-themes +#+end_src + +They are now ready to be used: [[#h:3f3c3728-1b34-437d-9d0c-b110f5b161a9][Enable and load]]. + +** Dealing with byte compilation errors +:properties: +:custom_id: h:e6268471-e847-4c9d-998f-49a83257b7f1 +:end: + +From time to time, we receive bug reports pertaining to errors with byte +compilation. These seldom have to do with faulty code in the themes: it +might be a shortcoming of =package.el=, some regression in the current +development target of Emacs, a misconfiguration in an otherwise exotic +setup, and the like. + +The common solution with a stable version of Emacs is to: + +1. Delete the =modus-themes= package. +2. Close the current Emacs session. +3. Install the =modus-themes= again. + +For those building Emacs directly from source, the solution may involve +reverting to an earlier commit in emacs.git. + +At any rate, if you encounter such an issue please report it: we will +either fix the bug on our end if it is truly ours, or help forward it to +the relevant upstream maintainer. Whatever you do, please understand +that a build failure does not mean we are necessarily doing something +wrong. + +[[#h:6536c8d5-3f98-43ab-a787-b94120e735e8][Issues you can help with]]. + +* Enable and load +:properties: +:custom_id: h:3f3c3728-1b34-437d-9d0c-b110f5b161a9 +:end: +#+findex: modus-themes-load-themes +#+findex: modus-themes-toggle +#+findex: modus-themes-load-operandi +#+findex: modus-themes-load-vivendi +#+cindex: Essential configuration +#+vindex: modus-themes-after-load-theme-hook + +Users of the built-in themes cannot ~require~ the package as usual +because there is no package to speak of. Instead, things are simpler as +all one needs is to load the theme of their preference by adding either +form to their init file: + +#+begin_src emacs-lisp +(load-theme 'modus-operandi) ; Light theme +(load-theme 'modus-vivendi) ; Dark theme +#+end_src + +Users of packaged variants of the themes must add a few more lines to +ensure that everything works as intended. First, one has to require the +main library before loading either theme: + +#+begin_src emacs-lisp +(require 'modus-themes) +#+end_src + +Then it is recommended to load the individual theme files with the +helper function ~modus-themes-load-themes~: + +#+begin_src emacs-lisp +;; Load the theme files before enabling a theme (else you get an error). +(modus-themes-load-themes) +#+end_src + +Once the libraries that define the themes are enabled, one can activate +a theme with either of the following expressions: + +#+begin_src emacs-lisp +(modus-themes-load-operandi) ; Light theme +;; OR +(modus-themes-load-vivendi) ; Dark theme +#+end_src + +Changes to the available customization options must always be evaluated +before loading a theme ([[#h:bf1c82f2-46c7-4eb2-ad00-dd11fdd8b53f][Customization Options]]). An exception to this +norm is when using the various Custom interfaces or with commands like +{{{kbd(M-x customize-set-variable)}}}, which can optionally +automatically reload the theme ([[#h:9001527a-4e2c-43e0-98e8-3ef72d770639][Option for inhibiting theme reload]]). + +This is how a basic setup could look like: + +#+begin_src emacs-lisp +;;; For the built-in themes which cannot use `require': +;; Add all your customizations prior to loading the themes +(setq modus-themes-italic-constructs t + modus-themes-bold-constructs nil + modus-themes-region '(bg-only no-extend)) + +;; Load the theme of your choice: +(load-theme 'modus-operandi) ;; OR (load-theme 'modus-vivendi) + +(define-key global-map (kbd "<f5>") #'modus-themes-toggle) + + + +;;; For packaged versions which must use `require': +(require 'modus-themes) + +;; Add all your customizations prior to loading the themes +(setq modus-themes-italic-constructs t + modus-themes-bold-constructs nil + modus-themes-region '(bg-only no-extend)) + +;; Load the theme files before enabling a theme +(modus-themes-load-themes) + +;; Load the theme of your choice: +(modus-themes-load-operandi) ;; OR (modus-themes-load-vivendi) + +(define-key global-map (kbd "<f5>") #'modus-themes-toggle) +#+end_src + +[[#h:e979734c-a9e1-4373-9365-0f2cd36107b8][Sample configuration with and without use-package]]. + +With those granted, bear in mind a couple of technical points on +~modus-themes-load-operandi~ and ~modus-themes-load-vivendi~, as well as +~modus-themes-toggle~ which relies on them: + +1. Those functions call ~load-theme~. Some users prefer to opt for + ~enable-theme~ instead ([[#h:e68560b3-7fb0-42bc-a151-e015948f8a35][Differences between loading and enabling]]). + +2. The functions will run the ~modus-themes-after-load-theme-hook~ as + their final step. This can be employed for bespoke configurations + ([[#h:f4651d55-8c07-46aa-b52b-bed1e53463bb][Advanced customization]]). Experienced users may not wish to rely on + such a hook and the functions that run it: they may prefer a custom + solution ([[#h:86f6906b-f090-46cc-9816-1fe8aeb38776][A theme-agnostic hook for theme loading]]). + +** Sample configuration with and without use-package +:properties: +:custom_id: h:e979734c-a9e1-4373-9365-0f2cd36107b8 +:end: +#+cindex: use-package configuration +#+cindex: sample configuration + +It is common for Emacs users to rely on ~use-package~ for declaring +package configurations in their setup. We use this as an example: + +#+begin_src emacs-lisp +;;; For the built-in themes which cannot use `require': +(use-package emacs + :init + ;; Add all your customizations prior to loading the themes + (setq modus-themes-italic-constructs t + modus-themes-bold-constructs nil + modus-themes-region '(bg-only no-extend)) + :config + ;; Load the theme of your choice: + (load-theme 'modus-operandi) ;; OR (load-theme 'modus-vivendi) + :bind ("<f5>" . modus-themes-toggle)) + + + +;;; For packaged versions which must use `require': +(use-package modus-themes + :ensure + :init + ;; Add all your customizations prior to loading the themes + (setq modus-themes-italic-constructs t + modus-themes-bold-constructs nil + modus-themes-region '(bg-only no-extend)) + + ;; Load the theme files before enabling a theme + (modus-themes-load-themes) + :config + ;; Load the theme of your choice: + (modus-themes-load-operandi) ;; OR (modus-themes-load-vivendi) + :bind ("<f5>" . modus-themes-toggle)) +#+end_src + +The same without ~use-package~: + +#+begin_src emacs-lisp +;;; For the built-in themes which cannot use `require': +;; Add all your customizations prior to loading the themes +(setq modus-themes-italic-constructs t + modus-themes-bold-constructs nil + modus-themes-region '(bg-only no-extend)) + +;; Load the theme of your choice: +(load-theme 'modus-operandi) ;; OR (load-theme 'modus-vivendi) + +(define-key global-map (kbd "<f5>") #'modus-themes-toggle) + + + +;;; For packaged versions which must use `require': +(require 'modus-themes) + +;; Add all your customizations prior to loading the themes +(setq modus-themes-italic-constructs t + modus-themes-bold-constructs nil + modus-themes-region '(bg-only no-extend)) + +;; Load the theme files before enabling a theme +(modus-themes-load-themes) + +;; Load the theme of your choice: +(modus-themes-load-operandi) ;; OR (modus-themes-load-vivendi) + +(define-key global-map (kbd "<f5>") #'modus-themes-toggle) +#+end_src + +[[#h:e68560b3-7fb0-42bc-a151-e015948f8a35][Differences between loading and enabling]]. + +Note: make sure not to customize the variable ~custom-theme-load-path~ +or ~custom-theme-directory~ after the themes' package declaration. That +will lead to failures in loading the files. If either or both of those +variables need to be changed, their values should be defined before the +package declaration of the themes. + +** Differences between loading and enabling +:properties: +:custom_id: h:e68560b3-7fb0-42bc-a151-e015948f8a35 +:end: +#+cindex: load-theme VS enable-theme + +The reason we recommend ~load-theme~ instead of the other option of +~enable-theme~ is that the former does a kind of "reset" on the face +specs. It quite literally loads (or reloads) the theme. Whereas the +latter simply puts an already loaded theme at the top of the list of +enabled items, re-using whatever state was last loaded. + +As such, ~load-theme~ reads all customizations that may happen during +any given Emacs session: even after the initial setup of a theme. +Examples are calls to ~custom-set-faces~, as well as new values assigned +to the options the Modus themes provide ([[#h:bf1c82f2-46c7-4eb2-ad00-dd11fdd8b53f][Customization Options]]). + +Our tests show that ~enable-theme~ does not read such variables anew, so +it might appear to the unsuspecting user that the themes are somehow +broken whenever they try to assign a new value to a customization option +or some face. + +This "reset" that ~load-theme~ brings about does, however, come at the +cost of being somewhat slower than ~enable-theme~. Users who have a +stable setup and who seldom update their variables during a given Emacs +session, are better off using something like this: + +#+begin_src emacs-lisp +(require 'modus-themes) +(load-theme 'modus-operandi t t) +(load-theme 'modus-vivendi t t) + +(enable-theme 'modus-operandi) ;; OR (enable-theme 'modus-vivendi) +#+end_src + +[[#h:b40aca50-a3b2-4c43-be58-2c26fcd14237][Toggle themes without reloading them]]. + +[[#h:e979734c-a9e1-4373-9365-0f2cd36107b8][Sample configuration with and without use-package]]. + +With the above granted, other sections of the manual discuss how to +configure custom faces, where ~load-theme~ is expected, though +~enable-theme~ could still apply in stable setups: + +[[#h:1487c631-f4fe-490d-8d58-d72ffa3bd474][Case-by-case face specs using the themes' palette]]. + +[[#h:51ba3547-b8c8-40d6-ba5a-4586477fd4ae][Face specs at scale using the themes' palette]]. + +* Customization Options +:properties: +:custom_id: h:bf1c82f2-46c7-4eb2-ad00-dd11fdd8b53f +:end: + +The Modus themes are highly configurable, though they should work well +without any further tweaks. By default, all customization options are +set to nil, unless otherwise noted in this manual. + +Remember that all customization options must be evaluated before loading +a theme ([[#h:3f3c3728-1b34-437d-9d0c-b110f5b161a9][Enable and load]]). If the theme is already active, it must be +reloaded for changes in user options to come into force. + +Below is a summary of what you will learn in the subsequent sections of +this manual. + +#+begin_src emacs-lisp +(setq modus-themes-italic-constructs t + modus-themes-bold-constructs nil + modus-themes-mixed-fonts nil + modus-themes-subtle-line-numbers nil + modus-themes-intense-mouseovers nil + modus-themes-deuteranopia t + modus-themes-tabs-accented t + modus-themes-variable-pitch-ui nil + modus-themes-inhibit-reload t ; only applies to `customize-set-variable' and related + + modus-themes-fringes nil ; {nil,'subtle,'intense} + + ;; Options for `modus-themes-lang-checkers' are either nil (the + ;; default), or a list of properties that may include any of those + ;; symbols: `straight-underline', `text-also', `background', + ;; `intense' OR `faint'. + modus-themes-lang-checkers nil + + ;; Options for `modus-themes-mode-line' are either nil, or a list + ;; that can combine any of `3d' OR `moody', `borderless', + ;; `accented', a natural number for extra padding (or a cons cell + ;; of padding and NATNUM), and a floating point for the height of + ;; the text relative to the base font size (or a cons cell of + ;; height and FLOAT) + modus-themes-mode-line '(accented borderless (padding . 4) (height . 0.9)) + + ;; Same as above: + ;; modus-themes-mode-line '(accented borderless 4 0.9) + + ;; Options for `modus-themes-markup' are either nil, or a list + ;; that can combine any of `bold', `italic', `background', + ;; `intense'. + modus-themes-markup '(background italic) + + ;; Options for `modus-themes-syntax' are either nil (the default), + ;; or a list of properties that may include any of those symbols: + ;; `faint', `yellow-comments', `green-strings', `alt-syntax' + modus-themes-syntax nil + + ;; Options for `modus-themes-hl-line' are either nil (the default), + ;; or a list of properties that may include any of those symbols: + ;; `accented', `underline', `intense' + modus-themes-hl-line '(underline accented) + + ;; Options for `modus-themes-paren-match' are either nil (the + ;; default), or a list of properties that may include any of those + ;; symbols: `bold', `intense', `underline' + modus-themes-paren-match '(bold intense) + + ;; Options for `modus-themes-links' are either nil (the default), + ;; or a list of properties that may include any of those symbols: + ;; `neutral-underline' OR `no-underline', `faint' OR `no-color', + ;; `bold', `italic', `background' + modus-themes-links '(neutral-underline background) + + ;; Options for `modus-themes-box-buttons' are either nil (the + ;; default), or a list that can combine any of `flat', `accented', + ;; `faint', `variable-pitch', `underline', `all-buttons', the + ;; symbol of any font weight as listed in `modus-themes-weights', + ;; and a floating point number (e.g. 0.9) for the height of the + ;; button's text. + modus-themes-box-buttons '(variable-pitch flat faint 0.9) + + ;; Options for `modus-themes-prompts' are either nil (the + ;; default), or a list of properties that may include any of those + ;; symbols: `background', `bold', `gray', `intense', `italic' + modus-themes-prompts '(intense bold) + + ;; The `modus-themes-completions' is an alist that reads three + ;; keys: `matches', `selection', `popup'. Each accepts a nil + ;; value (or empty list) or a list of properties that can include + ;; any of the following (for WEIGHT read further below): + ;; + ;; `matches' - `background', `intense', `underline', `italic', WEIGHT + ;; `selection' - `accented', `intense', `underline', `italic', `text-also' WEIGHT + ;; `popup' - same as `selected' + ;; `t' - applies to any key not explicitly referenced (check docs) + ;; + ;; WEIGHT is a symbol such as `semibold', `light', or anything + ;; covered in `modus-themes-weights'. Bold is used in the absence + ;; of an explicit WEIGHT. + modus-themes-completions '((matches . (extrabold)) + (selection . (semibold accented)) + (popup . (accented intense))) + + modus-themes-mail-citations nil ; {nil,'intense,'faint,'monochrome} + + ;; Options for `modus-themes-region' are either nil (the default), + ;; or a list of properties that may include any of those symbols: + ;; `no-extend', `bg-only', `accented' + modus-themes-region '(bg-only no-extend) + + ;; Options for `modus-themes-diffs': nil, 'desaturated, 'bg-only + modus-themes-diffs 'desaturated + + modus-themes-org-blocks 'gray-background ; {nil,'gray-background,'tinted-background} + + modus-themes-org-agenda ; this is an alist: read the manual or its doc string + '((header-block . (variable-pitch 1.3)) + (header-date . (grayscale workaholic bold-today 1.1)) + (event . (accented varied)) + (scheduled . uniform) + (habit . traffic-light)) + + modus-themes-headings ; this is an alist: read the manual or its doc string + '((1 . (overline background variable-pitch 1.3)) + (2 . (rainbow overline 1.1)) + (t . (semibold)))) +#+end_src + +** Option for inhibiting theme reload +:properties: +:alt_title: Custom reload theme +:description: Toggle auto-reload of the theme when setting custom variables +:custom_id: h:9001527a-4e2c-43e0-98e8-3ef72d770639 +:end: +#+vindex: modus-themes-inhibit-reload + +Brief: Toggle reloading of the active theme when an option is changed +through the Customize UI. + +Symbol: ~modus-themes-inhibit-reload~ (=boolean= type) + +Possible values: + +1. ~nil~ +2. ~t~ (default) + +By default, customizing a theme-related user option through the Custom +interfaces or with {{{kbd(M-x customize-set-variable)}}} will not reload the +currently active Modus theme. + +Enable this behavior by setting this variable to ~nil~. + +Regardless of this option, the active theme must be reloaded for changes +to user options to take effect ([[#h:3f3c3728-1b34-437d-9d0c-b110f5b161a9][Enable and load]]). + +** Option for red-green color deficiency or deuteranopia +:properties: +:alt_title: Deuteranopia style +:description: Toggle red/blue color-coding instead of red/green +:custom_id: h:3ed03a48-20d8-4ce7-b214-0eb7e4c79abe +:end: +#+vindex: modus-themes-deuteranopia + +Brief: When non-nil use red/blue color-coding instead of red/green, +where appropriate. + +Symbol: ~modus-themes-deuteranopia~ (=boolean= type) + +Possible values: + +1. ~nil~ (default) +2. ~t~ + +This is to account for red-green color deficiency, also know as +deuteranopia and variants. It applies to all contexts where there can +be a color-coded distinction between failure or success, a to-do or done +state, a mark for deletion versus a mark for selection (e.g. in Dired), +current and lazily highlighted search matches, removed lines in diffs as +opposed to added ones, and so on. + +Note that this does not change all colors throughout the active theme, +but only applies to cases that have color-coding significance. For +example, regular code syntax highlighting is not affected. There is no +such need because of the themes' overarching commitment to the highest +legibility standard, which ensures that text is readable regardless of +hue, as well as the predominance of colors on the +blue-cyan-magenta-purple side of the spectrum. + +[[#h:0b26cb47-9733-4cb1-87d9-50850cb0386e][Why are colors mostly variants of blue, magenta, cyan?]]. + +** Option for more bold constructs +:properties: +:alt_title: Bold constructs +:description: Toggle bold constructs in code +:custom_id: h:b25714f6-0fbe-41f6-89b5-6912d304091e +:end: +#+vindex: modus-themes-bold-constructs + +Brief: Use bold for code syntax highlighting and related. + +Symbol: ~modus-themes-bold-constructs~ (=boolean= type) + +Possible values: + +1. ~nil~ (default) +2. ~t~ + +The default is to use a bold typographic weight only when it is +required. + +With a non-nil value (~t~) display several syntactic constructs in bold +weight. This concerns keywords and other important aspects of code +syntax. It also affects certain mode line indicators and command-line +prompts. + +Advanced users may also want to configure the exact attributes of the +~bold~ face. + +[[#h:2793a224-2109-4f61-a106-721c57c01375][Configure bold and italic faces]]. + +** Option for more italic constructs +:properties: +:alt_title: Italic constructs +:description: Toggle italic font constructs in code +:custom_id: h:977c900d-0d6d-4dbb-82d9-c2aae69543d6 +:end: +#+vindex: modus-themes-italic-constructs + +Brief: Use italics for code syntax highlighting and related. + +Symbol: ~modus-themes-italic-constructs~ (=boolean= type) + +Possible values: + +1. ~nil~ (default) +2. ~t~ + +The default is to not use slanted text forms (italics) unless it is +absolutely necessary. + +With a non-nil value (~t~) choose to render more faces in italics. This +typically affects documentation strings and code comments. + +Advanced users may also want to configure the exact attributes of the +~italic~ face. + +[[#h:2793a224-2109-4f61-a106-721c57c01375][Configure bold and italic faces]]. + +** Option for syntax highlighting +:properties: +:alt_title: Syntax styles +:description: Choose the overall aesthetic of code syntax +:custom_id: h:c119d7b2-fcd4-4e44-890e-5e25733d5e52 +:end: +#+vindex: modus-themes-syntax + +Brief: Set the overall style of code syntax highlighting. + +Symbol: ~modus-themes-syntax~ (=choice= type, list of properties) + +Possible values are expressed as a list of properties (default is ~nil~ or +an empty list). The list can include any of the following symbols: + ++ ~faint~ ++ ~yellow-comments~ ++ ~green-strings~ ++ ~alt-syntax~ + +The default (a ~nil~ value or an empty list) is to use a balanced +combination of colors on the cyan-blue-magenta side of the spectrum. +There is little to no use of greens, yellows, and reds. Comments are +gray, strings are blue colored, doc strings are a shade of cyan, while +color combinations are designed to avoid exaggerations. + +The property ~faint~ fades the saturation of all applicable colors, where +that is possible or appropriate. + +The property ~yellow-comments~ applies a yellow color to comments. + +The property ~green-strings~ applies a green color to strings and a green +tint to doc strings. + +The property ~alt-syntax~ changes the combination of colors beyond strings +and comments, so that the effective palette is broadened to provide +greater variety relative to the default. + +Combinations of any of those properties are expressed as a list, like in +these examples: + +#+begin_src emacs-lisp +(faint) +(green-strings yellow-comments) +(alt-syntax green-strings yellow-comments) +(faint alt-syntax green-strings yellow-comments) +#+end_src + +The order in which the properties are set is not significant. + +In user configuration files the form may look like this: + +#+begin_src emacs-lisp +(setq modus-themes-syntax '(faint alt-syntax)) +#+end_src + +Independent of this variable, users may also control the use of a bold +weight or italic text: ~modus-themes-bold-constructs~ and +~modus-themes-italic-constructs~. + +[[#h:b25714f6-0fbe-41f6-89b5-6912d304091e][Option for more bold constructs]]. + +[[#h:977c900d-0d6d-4dbb-82d9-c2aae69543d6][Option for more italic constructs]]. + +** Option for font mixing +:properties: +:alt_title: Mixed fonts +:description: Toggle mixing of font families +:custom_id: h:115e6c23-ee35-4a16-8cef-e2fcbb08e28b +:end: +#+vindex: modus-themes-mixed-fonts + +Brief: Toggle the use of monospaced fonts for spacing-sensitive +constructs (affects font families). + +Symbol: ~modus-themes-mixed-fonts~ (=boolean= type) + +Possible values: + +1. ~nil~ (default) +2. ~t~ + +When set to non-nil (~t~), configure some spacing-sensitive faces like Org +tables and code blocks to always inherit from the ~fixed-pitch~ face. +This is to ensure that certain constructs like code blocks and tables +remain monospaced even when users opt for a mode that remaps typeface +families, such as the built-in {{{kbd(M-x variable-pitch-mode)}}}. Otherwise +the layout would appear broken, due to how spacing is done. + +For a consistent experience, user may need to specify the font family of +the ~fixed-pitch~ face. + +[[#h:defcf4fc-8fa8-4c29-b12e-7119582cc929][Font configurations for Org and others]]. + +Furthermore, users may prefer to use another package for handling mixed +typeface configurations, rather than letting the theme do it, perhaps +because a purpose-specific package has extra functionality. Two +possible options are ~org-variable-pitch~ and ~mixed-pitch~. + +** Option for links +:properties: +:alt_title: Link styles +:description: Choose among several styles, with or without underline +:custom_id: h:5808be52-361a-4d18-88fd-90129d206f9b +:end: +#+vindex: modus-themes-links + +Brief: Control the style of links to web pages, files, buffers... + +Symbol: ~modus-themes-links~ (=choice= type, list of properties) + +Possible values are expressed as a list of properties (default is ~nil~ or +an empty list). The list can include any of the following symbols: + ++ Underline style: + - ~neutral-underline~ + - ~no-underline~ ++ Text coloration: + - ~faint~ + - ~no-color~ ++ ~bold~ ++ ~italic~ ++ ~background~ + +The default (a ~nil~ value or an empty list) is a prominent text color, +typically blue, with an underline of the same color. + +For the style of the underline, a ~neutral-underline~ property turns the +color of the line into a subtle gray, while the ~no-underline~ property +removes the line altogether. If both of those are set, the latter takes +precedence. + +For text coloration, a ~faint~ property desaturates the color of the text +and the underline, unless the underline is affected by the +aforementioned properties. While a ~no-color~ property removes the color +from the text. If both of those are set, the latter takes precedence. + +A ~bold~ property applies a heavy typographic weight to the text of the +link. + +An ~italic~ property adds a slant to the link's text (italic or oblique +forms, depending on the typeface). + +A ~background~ property applies a subtle tinted background color. + +In case both ~no-underline~ and ~no-color~ are set, then a subtle gray +background is applied to all links. This can still be combined with the +~bold~ and ~italic~ properties. + +Combinations of any of those properties are expressed as a list, +like in these examples: + +#+begin_src emacs-lisp +(faint) +(no-underline faint) +(no-color no-underline bold) +(italic bold background no-color no-underline) +#+end_src + +The order in which the properties are set is not significant. + +In user configuration files the form may look like this: + +#+begin_src emacs-lisp +(setq modus-themes-links '(neutral-underline background)) +#+end_src + +The placement of the underline, meaning its proximity to the text, is +controlled by ~x-use-underline-position-properties~, +~x-underline-at-descent-line~, ~underline-minimum-offset~. Please refer to +their documentation strings. + +** Option for box buttons +:properties: +:alt_title: Box buttons +:description: Choose among several styles for buttons +:custom_id: h:8b85f711-ff40-45b0-b7fc-4727503cd2ec +:end: +#+vindex: modus-themes-box-buttons + +Brief: Control the style of buttons in the Custom UI and related. + +Symbol: ~modus-themes-box-buttons~ (=choice= type, list of properties) + +Possible values are expressed as a list of properties (default is ~nil~ or +an empty list). The list can include any of the following symbols: + ++ ~flat~ ++ ~accented~ ++ ~faint~ ++ ~variable-pitch~ ++ ~underline~ ++ A font weight, which must be supported by the underlying typeface: + - ~thin~ + - ~ultralight~ + - ~extralight~ + - ~light~ + - ~semilight~ + - ~regular~ + - ~medium~ + - ~semibold~ + - ~bold~ + - ~heavy~ + - ~extrabold~ + - ~ultrabold~ ++ A floating point as a height multiple of the default or a cons cell in + the form of =(height . FLOAT)= ++ ~all-buttons~ + +The default (a nil value or an empty list) is a gray background combined +with a pseudo three-dimensional effect. + +The ~flat~ property makes the button two dimensional. + +The ~accented~ property changes the background from gray to an accent +color. + +The ~faint~ property reduces the overall coloration. + +The ~variable-pitch~ property applies a proportionately spaced typeface +to the button~s text. + +[[#h:defcf4fc-8fa8-4c29-b12e-7119582cc929][Font configurations for Org and others]]. + +The ~underline~ property draws a line below the affected text and +removes whatever box effect. This is optimal when Emacs runs inside a +terminal emulator ([[#h:fbb5e254-afd6-4313-bb05-93b3b4f67358][More accurate colors in terminal emulators]]). If +~flat~ and ~underline~ are defined together, the latter takes +precedence. + +The symbol of a weight attribute adjusts the font of the button +accordingly, such as ~light~, ~semibold~, etc. Valid symbols are +defined in the variable ~modus-themes-weights~. + +[[#h:2793a224-2109-4f61-a106-721c57c01375][Configure bold and italic faces]]. + +A number, expressed as a floating point (e.g. =0.9=), adjusts the height +of the button's text to that many times the base font size. The default +height is the same as =1.0=, though it need not be explicitly stated. +Instead of a floating point, an acceptable value can be in the form of a +cons cell like =(height . FLOAT)= or =(height FLOAT)=, where FLOAT is +the given number. + +The ~all-buttons~ property extends the box button effect (or the +aforementioned properties) to the faces of the generic widget library. +By default, those do not look like the buttons of the Custom UI as they +are ordinary text wrapped in square brackets. + +Combinations of any of those properties are expressed as a list, +like in these examples: + +#+begin_src emacs-lisp +(flat) +(variable-pitch flat) +(variable-pitch flat semibold 0.9) +(variable-pitch flat semibold (height 0.9)) ; same as above +(variable-pitch flat semibold (height . 0.9)) ; same as above +#+end_src + +The order in which the properties are set is not significant. + +In user configuration files the form may look like this: + +#+begin_src emacs-lisp +(setq modus-themes-box-buttons '(variable-pitch flat 0.9)) +#+end_src + +** Option for command prompt styles +:properties: +:alt_title: Command prompts +:description: Choose among plain, subtle, or intense prompts +:custom_id: h:db5a9a7c-2928-4a28-b0f0-6f2b9bd52ba1 +:end: +#+vindex: modus-themes-prompts + +Brief: Control the style of command prompts (e.g. minibuffer, shell, IRC +clients). + +Symbol: ~modus-themes-prompts~ (=choice= type, list of properties) + +Possible values are expressed as a list of properties (default is ~nil~ or +an empty list). The list can include any of the following symbols: + ++ ~background~ ++ ~bold~ ++ ~gray~ ++ ~intense~ ++ ~italic~ + +The default (a ~nil~ value or an empty list) means to only use a subtle +accented foreground color. + +The property ~background~ applies a background color to the prompt's text. +By default, this is a subtle accented value. + +The property ~intense~ makes the foreground color more prominent. If the +~background~ property is also set, it amplifies the value of the +background as well. + +The property ~gray~ changes the prompt's colors to grayscale. This +affects the foreground and, if the ~background~ property is also set, the +background. Its effect is subtle, unless it is combined with the +~intense~ property. + +The property ~bold~ makes the text use a bold typographic weight. +Similarly, ~italic~ adds a slant to the font's forms (italic or oblique +forms, depending on the typeface). + +Combinations of any of those properties are expressed as a list, like in +these examples: + +#+begin_src emacs-lisp +(intense) +(bold intense) +(intense bold gray) +(intense background gray bold) +#+end_src + +The order in which the properties are set is not significant. + +In user configuration files the form may look like this: + +#+begin_src emacs-lisp +(setq modus-themes-prompts '(background gray)) +#+end_src + +** Option for mode line presentation +:properties: +:alt_title: Mode line +:description: Choose among several styles, with or without borders +:custom_id: h:27943af6-d950-42d0-bc23-106e43f50a24 +:end: +#+vindex: modus-themes-mode-line + +Brief: Control the style of the mode lines. + +Symbol: ~modus-themes-mode-line~ (=choice= type, list of properties) + +Possible values, which can be expressed as a list of combinations of box +effect, color, and border visibility: + ++ Overall style: + - ~3d~ + - ~moody~ ++ ~accented~ ++ ~borderless~ ++ A natural number > 1 for extra padding or a cons cell in the form of + ~(padding . NATNUM)~. ++ A floating point to set the height of the mode line's text. It can + also be a cons cell in the form of ~(height . FLOAT)~. + +The default (a nil value or an empty list) is a two-dimensional +rectangle with a border around it. The active and the inactive mode +lines use different shades of grayscale values for the background, +foreground, border. + +The ~3d~ property applies a three-dimensional effect to the active mode +line. The inactive mode lines remain two-dimensional and are toned down +a bit, relative to the default style. + +The ~moody~ property optimizes the mode line for use with the library of +the same name (hereinafter referred to as 'Moody'). In practice, it +removes the box effect and replaces it with underline and overline +properties. It also tones down the inactive mode lines. Despite its +intended purpose, this option can also be used without the Moody library +(please consult the themes' manual on this point for more details). If +both ~3d~ and ~moody~ properties are set, the latter takes precedence. + +The ~borderless~ property removes the color of the borders. It does not +actually remove the borders, but only makes their color the same as the +background, effectively creating some padding. + +The ~accented~ property ensures that the active mode line uses a colored +background instead of the standard shade of gray. + +A positive integer (natural number or natnum) applies a padding effect +of NATNUM pixels at the boundaries of the mode lines. The default value +is 1 and does not need to be specified explicitly. The padding has no +effect when the ~moody~ property is also used, because Moody already +applies its own tweaks. To ensure that the underline is placed at the +bottom of the mode line, set ~x-underline-at-descent-line~ to non-nil +(this is not needed when the ~borderless~ property is also set). For +users on Emacs 29, the ~x-use-underline-position-properties~ variable must +also be set to nil. + +The padding can also be expressed as a cons cell in the form of +=(padding . NATNUM)= or =(padding NATNUM)= where the key is constant and +NATNUM is the desired natural number. + +A floating point applies an adjusted height to the mode line's text as a +multiple of the main font size. The default rate is 1.0 and does not +need to be specified. Apart from a floating point, the height may also +be expressed as a cons cell in the form of =(height . FLOAT)= or +=(height FLOAT)= where the key is constant and the FLOAT is the desired +number. + +Combinations of any of those properties are expressed as a list, like in +these examples: + +#+begin_src emacs-lisp +(accented) +(borderless 3d) +(moody accented borderless) +#+end_src + +Same as above, using the padding and height as an example (these +all yield the same result): + +#+begin_src emacs-lisp +(accented borderless 4 0.9) +(accented borderless (padding . 4) (height . 0.9)) +(accented borderless (padding 4) (height 0.9)) +#+end_src + +The order in which the properties are set is not significant. + +In user configuration files the form may look like this: + +#+begin_src emacs-lisp +(setq modus-themes-mode-line '(borderless accented)) +#+end_src + +Note that Moody does not expose any faces that the themes could style +directly. Instead it re-purposes existing ones to render its tabs and +ribbons. As such, there may be cases where the contrast ratio falls +below the 7:1 target that the themes conform with (WCAG AAA). To hedge +against this, we configure a fallback foreground for the ~moody~ property, +which will come into effect when the background of the mode line changes +to something less accessible, such as Moody ribbons (read the doc string +of ~set-face-attribute~, specifically ~:distant-foreground~). This fallback +is activated when Emacs determines that the background and foreground of +the given construct are too close to each other in terms of color +distance. In practice, users will need to experiment with the variable +~face-near-same-color-threshold~ to trigger the effect. We find that a +value of =45000= shall suffice, contrary to the default =30000=. Though for +the combinations that involve the ~accented~ and ~moody~ properties, as +mentioned above, that should be raised up to =70000=. Do not set it too +high, because it has the adverse effect of always overriding the default +colors (which have been carefully designed to be highly accessible). + +Furthermore, because Moody expects an underline and overline instead of +a box style, it is strongly advised to set ~x-underline-at-descent-line~ +to a non-nil value. + +Finally, note that various packages which heavily modify the mode line, +such as =doom-modeline=, =nano-modeline=, =powerline=, =spaceline= may not look +as intended with all possible combinations of this user option. + +** Option for accented background in tab interfaces +:properties: +:alt_title: Tab style +:description: Toggle accented background for tabs +:custom_id: h:27cef8f5-dc4e-4c93-ba41-b899e650d936 +:end: +#+vindex: modus-themes-tabs-accented + +Brief: Toggle accent colors for tabbed interfaces. + +Symbol: ~modus-themes-tabs-accented~ (=boolean= type) + +Possible values: + ++ ~nil~ (default) ++ ~t~ + +By default, all tab interfaces use backgrounds which are shades of gray. +When this option is set to non-nil, the backgrounds become colorful. + +This affects the built-in ~tab-bar-mode~ and ~tab-line-mode~, as well as the +Centaur tabs package. + +** Option for completion framework aesthetics +:properties: +:alt_title: Completion UIs +:description: Choose among several styles for completion UIs +:custom_id: h:f1c20c02-7b34-4c35-9c65-99170efb2882 +:end: +#+vindex: modus-themes-completions + +Brief: Set the overall style of completion framework interfaces. + +Symbol: ~modus-themes-completions~ (=alist= type properties) + +This affects Company, Corfu, Flx, Helm, Icomplete/Fido, Ido, Ivy, +Orderless, Selectrum, Vertico. The value is an alist that takes the +form of a =(key . properties)= combination. Here is a sample, followed +by a description of the particularities: + +#+begin_src emacs-lisp +(setq modus-themes-completions + '((matches . (extrabold background intense)) + (selection . (semibold accented intense)) + (popup . (accented)))) +#+end_src + +The ~matches~ key refers to the highlighted characters that correspond +to the user's input. By default (nil or an empty list), they have a +bold weight and a colored foreground. The list of properties may +include any of the following symbols regardless of the order they may +appear in: + +- ~background~ to add a background color; + +- ~intense~ to increase the overall coloration (also amplifies + the ~background~, if present); + +- ~underline~ to draw a line below the characters; + +- ~italic~ to use a slanted font (italic or oblique forms); + +- The symbol of a font weight attribute such as ~light~, ~semibold~, et + cetera. Valid symbols are defined in the ~modus-themes-weights~ + variable. The absence of a weight means that bold will be used. + +The ~selection~ key applies to the current line or currently matched +candidate, depending on the specifics of the User Interface. By default +(nil or an empty list), it has a subtle gray background, a bold weight, +and the base foreground value for the text. The list of properties it +accepts is as follows (order is not significant): + +- ~accented~ to make the background colorful instead of gray; + +- ~text-also~ to apply extra color to the text of the selected line; + +- ~intense~ to increase the overall coloration; + +- ~underline~ to draw a line below the characters; + +- ~italic~ to use a slanted font (italic or oblique forms); + +- The symbol of a font weight attribute such as ~light~, ~semibold~, et + cetera. Valid symbols are defined in the ~modus-themes-weights~ + variable. The absence of a weight means that bold will be used. + +The ~popup~ key takes the same values as ~selection~. + +Apart from specifying each key separately, a fallback list is accepted. +This is only useful when the desired aesthetic is the same across all +keys that are not explicitly referenced. For example, this: + +#+begin_src emacs-lisp +(setq modus-themes-completions + '((t . (extrabold intense)))) +#+end_src + +Is the same as: + +#+begin_src emacs-lisp +(setq modus-themes-completions + '((matches . (extrabold intense)) + (selection . (extrabold intense)) + (popup . (extrabold intense)))) +#+end_src + +In the case of the fallback, any property that does not apply to the +corresponding key is simply ignored (~matches~ does not have ~accented~ +and ~text-also~, while ~selection~ and ~popup~ do not have +~background~). + +A concise expression of those associations can be written as follows, +where the ~car~ is always the key and the ~cdr~ is the list of +properties (whatever order they may appear in): + +#+begin_src emacs-lisp +(setq modus-themes-completions + '((matches extrabold background intense) + (selection semibold accented intense) + (popup accented))) +#+end_src + +[[#h:2793a224-2109-4f61-a106-721c57c01375][Configure bold and italic faces]]. + +Also refer to the Orderless documentation for its intersection with +Company (if you choose to use those in tandem). + +** Option for mail citations +:properties: +:alt_title: Mail citations +:description: Choose among colorful, desaturated, monochrome citations +:custom_id: h:5a12765d-0ba0-4a75-ab11-e35d3bbb317d +:end: +#+vindex: modus-themes-mail-citations + +Brief: Set the overall style of citations/quotes when composing +emails. + +Symbol: ~modus-themes-mail-citations~ (=choice= type) + +Possible values: + +1. ~nil~ (default) +2. ~intense~ +3. ~faint~ +4. ~monochrome~ + +By default (a nil value) citations are styled with contrasting hues to +denote their depth. Colors are easy to tell apart because they +complement each other, but they otherwise are not very prominent. + +Option ~intense~ is similar to the default in terms of using contrasting +and complementary hues, but applies more saturated colors. + +Option ~faint~ maintains the same color-based distinction between citation +levels though the colors it uses have subtle differences between them. + +Option ~monochrome~ turns all quotes into a shade of gray. + +Whatever the value assigned to this variable, citations in emails are +controlled by typographic elements or indentation, which the themes do +not touch. + +** Option for fringe visibility +:properties: +:alt_title: Fringes +:description: Choose among invisible, subtle, or intense fringe styles +:custom_id: h:1983c3fc-74f6-44f3-b917-967c403bebae +:end: +#+vindex: modus-themes-fringes + +Brief: Control the overall coloration of the fringes. + +Symbol: ~modus-themes-fringes~ (=choice= type) + +Possible values: + +1. ~nil~ (default) +2. ~subtle~ +3. ~intense~ + +The default is to use the same color as that of the main background, +meaning that the fringes are not obvious though they still occupy the +space given to them by ~fringe-mode~. + +Options ~subtle~ and ~intense~ apply a gray background, making the fringes +visible. The difference between the two is one of degree, as their +names imply. + +** Option for language checkers +:properties: +:alt_title: Language checkers +:description: Control the style of language checkers/linters +:custom_id: h:4b13743a-8ebf-4d2c-a043-cceba10b1eb4 +:end: +#+vindex: modus-themes-lang-checkers + +Brief: Control the style of in-buffer warnings and errors produced by +spell checkers, code linters, and the like. + +Symbol: ~modus-themes-lang-checkers~ (=choice= type, list of properties) + +Possible values are expressed as a list of properties (default is ~nil~ or +an empty list). The list can include any of the following symbols: + ++ ~straight-underline~ ++ ~text-also~ ++ ~background~ ++ Overall coloration: + - ~intense~ + - ~faint~ + +The default (a ~nil~ value or an empty list) applies a color-coded +underline to the affected text, while it leaves the original foreground +intact. If the display spec of Emacs has support for it, the +underline's style is that of a wave, otherwise it is a straight line. + +The property ~straight-underline~ ensures that the underline under the +affected text is always drawn as a straight line. + +The property ~text-also~ applies the same color of the underline to the +affected text. + +The property ~background~ adds a color-coded background. + +The property ~intense~ amplifies the applicable colors if ~background~ +and/or ~text-also~ are set. If ~intense~ is set on its own, then it implies +~text-also~. + +The property ~faint~ uses nuanced colors for the underline and for the +foreground when ~text-also~ is included. If both ~faint~ and ~intense~ are +specified, the former takes precedence. + +Combinations of any of those properties can be expressed in a list, as +in those examples: + +#+begin_src emacs-lisp +(background) +(straight-underline intense) +(background text-also straight-underline) +#+end_src + +The order in which the properties are set is not significant. + +In user configuration files the form may look like this: + +#+begin_src emacs-lisp +(setq modus-themes-lang-checkers '(text-also background)) +#+end_src + +NOTE: The placement of the straight underline, though not the wave +style, is controlled by the built-in variables ~underline-minimum-offset~, +~x-underline-at-descent-line~, ~x-use-underline-position-properties~. + +To disable fringe indicators for Flymake or Flycheck, refer to variables +~flymake-fringe-indicator-position~ and ~flycheck-indication-mode~, +respectively. + +** Option for line highlighting +:properties: +:alt_title: Line highlighting +:description: Choose style of current line (hl-line-mode) +:custom_id: h:1dba1cfe-d079-4c13-a810-f768e8789177 +:end: +#+vindex: modus-themes-hl-line + +Brief: Control the style of the current line of ~hl-line-mode~. + +Symbol: ~modus-themes-hl-line~ (=choice= type, list of properties) + +Possible values are expressed as a list of properties (default is ~nil~ or +an empty list). The list can include any of the following symbols: + ++ ~accented~ ++ ~intense~ ++ ~underline~ + +The default (a ~nil~ value or an empty list) is a subtle gray background +color. + +The property ~accented~ changes the background to a colored variant. + +An ~underline~ property draws a line below the highlighted area. Its +color is similar to the background, so gray by default or an accent +color when ~accented~ is also set. + +An ~intense~ property amplifies the colors in use, which may be both the +background and the underline. + +Combinations of any of those properties are expressed as a list, like in +these examples: + +#+begin_src emacs-lisp +(intense) +(underline intense) +(accented intense underline) +#+end_src + +The order in which the properties are set is not significant. + +In user configuration files the form may look like this: + +#+begin_src emacs-lisp +(setq modus-themes-hl-line '(underline accented)) +#+end_src + +Set ~x-underline-at-descent-line~ to a non-nil value for better results +with underlines. + +This style affects several packages that enable ~hl-line-mode~, such as +=elfeed=, =notmuch=, and =mu4e=. + +[ Also check the =lin= package on GNU ELPA (by the author of the + modus-themes) for a stylistic enhancement to ~hl-line-mode~. ] + +** Option for line numbers +:properties: +:alt_title: Line numbers +:description: Toggle subtle style for line numbers +:custom_id: h:8c4a6230-2e43-4aa2-a631-3b7179392e09 +:end: +#+vindex: modus-themes-subtle-line-numbers + +Brief: Toggle subtle line numbers. + +Symbol: ~modus-themes-subtle-line-numbers~ (=boolean= type) + +Possible value: + +1. ~nil~ (default) +2. ~t~ + +The default style for ~display-line-numbers-mode~ and its global variant +is to apply a subtle gray background to the line numbers. The current +line has a more pronounced background and foreground combination to +bring more attention to itself. + +Similarly, the faces for ~display-line-numbers-major-tick~ and its +counterpart ~display-line-numbers-minor-tick~ use appropriate styles that +involve a bespoke background and foreground combination. + +With a non-nil value (~t~), line numbers have no background of their own. +Instead they retain the primary background of the theme, blending with +the rest of the buffer. Foreground values for all relevant faces are +updated to accommodate this aesthetic. + +** Option for mouseover effects +:properties: +:alt_title: Mouse hover effects +:description: Toggle intense style for mouseover highlights +:custom_id: h:9b869620-fcc5-4b5f-9ab8-225d73b7f22f +:end: +#+vindex: modus-themes-intense-mouseovers + +Brief: Toggle intense mouse hover effects. + +Symbol: ~modus-themes-intense-mouseovers~ (=boolean= type) + +Possible value: + +1. ~nil~ (default) +2. ~t~ + +By default all mouseover effects apply a highlight with a subtle colored +background. When non-nil, these have a more pronounced effect. + +Note that this affects the generic ~highlight~ which, strictly speaking, +is not limited to mouse usage. + +** Option for markup style in Org and others +:properties: +:alt_title: Markup +:description: Choose style for markup in Org and others +:custom_id: h:9d9a4e64-99ac-4018-8f66-3051b9c43fd7 +:end: +#+vindex: modus-themes-markup + +Brief: Choose style of markup in Org, Markdown, and others (affects +constructs such as Org's ==verbatim== and =~code~=). + +Symbol: ~modus-themes-markup~ (=boolean= type) + +Possible values are expressed as a list of properties (default is ~nil~ or +an empty list). The list can include any of the following symbols: + +1. ~bold~ +2. ~italic~ +3. ~background~ +4. ~intense~ + +The ~italic~ property applies a typographic slant (italics). + +The ~bold~ property applies a heavier typographic weight. + +[[#h:2793a224-2109-4f61-a106-721c57c01375][Configure bold and italic faces]]. + +The ~background~ property adds a background color. The background is a +shade of gray, unless the ~intense~ property is also set. + +The ~intense~ property amplifies the existing coloration. When +~background~ is used, the background color is enhanced as well and +becomes tinted instead of being gray. + +Combinations of any of those properties are expressed as a list, +like in these examples: + +#+begin_src emacs-lisp +(bold) +(bold italic) +(bold italic intense) +(bold italic intense background) +#+end_src + +The order in which the properties are set is not significant. + +In user configuration files the form may look like this: + +#+begin_src emacs-lisp +(setq modus-themes-markup '(bold italic)) +#+end_src + +Also check the variables ~org-hide-emphasis-markers~, +~org-hide-macro-markers~. + +** Option for parenthesis matching +:properties: +:alt_title: Matching parentheses +:description: Choose between various styles for matching delimiters/parentheses +:custom_id: h:e66a7e4d-a512-4bc7-9f86-fbbb5923bf37 +:end: +#+vindex: modus-themes-paren-match + +Brief: Control the style of matching delimiters produced by +~show-paren-mode~. + +Symbol: ~modus-themes-paren-match~ (=choice= type, list of properties) + +Possible values are expressed as a list of properties (default is ~nil~ or +an empty list). The list can include any of the following symbols: + ++ ~bold~ ++ ~intense~ ++ ~underline~ + +The default (a ~nil~ value or an empty list) is a subtle background color. + +The ~bold~ property adds a bold weight to the characters of the matching +delimiters. + +The ~intense~ property applies a more prominent background color to the +delimiters. + +The ~underline~ property draws a straight line under the affected text. + +Combinations of any of those properties are expressed as a list, like in +these examples: + +#+begin_src emacs-lisp +(bold) +(underline intense) +(bold intense underline) +#+end_src + +The order in which the properties are set is not significant. + +In user configuration files the form may look like this: + +#+begin_src emacs-lisp +(setq modus-themes-paren-match '(bold intense)) +#+end_src + +This customization variable affects the built-in ~show-paren-mode~ and the +=smartparens= package. + +** Option for active region +:properties: +:alt_title: Active region +:description: Choose between various styles for the active region +:custom_id: h:60798063-b4ad-45ea-b9a7-ff7b5c0ab74c +:end: +#+vindex: modus-themes-region + +Brief: Control the style of the region. + +Symbol: ~modus-themes-region~ (=choice= type, list of properties) + +Possible values are expressed as a list of properties (default is ~nil~ or +an empty list). The list can include any of the following symbols: + ++ ~no-extend~ ++ ~bg-only~ ++ ~accented~ + +The default (a ~nil~ value or an empty list) is a prominent gray +background that overrides all foreground colors in the area it +encompasses. Its reach extends to the edge of the window. + +The ~no-extend~ property limits the region to the end of the line, so that +it does not reach the edge of the window. + +The ~bg-only~ property makes the region's background color more subtle to +allow the underlying text to retain its foreground colors. + +The ~accented~ property applies a more colorful background to the region. + +Combinations of any of those properties are expressed as a list, like in +these examples: + +#+begin_src emacs-lisp +(no-extend) +(bg-only accented) +(accented bg-only no-extend) +#+end_src + +The order in which the properties are set is not significant. + +In user configuration files the form may look like this: + +#+begin_src emacs-lisp +(setq modus-themes-region '(bg-only no-extend)) +#+end_src + +** Option for diff buffer looks +:properties: +:alt_title: Diffs +:description: Choose among intense, desaturated, or background-only diffs +:custom_id: h:ea7ac54f-5827-49bd-b09f-62424b3b6427 +:end: +#+vindex: modus-themes-diffs + +Brief: Set the overall style of diffs. + +Symbol: ~modus-themes-diffs~ (=choice= type) + +Possible values: + +1. ~nil~ (default) +2. ~desaturated~ +3. ~bg-only~ + +The default (~nil~) uses fairly intense color combinations for diffs, by +applying prominently colored backgrounds, with appropriately tinted +foregrounds. + +Option ~desaturated~ follows the same principles as with the default +(~nil~), though it tones down all relevant colors. + +Option ~bg-only~ applies a background but does not override the text's +foreground. This makes it suitable for a non-nil value passed to +~diff-font-lock-syntax~ (note: Magit does not support syntax highlighting +in diffs---last checked on 2021-12-02). + +When the user option ~modus-themes-deuteranopia~ is non-nil, all diffs +will use a red/blue color-coding system instead of the standard +red/green. Other stylistic changes are made in the interest of +optimizing for such a use-case. + +[[#h:3ed03a48-20d8-4ce7-b214-0eb7e4c79abe][Option for red-green color deficiency or deuteranopia]]. + +In versions before =2.0.0= there was an option for foreground-only diffs. +This is no longer supported at the theme level because there are cases +where the perceived contrast and overall contextuality were not good +enough although the applied colors were technically above the 7:1 +contrast threshold. + +[[#h:e2aed9eb-5e1e-45ec-bbd7-bc4faeab3236][Diffs with only the foreground]]. + +[[#h:b0b31802-0216-427e-b071-1a47adcfe608][Ediff without diff color-coding]]. + +** Option for org-mode block styles +:properties: +:alt_title: Org mode blocks +:description: Choose among plain, gray, or tinted backgrounds +:custom_id: h:b7e328c0-3034-4db7-9cdf-d5ba12081ca2 +:end: +#+vindex: modus-themes-org-blocks + +Brief: Set the overall style of Org code blocks, quotes, and the like. + +Symbol: ~modus-themes-org-blocks~ (=choice= type) + +Possible values: + +1. ~nil~ (default) +2. ~gray-background~ (value ~grayscale~ exists for backward compatibility) +3. ~tinted-background~ (value ~rainbow~ exists for backward compatibility) + +Nil (the default) means that the block has no background of its own: it +uses the one that applies to the rest of the buffer. In this case, the +delimiter lines have a gray color for their text, making them look +exactly like all other Org properties. + +Option ~gray-background~ applies a subtle gray background to the block's +contents. It also affects the begin and end lines of the block as they +get another shade of gray as their background, which differentiates them +from the contents of the block. All background colors extend to the +edge of the window, giving the area a rectangular, "blocky" +presentation. + +Option ~tinted-background~ uses a slightly colored background for the +contents of the block. The exact color will depend on the programming +language and is controlled by the variable ~org-src-block-faces~ (refer to +the theme's source code for the current association list). For this to +take effect, the Org buffer needs to be restarted with ~org-mode-restart~. +In this scenario, it may be better to inhibit the extension of the +delimiter lines' background to the edge of the window because Org does +not provide a mechanism to update their colors depending on the contents +of the block. Disable the extension of such backgrounds by setting +~org-fontify-whole-block-delimiter-line~ to nil. + +Code blocks use their major mode's colors only when the variable +~org-src-fontify-natively~ is non-nil. While quote/verse blocks require +setting ~org-fontify-quote-and-verse-blocks~ to a non-nil value. + +[[#h:f44cc6e3-b0f1-4a5e-8a90-9e48fa557b50][Update Org block delimiter fontification]]. + +Older versions of the themes provided options ~grayscale~ (or ~greyscale~) +and ~rainbow~. Those will continue to work as they are aliases for +~gray-background~ and ~tinted-background~, respectively. + +** Option for Org agenda constructs +:properties: +:alt_title: Org agenda +:description: Control each element in the presentation of the agenda +:custom_id: h:68f481bc-5904-4725-a3e6-d7ecfa7c3dbc +:end: +#+vindex: modus-themes-org-agenda + +Brief: Control the style of the Org agenda. Multiple parameters are +available, each with its own options. + +Symbol: ~modus-themes-org-agenda~ (=alist= type, multiple styles) + +This is an alist that accepts a =(key . value)= combination. Some values +are specified as a list. Here is a sample, followed by a description of +all possible combinations: + +#+begin_src emacs-lisp +(setq modus-themes-org-agenda + '((header-block . (variable-pitch 1.5)) + (header-date . (grayscale workaholic bold-today 1.2)) + (event . (accented italic varied)) + (scheduled . uniform) + (habit . traffic-light))) +#+end_src + +A ~header-block~ key applies to elements that concern the headings which +demarcate blocks in the structure of the agenda. By default (a ~nil~ +value) those are rendered in a bold typographic weight, plus a height +that is slightly taller than the default font size. Acceptable values +come in the form of a list that can include either or both of those +properties: + +- ~variable-pitch~ to use a proportionately spaced typeface; + +- A number as a floating point (e.g. 1.5) to set the height of the text + to that many times the default font height. A float of 1.0 or the + symbol ~no-scale~ have the same effect of making the font the same + height as the rest of the buffer. When neither a number nor + `no-scale' are present, the default is a small increase in height (a + value of 1.15). + + Instead of a floating point, an acceptable value can be in the form of + a cons cell like =(height . FLOAT)= or =(height FLOAT)=, where FLOAT + is the given number. + +- The symbol of a weight attribute adjusts the font of the heading + accordingly, such as ~light~, ~semibold~, etc. Valid symbols are + defined in the variable ~modus-themes-weights~. The absence of a + weight means that bold will be used by virtue of inheriting the ~bold~ + face. + +[[#h:2793a224-2109-4f61-a106-721c57c01375][Configure bold and italic faces]]. + +In case both a number and ~no-scale~ are in the list, the latter takes +precedence. If two numbers are specified, the first one is applied. + +Example usage: + +#+begin_src emacs-lisp +(header-block . nil) +(header-block . (1.5)) +(header-block . (no-scale)) +(header-block . (variable-pitch 1.5)) +(header-block . (variable-pitch 1.5 semibold)) +#+end_src + +A ~header-date~ key covers date headings. Dates use only a foreground +color by default (a ~nil~ value), with weekdays and weekends having a +slight difference in hueness. The current date has an added gray +background. This key accepts a list of values that can include any of +the following properties: + +- ~grayscale~ to make weekdays use the main foreground color and + weekends a more subtle gray; + +- ~workaholic~ to make weekdays and weekends look the same in + terms of color; + +- ~bold-today~ to apply a bold typographic weight to the current + date; + +- ~bold-all~ to render all date headings in a bold weight; + +- ~underline-today~ applies an underline to the current date while + removing the background it has by default; + +- A number as a floating point (e.g. 1.2) to set the height of the text + to that many times the default font height. The default is the same + as the base font height (the equivalent of 1.0). Instead of a + floating point, an acceptable value can be in the form of a cons cell + like =(height . FLOAT)= or =(height FLOAT)=, where FLOAT is the given + number. + +For example: + +#+begin_src emacs-lisp +(header-date . nil) +(header-date . (workaholic)) +(header-date . (grayscale bold-all)) +(header-date . (grayscale workaholic)) +(header-date . (grayscale workaholic bold-today)) +(header-date . (grayscale workaholic bold-today scale-heading)) +#+end_src + +An ~event~ key covers (i) headings with a plain time stamp that are +shown on the agenda, also known as events, (ii) entries imported from +the diary, and (iii) other items that derive from a symbolic expression +or sexp (phases of the moon, holidays, etc.). By default all those look +the same and have a subtle foreground color (the default is a nil value +or an empty list). This key accepts a list of properties. Those are: + +- ~accented~ applies an accent value to the event's foreground, + replacing the original gray. It makes all entries stand out more. +- ~italic~ adds a slant to the font's forms (italic or oblique forms, + depending on the typeface). +- ~varied~ differentiates between events with a plain time stamp and + entries that are generated from either the diary or a symbolic + expression. It generally puts more emphasis on events. When ~varied~ + is combined with ~accented~, it makes only events use an accent color, + while diary/sexp entries retain their original subtle foreground. + When ~varied~ is used in tandem with ~italic~, it applies a slant only + to diary and sexp entries, not events. And when ~varied~ is the sole + property passed to the ~event~ key, it has the same meaning as the + list (italic varied). The combination of ~varied~, ~accented~, + ~italic~ covers all of the aforementioned cases. + +For example: + +#+begin_src emacs-lisp +(event . nil) +(event . (italic)) +(event . (accented italic)) +(event . (accented italic varied)) +#+end_src + +A ~scheduled~ key applies to tasks with a scheduled date. By default (a +~nil~ value), those use varying shades of yellow to denote (i) a past or +current date and (ii) a future date. Valid values are symbols: + +- nil (default); +- ~uniform~ to make all scheduled dates the same color; +- ~rainbow~ to use contrasting colors for past, present, future + scheduled dates. + +For example: + +#+begin_src emacs-lisp +(scheduled . nil) +(scheduled . uniform) +(scheduled . rainbow) +#+end_src + +A ~habit~ key applies to the ~org-habit~ graph. All possible value are +passed as a symbol. Those are: + +- The default (~nil~) is meant to conform with the original aesthetic of + ~org-habit~. It employs all four color codes that correspond to the + org-habit states---clear, ready, alert, and overdue---while + distinguishing between their present and future variants. This + results in a total of eight colors in use: red, yellow, green, blue, + in tinted and shaded versions. They cover the full set of information + provided by the ~org-habit~ consistency graph. +- ~simplified~ is like the default except that it removes the dichotomy + between current and future variants by applying uniform color-coded + values. It applies a total of four colors: red, yellow, green, blue. + They produce a simplified consistency graph that is more legible (or + less busy) than the default. The intent is to shift focus towards the + distinction between the four states of a habit task, rather than each + state's present/future outlook. +- ~traffic-light~ further reduces the available colors to red, yellow, and + green. As in ~simplified~, present and future variants appear + uniformly, but differently from it, the ~clear~ state is rendered in a + green hue, instead of the original blue. This is meant to capture the + use-case where a habit task being too early is less important than it + being too late. The difference between ready and clear states is + attenuated by painting both of them using shades of green. This + option thus highlights the alert and overdue states. +- When ~modus-themes-deuteranopia~ is non-nil the exact style of the habit + graph adapts to the needs of users with red-green color deficiency by + substituting every instance of green with blue or cyan (depending on + the specifics). + +[[#h:3ed03a48-20d8-4ce7-b214-0eb7e4c79abe][Option for red-green color deficiency or deuteranopia]]. + +For example: + +#+begin_src emacs-lisp +(habit . nil) +(habit . simplified) +(habit . traffic-light) +#+end_src + +Putting it all together, the alist can look like this: + +#+begin_src emacs-lisp +'((header-block . (1.5 variable-pitch)) + (header-date . (grayscale workaholic bold-today)) + (event . (accented varied)) + (scheduled . uniform) + (habit . traffic-light)) + +;; Or else: +(setq modus-themes-org-agenda + '((header-block . (1.5 variable-pitch)) + (header-date . (grayscale workaholic bold-today)) + (event . (accented varied)) + (scheduled . uniform) + (habit . traffic-light))) +#+end_src + +** Option for the headings' overall style +:properties: +:alt_title: Heading styles +:description: Choose among several styles, also per heading level +:custom_id: h:271eff19-97aa-4090-9415-a6463c2f9ae1 +:end: +#+vindex: modus-themes-headings + +Brief: Heading styles with optional list of values for levels 0-8. + +Symbol: ~modus-themes-headings~ (=alist= type, multiple properties) + +This is an alist that accepts a =(key . list-of-values)= combination. +The key is either a number, representing the heading's level (0-8) or t, +which pertains to the fallback style. + +Level 0 is a special heading: it is used for what counts as a document +title or equivalent, such as the =#+title= construct we find in Org +files. Levels 1-8 are regular headings. + +The list of values covers symbols that refer to properties, as described +below. Here is a complete sample, followed by a presentation of all +available properties: + +#+begin_src emacs-lisp +(setq modus-themes-headings + '((1 . (background overline variable-pitch 1.5)) + (2 . (overline rainbow 1.3)) + (3 . (overline 1.1)) + (t . (monochrome)))) +#+end_src + +Properties: + ++ ~rainbow~ ++ ~overline~ ++ ~background~ ++ ~monochrome~ ++ A font weight, which must be supported by the underlying typeface: + - ~thin~ + - ~ultralight~ + - ~extralight~ + - ~light~ + - ~semilight~ + - ~regular~ + - ~medium~ + - ~semibold~ + - ~bold~ + - ~heavy~ + - ~extrabold~ + - ~ultrabold~ ++ ~no-bold~ (deprecated alias of a ~regular~ weight) ++ A floating point as a height multiple of the default or a cons cell in + the form of =(height . FLOAT)=. + +By default (a ~nil~ value for this variable), all headings have a bold +typographic weight and use a desaturated text color. + +A ~rainbow~ property makes the text color more saturated. + +An ~overline~ property draws a line above the area of the heading. + +A ~background~ property adds a subtle tinted color to the background of +the heading. + +A ~monochrome~ property makes the heading the same as the base color, +which is that of the ~default~ face's foreground. When ~background~ is also +set, ~monochrome~ changes its color to gray. If both ~monochrome~ and +~rainbow~ are set, the former takes precedence. + +A ~variable-pitch~ property changes the font family of the heading to that +of the ~variable-pitch~ face (normally a proportionately spaced typeface). + +The symbol of a weight attribute adjusts the font of the heading +accordingly, such as ~light~, ~semibold~, etc. Valid symbols are +defined in the variable ~modus-themes-weights~. The absence of a weight +means that bold will be used by virtue of inheriting the ~bold~ face. +For backward compatibility, the ~no-bold~ value is accepted, though +users are encouraged to specify a ~regular~ weight instead. + +[[#h:2793a224-2109-4f61-a106-721c57c01375][Configure bold and italic faces]]. + +A number, expressed as a floating point (e.g. 1.5), adjusts the height +of the heading to that many times the base font size. The default +height is the same as 1.0, though it need not be explicitly stated. +Instead of a floating point, an acceptable value can be in the form of a +cons cell like =(height . FLOAT)= or =(height FLOAT)=, where FLOAT is +the given number. + +Combinations of any of those properties are expressed as a list, like in +these examples: + +#+begin_src emacs-lisp +(semibold) +(rainbow background) +(overline monochrome semibold 1.3) +(overline monochrome semibold (height 1.3)) ; same as above +(overline monochrome semibold (height . 1.3)) ; same as above +#+end_src + +The order in which the properties are set is not significant. + +In user configuration files the form may look like this: + +#+begin_src emacs-lisp +(setq modus-themes-headings + '((1 . (background overline rainbow 1.5)) + (2 . (background overline 1.3)) + (t . (overline semibold)))) +#+end_src + +When defining the styles per heading level, it is possible to pass a +non-nil value (~t~) instead of a list of properties. This will retain the +original aesthetic for that level. For example: + +#+begin_src emacs-lisp +(setq modus-themes-headings + '((1 . t) ; keep the default style + (2 . (background overline)) + (t . (rainbow)))) ; style for all other headings + +(setq modus-themes-headings + '((1 . (background overline)) + (2 . (rainbow semibold)) + (t . t))) ; default style for all other levels +#+end_src + +For Org users, the extent of the heading depends on the variable +~org-fontify-whole-heading-line~. This affects the ~overline~ and +~background~ properties. Depending on the version of Org, there may be +others, such as ~org-fontify-done-headline~. + +** Option for variable-pitch font in UI elements +:properties: +:alt_title: UI typeface +:description: Toggle the use of variable-pitch across the User Interface +:custom_id: h:16cf666c-5e65-424c-a855-7ea8a4a1fcac +:end: +#+vindex: modus-themes-variable-pitch-ui + +Brief: Toggle the use of proportionately spaced (~variable-pitch~) fonts +in the User Interface. + +Symbol: ~modus-themes-variable-pitch-ui~ (=boolean= type) + +Possible values: + +1. ~nil~ (default) +2. ~t~ + +This option concerns User Interface elements that are under the direct +control of Emacs. In particular: the mode line, header line, tab bar, +and tab line. + +The default is to use the same font as the rest of Emacs, which usually +is a monospaced family. + +With a non-nil value (~t~) apply a proportionately spaced typeface. This +is done by assigning the ~variable-pitch~ face to the relevant items. + +[[#h:defcf4fc-8fa8-4c29-b12e-7119582cc929][Font configurations for Org and others]]. + +* Advanced customization +:properties: +:custom_id: h:f4651d55-8c07-46aa-b52b-bed1e53463bb +:end: + +Unlike the predefined customization options which follow a clear pattern +of allowing the user to quickly specify their preference, the themes +also provide a more flexible, albeit difficult, mechanism to control +things with precision ([[#h:bf1c82f2-46c7-4eb2-ad00-dd11fdd8b53f][Customization Options]]). + +This section is of interest only to users who are prepared to maintain +their own local tweaks and who are willing to deal with any possible +incompatibilities between versioned releases of the themes. As such, +they are labeled as "do-it-yourself" or "DIY". + +** More accurate colors in terminal emulators +:PROPERTIES: +:CUSTOM_ID: h:fbb5e254-afd6-4313-bb05-93b3b4f67358 +:END: +#+cindex: Color accuracy of terminal emulators + +[ This is based on partial information. Please help verify and/or + expand these findings. ] + +The graphical version of Emacs can reproduce color values accurately. +Whereas things get more tricky when Emacs is used in a terminal +emulator, because the terminals' own capabilities determine the number +of colors that may be displayed: the Modus themes don't look as good in +that case. + +There is, however, a way to instruct supported terminal emulators to use +more accurate colors. In a shell prompt type =toe -a | grep direct= to +get a list of relevant terminfo entries. There should be items such as +=xterm-direct=, =alacritty-direct=, =kitty-direct=. Once you find the one +that corresponds to your terminal, call Emacs with an environment +variable like =TERM=xterm-direct=. Example that can be adapted to shell +aliases: + +: TERM=xterm-direct emacsclient -nw + +Another example that can be bound to a key: + +: TERM=xterm-direct uxterm -e emacsclient -nw + +** Range of color with terminal emulators +:PROPERTIES: +:CUSTOM_ID: h:6b8211b0-d11b-4c00-9543-4685ec3b742f +:END: +#+cindex: Pure white and pure black in terminal emulators + +[ This is based on partial information. Please help verify and/or + expand these findings. ] + +When Emacs runs in a non-windowed session its color reproduction +capacity is framed or determined by the underlying terminal emulator +([[#h:fbb5e254-afd6-4313-bb05-93b3b4f67358][More accurate colors in terminal emulators]]). Emacs cannot produce a +color that lies outside the range of what the terminal's color palette +renders possible. + +This is immediately noticeable when the terminal's first 16 codes do not +include a pure black value for the =termcol0= entry and a pure white for +=termcol15=. Emacs cannot set the correct background (white for +~modus-operandi~; black for ~modus-vivendi~) or foreground (inverse of +the background). It thus falls back to the closest approximation, which +seldom is appropriate for the purposes of the Modus themes. + +In such a case, the user is expected to update their terminal's color +palette such as by adapting these resources: + +#+begin_src emacs-lisp +! Theme: modus-operandi +! Description: XTerm port of modus-operandi (Modus themes for GNU Emacs) +! Author: Protesilaos Stavrou, <https://protesilaos.com> +xterm*background: #ffffff +xterm*foreground: #000000 +xterm*color0: #000000 +xterm*color1: #a60000 +xterm*color2: #005e00 +xterm*color3: #813e00 +xterm*color4: #0031a9 +xterm*color5: #721045 +xterm*color6: #00538b +xterm*color7: #bfbfbf +xterm*color8: #595959 +xterm*color9: #972500 +xterm*color10: #315b00 +xterm*color11: #70480f +xterm*color12: #2544bb +xterm*color13: #5317ac +xterm*color14: #005a5f +xterm*color15: #ffffff + +! Theme: modus-vivendi +! Description: XTerm port of modus-vivendi (Modus themes for GNU Emacs) +! Author: Protesilaos Stavrou, <https://protesilaos.com> +xterm*background: #000000 +xterm*foreground: #ffffff +xterm*color0: #000000 +xterm*color1: #ff8059 +xterm*color2: #44bc44 +xterm*color3: #d0bc00 +xterm*color4: #2fafff +xterm*color5: #feacd0 +xterm*color6: #00d3d0 +xterm*color7: #bfbfbf +xterm*color8: #595959 +xterm*color9: #ef8b50 +xterm*color10: #70b900 +xterm*color11: #c0c530 +xterm*color12: #79a8ff +xterm*color13: #b6a0ff +xterm*color14: #6ae4b9 +xterm*color15: #ffffff +#+end_src + +** Visualize the active Modus theme's palette +:properties: +:custom_id: h:f4d4b71b-2ca5-4c3d-b0b4-9bfd7aa7fb4d +:end: +#+findex: modus-themes-list-colors +#+findex: modus-themes-list-colors-current +#+cindex: Preview color values + +The command ~modus-themes-list-colors~ prompts for a choice between +=modus-operandi= and =modus-vivendi= to produce a help buffer that shows a +preview of each variable in the given theme's color palette. The +command ~modus-themes-list-colors-current~ skips the prompt, using the +current Modus theme. + +Each row shows a foreground and background coloration using the +underlying value it references. For example a line with =#a60000= (a +shade of red) will show red text followed by a stripe with that same +color as a backdrop. + +The name of the buffer describes the given Modus theme. It is thus +called =*modus-operandi-list-colors*= or =*modus-vivendi-list-colors*=. + +** Per-theme customization settings +:properties: +:custom_id: h:a897b302-8e10-4a26-beab-3caaee1e1193 +:end: + +If you prefer to maintain different customization options between the +two themes, it is best you write your own functions that first set those +options and then load the relevant theme. The following code does +exactly that by simply differentiating the two themes on the choice of +bold constructs in code syntax (enabled for one, disabled for the +other). + +#+begin_src emacs-lisp +(defun my-demo-modus-operandi () + (interactive) + (setq modus-themes-bold-constructs t) ; ENABLE bold + (modus-themes-load-operandi)) + +(defun my-demo-modus-vivendi () + (interactive) + (setq modus-themes-bold-constructs nil) ; DISABLE bold + (modus-themes-load-vivendi)) + +(defun my-demo-modus-themes-toggle () + (if (eq (car custom-enabled-themes) 'modus-operandi) + (my-demo-modus-vivendi) + (my-demo-modus-operandi))) +#+end_src + +Then assign ~my-demo-modus-themes-toggle~ to a key instead of the +equivalent the themes provide. + +For a more elaborate design, it is better to inspect the source code of +~modus-themes-toggle~ and relevant functions. + +** Case-by-case face specs using the themes' palette +:properties: +:custom_id: h:1487c631-f4fe-490d-8d58-d72ffa3bd474 +:end: +#+findex: modus-themes-color +#+findex: modus-themes-color-alts +#+cindex: Extracting individual colors + +This section is about tweaking individual faces. If you plan to do +things at scale, consult the next section: [[#h:51ba3547-b8c8-40d6-ba5a-4586477fd4ae][Set multiple faces]]. + +We already covered in previous sections how to toggle between the themes +and how to configure options prior to loading. We also explained that +some of the functions made available to users will fire up a hook that +can be used to pass tweaks in the post-theme-load phase. + +Now assume you wish to change a single face, say, the ~cursor~. And you +would like to get the standard "blue" color value of the active Modus +theme, whether it is Modus Operandi or Modus Vivendi. To do that, you +can use the ~modus-themes-color~ function. It accepts a symbol that is +associated with a color in ~modus-themes-operandi-colors~ and +~modus-themes-vivendi-colors~. Like this: + +#+begin_src emacs-lisp +(modus-themes-color 'blue) +#+end_src + +The function always extracts the color value of the active Modus theme. + +#+begin_src emacs-lisp +(progn + (load-theme 'modus-operandi t) + (modus-themes-color 'blue)) ; "#0031a9" for `modus-operandi' + +(progn + (load-theme 'modus-vivendi t) + (modus-themes-color 'blue)) ; "#2fafff" for `modus-vivendi' +#+end_src + +Do {{{kbd(C-h v)}}} on the aforementioned variables to check all the available +symbols that can be passed to this function. Or simply invoke the +command ~modus-themes-list-colors~ to produce a buffer with a preview of +each entry in the palette. + +[[#h:f4d4b71b-2ca5-4c3d-b0b4-9bfd7aa7fb4d][Visualize the active Modus theme's palette]]. + +With that granted, let us expand the example to actually change the +~cursor~ face's background property. We employ the built-in function of +~set-face-attribute~: + +#+begin_src emacs-lisp +(set-face-attribute 'cursor nil :background (modus-themes-color 'blue)) +#+end_src + +If you evaluate this form, your cursor will become blue. But if you +change themes, such as with ~modus-themes-toggle~, your edits will be +lost, because the newly loaded theme will override the ~:background~ +attribute you had assigned to that face. + +For such changes to persist, we need to make them after loading the +theme. So we rely on ~modus-themes-after-load-theme-hook~, which gets +called from ~modus-themes-load-operandi~, ~modus-themes-load-vivendi~, as +well as the command ~modus-themes-toggle~. Here is a sample function that +tweaks two faces and then gets added to the hook: + +#+begin_src emacs-lisp +(defun my-modus-themes-custom-faces () + (set-face-attribute 'cursor nil :background (modus-themes-color 'blue)) + (set-face-attribute 'font-lock-type-face nil :foreground (modus-themes-color 'magenta-alt))) + +(add-hook 'modus-themes-after-load-theme-hook #'my-modus-themes-custom-faces) +#+end_src + +[[#h:86f6906b-f090-46cc-9816-1fe8aeb38776][A theme-agnostic hook for theme loading]]. + +Using this principle, it is possible to override the styles of faces +without having to find color values for each case. + +Another application is to control the precise weight for bold +constructs. This is particularly useful if your typeface has several +variants such as "heavy", "extrabold", "semibold". All you have to do +is edit the ~bold~ face. For example: + +#+begin_src emacs-lisp +(set-face-attribute 'bold nil :weight 'semibold) +#+end_src + +Remember to use the custom function and hook combo we demonstrated +above. Because the themes do not hard-wire a specific weight, this +simple form is enough to change the weight of all bold constructs +throughout the interface. + +Finally, there are cases where you want to tweak colors though wish to +apply different ones to each theme, say, a blue hue for Modus Operandi +and a shade of red for Modus Vivendi. To this end, we provide +~modus-themes-color-alts~ as a convenience function to save you from the +trouble of writing separate wrappers for each theme. It still returns a +single value by querying either of ~modus-themes-operandi-colors~ and +~modus-themes-vivendi-colors~, only here you pass the two keys you want, +first for ~modus-operandi~ then ~modus-vivendi~. + +Take the previous example with the ~cursor~ face: + +#+begin_src emacs-lisp +;; Blue for `modus-operandi' and red for `modus-vivendi' +(set-face-attribute 'cursor nil :background (modus-themes-color-alts 'blue 'red)) +#+end_src + +** Face specs at scale using the themes' palette +:properties: +:custom_id: h:51ba3547-b8c8-40d6-ba5a-4586477fd4ae +:end: +#+findex: modus-themes-with-colors +#+cindex: Extracting colors en masse + +The examples here are for large scale operations. For simple, one-off +tweaks, you may prefer the approach documented in the previous section +([[#h:1487c631-f4fe-490d-8d58-d72ffa3bd474][Case-by-case face specs using the themes' palette]]). + +The ~modus-themes-with-colors~ macro lets you retrieve multiple color +values by employing the backquote/backtick and comma notation. The +values are stored in the alists ~modus-themes-operandi-colors~ and +~modus-themes-vivendi-colors~, while the macro always queries that of the +active Modus theme (preview the current palette with the command +~modus-themes-list-colors~). + +[[#h:f4d4b71b-2ca5-4c3d-b0b4-9bfd7aa7fb4d][Visualize the active Modus theme's palette]]. + +Here is an abstract example that just returns a list of color values +while ~modus-operandi~ is enabled: + +#+begin_src emacs-lisp +(modus-themes-with-colors + (list fg-main + blue-faint + magenta + magenta-alt-other + cyan-alt-other + fg-special-cold + blue-alt + magenta-faint + cyan + fg-main + green-faint + red-alt-faint + blue-alt-faint + fg-special-warm + cyan-alt + blue)) +;; => +;; ("#000000" "#002f88" "#721045" "#5317ac" +;; "#005a5f" "#093060" "#2544bb" "#752f50" +;; "#00538b" "#000000" "#104410" "#702f00" +;; "#003f78" "#5d3026" "#30517f" "#0031a9") +#+end_src + +Getting a list of colors may have its applications, though what you are +most likely interested in is how to use those variables to configure +several faces at once. To do so we can rely on the built-in +~custom-set-faces~ function, which sets face specifications for the +special ~user~ theme. That "theme" gets applied on top of regular themes +like ~modus-operandi~ and ~modus-vivendi~. + +This is how it works: + +#+begin_src emacs-lisp +(modus-themes-with-colors + (custom-set-faces + `(cursor ((,class :background ,blue))) + `(mode-line ((,class :background ,yellow-nuanced-bg + :foreground ,yellow-nuanced-fg))) + `(mode-line-inactive ((,class :background ,blue-nuanced-bg + :foreground ,blue-nuanced-fg))))) +#+end_src + +The above snippet will immediately refashion the faces it names once it +is evaluated. However, if you switch between the Modus themes, say, +from ~modus-operandi~ to ~modus-vivendi~, the colors will not get updated to +match those of the new theme. To make things work across the themes, we +need to employ the same technique we discussed in the previous section, +namely, to pass our changes at the post-theme-load phase via a hook. + +The themes provide the ~modus-themes-after-load-theme-hook~, which gets +called from ~modus-themes-load-operandi~, ~modus-themes-load-vivendi~, as +well as the command ~modus-themes-toggle~. With this knowledge, you can +wrap the macro in a function and then assign that function to the hook. +Thus: + +#+begin_src emacs-lisp +(defun my-modus-themes-custom-faces () + (modus-themes-with-colors + (custom-set-faces + `(cursor ((,class :background ,blue))) + `(mode-line ((,class :background ,yellow-nuanced-bg + :foreground ,yellow-nuanced-fg))) + `(mode-line-inactive ((,class :background ,blue-nuanced-bg + :foreground ,blue-nuanced-fg)))))) + +(add-hook 'modus-themes-after-load-theme-hook #'my-modus-themes-custom-faces) +#+end_src + +[[#h:86f6906b-f090-46cc-9816-1fe8aeb38776][A theme-agnostic hook for theme loading]]. + +To discover the faces defined by all loaded libraries, you may do +{{{kbd(M-x list-faces-display)}}}. Be warned that when you ~:inherit~ a face +you are introducing an implicit dependency, so try to avoid doing so for +libraries other than the built-in {{{file(faces.el)}}} (or at least understand +that things may break if you inherit from a yet-to-be-loaded face). + +Also bear in mind that these examples are meant to work with the Modus +themes. If you are cycling between multiple themes you may encounter +unforeseen issues, such as the colors of the Modus themes being applied +to a non-Modus item. + +Finally, note that you can still use other functions where those make +sense. For example, the ~modus-themes-color-alts~ that was discussed in +the previous section. Adapt the above example like this: + +#+begin_src emacs-lisp +... +(modus-themes-with-colors + (custom-set-faces + `(cursor ((,class :background ,(modus-themes-color-alts 'blue 'green)))) + ...)) +#+end_src + +** Remap face with local value +:properties: +:custom_id: h:7a93cb6f-4eca-4d56-a85c-9dcd813d6b0f +:end: +#+cindex: Remapping faces + +There are cases where we need to change the buffer-local attributes of a +face. This might be because we have our own minor mode that re-uses a +face for a particular purpose, such as a line selection tool that +activates ~hl-line-mode~, but we wish to keep it distinct from other +buffers. This is where ~face-remap-add-relative~ can be applied and may +be combined with ~modus-themes-with-colors~ to deliver consistent results. + +[[#h:51ba3547-b8c8-40d6-ba5a-4586477fd4ae][Face specs at scale using the themes' palette]]. + +In this example we will write a simple interactive function that adjusts +the background color of the ~region~ face. This is the sample code: + +#+begin_src emacs-lisp +(defvar my-rainbow-region-colors + (modus-themes-with-colors + `((red . ,red-subtle-bg) + (green . ,green-subtle-bg) + (yellow . ,yellow-subtle-bg) + (blue . ,blue-subtle-bg) + (magenta . ,magenta-subtle-bg) + (cyan . ,cyan-subtle-bg))) + "Sample list of color values for `my-rainbow-region'.") + +(defun my-rainbow-region (color) + "Remap buffer-local attribute of `region' using COLOR." + (interactive + (list + (completing-read "Pick a color: " my-rainbow-region-colors))) + (face-remap-add-relative + 'region + `( :background ,(alist-get (intern color) my-rainbow-region-colors) + :foreground ,(face-attribute 'default :foreground)))) +#+end_src + +When ~my-rainbow-region~ is called interactively, it prompts for a color +to use. The list of candidates is drawn from the car of each +association in ~my-rainbow-region-colors~ (so "red", "green", etc.). + +To extend this principle, we may write wrapper functions that pass a +color directly. Those can be useful in tandem with hooks. Consider +this example: + +#+begin_src emacs-lisp +(defun my-rainbow-region-magenta () + (my-rainbow-region 'magenta)) + +(add-hook 'diff-mode-hook #'my-rainbow-region-magenta) +#+end_src + +Whenever we enter a ~diff-mode~ buffer, we now get a magenta-colored +region. + +Perhaps you may wish to generalize those findings in to a set of +functions that also accept an arbitrary face. We shall leave the +experimentation up to you. + +** Cycle through arbitrary colors +:properties: +:custom_id: h:77dc4a30-b96a-4849-85a8-fee3c2995305 +:end: +#+cindex: Cycle colors + +Users may opt to customize individual faces of the themes to accommodate +their particular needs. One such case is with the color intensity of +comments, specifically the foreground of ~font-lock-comment-face~. The +Modus themes set that to a readable value, in accordance with their +accessibility objective, though users may prefer to lower the overall +contrast on an on-demand basis. + +One way to achieve this is to design a command that cycles through three +distinct levels of intensity, though the following can be adapted to any +kind of cyclic behavior, such as to switch between red, green, and blue. + +In the following example, we employ the ~modus-themes-color~ function +which reads a symbol that represents an entry in the active theme's +color palette ([[#h:1487c631-f4fe-490d-8d58-d72ffa3bd474][Case-by-case face specs using the themes' palette]]). +Those are stored in ~my-modus-themes-comment-colors~. + +#+begin_src emacs-lisp +(defvar my-modus-themes-comment-colors + ;; We are abusing the palette here, as those colors have their own + ;; purpose in the palette, so please ignore the semantics of their + ;; names. + '((low . bg-region) + (medium . bg-tab-inactive-alt) + (high . fg-alt)) + "Alist of levels of intensity mapped to color palette entries. +The entries are found in `modus-themes-operandi-colors' or +`modus-themes-vivendi-colors'.") + +(defvar my-modus-themes--adjust-comment-color-state nil + "The cyclic state of `my-modus-themes-adjust-comment-color'. +For internal use.") + +(defun my-modus-themes--comment-foreground (degree state) + "Set `font-lock-comment-face' foreground. +Use `my-modus-themes-comment-colors' to extract the color value +for each level of intensity. + +This is complementary to `my-modus-themes-adjust-comment-color'." + (let ((palette-colors my-modus-themes-comment-colors)) + (set-face-foreground + 'font-lock-comment-face + (modus-themes-color (alist-get degree palette-colors))) + (setq my-modus-themes--adjust-comment-color-state state) + (message "Comments are set to %s contrast" degree))) + +(defun my-modus-themes-adjust-comment-color () + "Cycle through levels of intensity for comments. +The levels are determined by `my-modus-themes-comment-colors'." + (interactive) + (pcase my-modus-themes--adjust-comment-color-state + ('nil + (my-modus-themes--comment-foreground 'low 1)) + (1 + (my-modus-themes--comment-foreground 'medium 2)) + (_ + (my-modus-themes--comment-foreground 'high nil)))) +#+end_src + +With the above, {{{kbd(M-x my-modus-themes-adjust-comment-color)}}} will cycle +through the three levels of intensity that have been specified. + +Another approach is to not read from the active theme's color palette +and instead provide explicit color values, either in hexadecimal RGB +notation (like =#123456=) or as the names that are displayed in the output +of {{{kbd(M-x list-colors-display)}}}. In this case, the alist with the +colors will have to account for the active theme, so as to set the +appropriate colors. While this introduces a bit more complexity, it +ultimately offers greater flexibility on the choice of colors for such a +niche functionality (so there is no need to abuse the palette of the +active Modus theme): + +#+begin_src emacs-lisp +(defvar my-modus-themes-comment-colors + '((light . ((low . "gray75") + (medium . "gray50") + (high . "#505050"))) ; the default for `modus-operandi' + + (dark . ((low . "gray25") + (medium . "gray50") + (high . "#a8a8a8")))) ; the default for `modus-vivendi' + "Alist of levels of intensity mapped to color values. +For such colors, consult the command `list-colors-display'. Pass +the name of a color or its hex value.") + +(defvar my-modus-themes--adjust-comment-color-state nil + "The cyclic state of `my-modus-themes-adjust-comment-color'. +For internal use.") + +(defun my-modus-themes--comment-foreground (degree state) + "Set `font-lock-comment-face' foreground. +Use `my-modus-themes-comment-colors' to extract the color value +for each level of intensity. + +This is complementary to `my-modus-themes-adjust-comment-color'." + (let* ((colors my-modus-themes-comment-colors) + (levels (pcase (car custom-enabled-themes) + ('modus-operandi (alist-get 'light colors)) + ('modus-vivendi (alist-get 'dark colors))))) + (set-face-foreground + 'font-lock-comment-face + (alist-get degree levels)) + (setq my-modus-themes--adjust-comment-color-state state) + (message "Comments are set to %s contrast" degree))) + +(defun my-modus-themes-adjust-comment-color () + "Cycle through levels of intensity for comments. +The levels are determined by `my-modus-themes-comment-colors'." + (interactive) + (pcase my-modus-themes--adjust-comment-color-state + ('nil + (my-modus-themes--comment-foreground 'low 1)) + (1 + (my-modus-themes--comment-foreground 'medium 2)) + (_ + (my-modus-themes--comment-foreground 'high nil)))) +#+end_src + +The effect of the above configurations on ~font-lock-comment-face~ is +global. To make it buffer-local, one must tweak the code to employ the +function ~face-remap-add-relative~ ([[#h:7a93cb6f-4eca-4d56-a85c-9dcd813d6b0f][Remap face with local value]]). + +So this form in ~my-modus-themes--comment-foreground~: + +#+begin_src emacs-lisp +;; example 1 +(... + (set-face-foreground + 'font-lock-comment-face + (modus-themes-color (alist-get degree palette-colors))) + ...) + +;; example 2 +(... + (set-face-foreground + 'font-lock-comment-face + (alist-get degree levels)) + ...) +#+end_src + +Must become this: + +#+begin_src emacs-lisp +;; example 1 +(... + (face-remap-add-relative + 'font-lock-comment-face + `(:foreground ,(modus-themes-color (alist-get degree palette-colors)))) + ...) + +;; example 2 +(... + (face-remap-add-relative + 'font-lock-comment-face + `(:foreground ,(alist-get degree levels))) + ...) +#+end_src + +** Override colors +:properties: +:custom_id: h:307d95dd-8dbd-4ece-a543-10ae86f155a6 +:end: +#+vindex: modus-themes-operandi-color-overrides +#+vindex: modus-themes-vivendi-color-overrides +#+cindex: Change a theme's colors + +The themes provide a mechanism for overriding their color values. This +is controlled by the variables ~modus-themes-operandi-color-overrides~ and +~modus-themes-vivendi-color-overrides~, which are alists that should +mirror a subset of the associations in ~modus-themes-operandi-colors~ and +~modus-themes-vivendi-colors~ respectively. As with all customizations, +overriding must be done before loading the affected theme. + +[[#h:f4d4b71b-2ca5-4c3d-b0b4-9bfd7aa7fb4d][Visualize the active Modus theme's palette]]. + +Let us approach the present topic one step at a time. Here is a +simplified excerpt of the default palette for Modus Operandi with some +basic background values that apply to buffers and the mode line +(remember to inspect the actual value to find out all the associations +that can be overridden): + +#+begin_src emacs-lisp +(defconst modus-themes-operandi-colors + '((bg-main . "#ffffff") + (bg-dim . "#f8f8f8") + (bg-alt . "#f0f0f0") + (bg-active . "#d7d7d7") + (bg-inactive . "#efefef"))) +#+end_src + +As one can tell, we bind a key to a hexadecimal RGB color value. Now +say we wish to override those specific values and have our changes +propagate to all faces that use those keys. We could write something +like this, which adds a subtle ochre tint: + +#+begin_src emacs-lisp +(setq modus-themes-operandi-color-overrides + '((bg-main . "#fefcf4") + (bg-dim . "#faf6ef") + (bg-alt . "#f7efe5") + (bg-active . "#e8dfd1") + (bg-inactive . "#f6ece5"))) +#+end_src + +Once this is evaluated, any subsequent loading of ~modus-operandi~ will +use those values instead of the defaults. No further intervention is +required. + +To reset the changes, we apply this and reload the theme: + +#+begin_src emacs-lisp +(setq modus-themes-operandi-color-overrides nil) +#+end_src + +Users who wish to leverage such a mechanism can opt to implement it +on-demand by means of a global minor mode. The following snippet covers +both themes and expands to some more assosiations in the palette: + +#+begin_src emacs-lisp +(define-minor-mode my-modus-themes-tinted + "Tweak some Modus themes colors." + :init-value nil + :global t + (if my-modus-themes-tinted + (setq modus-themes-operandi-color-overrides + '((bg-main . "#fefcf4") + (bg-dim . "#faf6ef") + (bg-alt . "#f7efe5") + (bg-hl-line . "#f4f0e3") + (bg-active . "#e8dfd1") + (bg-inactive . "#f6ece5") + (bg-region . "#c6bab1") + (bg-header . "#ede3e0") + (bg-tab-active . "#fdf6eb") + (bg-tab-inactive . "#c8bab8")) + modus-themes-vivendi-color-overrides + '((bg-main . "#100b17") + (bg-dim . "#161129") + (bg-alt . "#181732") + (bg-hl-line . "#191628") + (bg-active . "#282e46") + (bg-inactive . "#1a1e39") + (bg-region . "#393a53") + (bg-header . "#202037") + (bg-tab-active . "#120f18") + (bg-tab-inactive . "#3a3a5a"))) + (setq modus-themes-operandi-color-overrides nil + modus-themes-vivendi-color-overrides nil))) +#+end_src + +A more neutral style for ~modus-themes-operandi-color-overrides~ can +look like this: + +#+begin_src emacs-lisp +'((bg-main . "#f7f7f7") + (bg-dim . "#f2f2f2") + (bg-alt . "#e8e8e8") + (bg-hl-line . "#eaeaef") + (bg-active . "#e0e0e0") + (bg-inactive . "#e6e6e6") + (bg-region . "#b5b5b5") + (bg-header . "#e4e4e4") + (bg-tab-active . "#f5f5f5") + (bg-tab-inactive . "#c0c0c0")) +#+end_src + +With those in place, one can use {{{kbd(M-x my-modus-themes-tinted)}}} +and then load the Modus theme of their choice. The new palette subset +will come into effect: subtle ochre tints (or shades of gray) for Modus +Operandi and night sky blue shades for Modus Vivendi. Switching between +the two themes, such as with {{{kbd(M-x modus-themes-toggle)}}} will +also use the overrides. + +Given that this is a user-level customization, one is free to implement +whatever color values they desire, even if the possible combinations +fall below the minimum 7:1 contrast ratio that governs the design of the +themes (the WCAG AAA legibility standard). Alternatively, this can also +be done programmatically ([[#h:4589acdc-2505-41fc-9f5e-699cfc45ab00][Override color saturation]]). + +The above are expanded into a fully fledged derivative elsewhere in this +document ([[#h:736c0ff5-8c9c-4565-82cf-989e57d07d4a][Override colors completely]]). + +For manual interventions it is advised to inspect the source code of +~modus-themes-operandi-colors~ and ~modus-themes-vivendi-colors~ for the +inline commentary: it explains what the intended use of each palette +subset is. + +Furthermore, users may benefit from the ~modus-themes-contrast~ function +that we provide: [[#h:02e25930-e71a-493d-828a-8907fc80f874][test color combinations]]. It measures the contrast +ratio between two color values, so it can help in overriding the palette +(or a subset thereof) without making the end result inaccessible. + +** Override color saturation +:properties: +:custom_id: h:4589acdc-2505-41fc-9f5e-699cfc45ab00 +:end: +#+cindex: Change a theme's color saturation + +In the previous section we documented how one can override color values +manually ([[#h:307d95dd-8dbd-4ece-a543-10ae86f155a6][Override colors]]). Here we use a programmatic approach which +leverages the built-in ~color-saturate-name~ function to adjust the +saturation of all color values used by the active Modus theme. Our goal +is to prepare a counterpart of the active theme's palette that holds +modified color values, adjusted for a percent change in saturation. A +positive number amplifies the effect, while a negative one will move +towards a grayscale spectrum. + +We start with a function that can be either called from Lisp or invoked +interactively. In the former scenario, we pass to it the rate of change +we want. While in the latter, a minibuffer prompt asks for a number to +apply the desired effect. In either case, we intend to assign anew the +value of ~modus-themes-operandi-color-overrides~ (light theme) and the +same for ~modus-themes-vivendi-color-overrides~ (dark theme). + +#+begin_src emacs-lisp +(defun my-modus-themes-saturate (percent) + "Saturate current Modus theme palette overrides by PERCENT." + (interactive + (list (read-number "Saturation by percent: "))) + (let* ((theme (modus-themes--current-theme)) + (palette (pcase theme + ('modus-operandi modus-themes-operandi-colors) + ('modus-vivendi modus-themes-vivendi-colors) + (_ (error "No Modus theme is active")))) + (overrides (pcase theme + ('modus-operandi 'modus-themes-operandi-color-overrides) + ('modus-vivendi 'modus-themes-vivendi-color-overrides) + (_ (error "No Modus theme is active"))))) + (let (name cons colors) + (dolist (cons palette) + (setq name (color-saturate-name (cdr cons) percent)) + (setq name (format "%s" name)) + (setq cons `(,(car cons) . ,name)) + (push cons colors)) + (set overrides colors)) + (pcase theme + ('modus-operandi (modus-themes-load-operandi)) + ('modus-vivendi (modus-themes-load-vivendi))))) + +;; sample Elisp calls (or call `my-modus-themes-saturate' interactively) +(my-modus-themes-saturate 50) +(my-modus-themes-saturate -75) +#+end_src + +Using the above has an immediate effect, as it reloads the active Modus +theme. + +The =my-modus-themes-saturate= function stores new color values in the +variables ~modus-themes-operandi-color-overrides~ and +~modus-themes-vivendi-color-overrides~, meaning that it undoes changes +implemented by the user on individual colors. To have both automatic +saturation adjustment across the board and retain per-case edits to the +palette, some tweaks to the above function are required. For example: + +#+begin_src emacs-lisp +(defvar my-modus-themes-vivendi-extra-color-overrides + '((fg-main . "#ead0c0") + (bg-main . "#050515")) + "My bespoke colors for `modus-vivendi'.") + +(defvar my-modus-themes-operandi-extra-color-overrides + '((fg-main . "#1a1a1a") + (bg-main . "#fefcf4")) + "My bespoke colors for `modus-operandi'.") + +(defun my-modus-themes-saturate (percent) + "Saturate current Modus theme palette overrides by PERCENT. +Preserve the color values stored in +`my-modus-themes-operandi-extra-color-overrides', +`my-modus-themes-vivendi-extra-color-overrides'." + (interactive + (list (read-number "Saturation by percent: "))) + (let* ((theme (modus-themes--current-theme)) + (palette (pcase theme + ('modus-operandi modus-themes-operandi-colors) + ('modus-vivendi modus-themes-vivendi-colors) + (_ (error "No Modus theme is active")))) + (overrides (pcase theme + ('modus-operandi 'modus-themes-operandi-color-overrides) + ('modus-vivendi 'modus-themes-vivendi-color-overrides) + (_ (error "No Modus theme is active")))) + (extra-overrides (pcase theme + ('modus-operandi my-modus-themes-operandi-extra-color-overrides) + ('modus-vivendi my-modus-themes-vivendi-extra-color-overrides) + (_ (error "No Modus theme is active"))))) + (let (name cons colors) + (dolist (cons palette) + (setq name (color-saturate-name (cdr cons) percent)) + (setq name (format "%s" name)) + (setq cons `(,(car cons) . ,name)) + (push cons colors)) + (set overrides (append extra-overrides colors))) + (pcase theme + ('modus-operandi (modus-themes-load-operandi)) + ('modus-vivendi (modus-themes-load-vivendi))))) +#+end_src + +To disable the effect, one must reset the aforementioned variables of +the themes to ~nil~. Or specify a command for it, such as by taking +inspiration from the ~modus-themes-toggle~ we already provide: + +#+begin_src emacs-lisp +(defun my-modus-themes-revert-overrides () + "Reset palette overrides and reload active Modus theme." + (interactive) + (setq modus-themes-operandi-color-overrides nil + modus-themes-vivendi-color-overrides nil) + (pcase (modus-themes--current-theme) + ('modus-operandi (modus-themes-load-operandi)) + ('modus-vivendi (modus-themes-load-vivendi)))) +#+end_src + +** Override colors through blending +:properties: +:custom_id: h:80c326bf-fe32-47b2-8c59-58022256fd6e +:end: +#+cindex: Change theme colors through blending + +This is yet another method of overriding color values. + +[[#h:307d95dd-8dbd-4ece-a543-10ae86f155a6][Override colors]]. + +[[#h:4589acdc-2505-41fc-9f5e-699cfc45ab00][Override color saturation]]. + +Building on ideas and concepts from the previous sections, this method +blends the entire palette at once with the chosen colors. The function +~my-modus-themes-interpolate~ blends two colors, taking a value from the +themes and mixing it with a user-defined color to arrive at a midpoint. +This scales to all background and foreground colors with the help of the +~my-modus-themes-tint-palette~ function. + +#+begin_src emacs-lisp +(setq my-modus-operandi-bg-blend "#fbf1c7" + my-modus-operandi-fg-blend "#3a6084" + my-modus-vivendi-bg-blend "#3a4042" + my-modus-vivendi-fg-blend "#d7b765") + +;; Adapted from the `kurecolor-interpolate' function of kurecolor.el +(defun my-modus-themes-interpolate (color1 color2) + (cl-destructuring-bind (r g b) + (mapcar #'(lambda (n) (* (/ n 2) 255.0)) + (cl-mapcar '+ (color-name-to-rgb color1) (color-name-to-rgb color2))) + (format "#%02X%02X%02X" r g b))) + +(defun my-modus-themes-tint-palette (palette bg-blend fg-blend) + "Modify Modus PALETTE programmatically and return a new palette. +Blend background colors with BG-BLEND and foreground colors with FG-BLEND." + (let (name cons colors) + (dolist (cons palette) + (let ((blend (if (string-match "bg" (symbol-name (car cons))) + bg-blend + fg-blend))) + (setq name (my-modus-themes-interpolate (cdr cons) blend))) + (setq name (format "%s" name)) + (setq cons `(,(car cons) . ,name)) + (push cons colors)) + colors)) + +(define-minor-mode modus-themes-tinted-mode + "Tweak some Modus themes colors." + :init-value nil + :global t + (if modus-themes-tinted-mode + (setq modus-themes-operandi-color-overrides + (my-modus-themes-tint-palette modus-themes-operandi-colors + my-modus-operandi-bg-blend + my-modus-operandi-fg-blend) + modus-themes-vivendi-color-overrides + (my-modus-themes-tint-palette modus-themes-vivendi-colors + my-modus-vivendi-bg-blend + my-modus-vivendi-fg-blend)) + (setq modus-themes-operandi-color-overrides nil + modus-themes-vivendi-color-overrides nil))) + +(modus-themes-tinted-mode 1) +#+end_src + +** Override colors completely +:PROPERTIES: +:CUSTOM_ID: h:736c0ff5-8c9c-4565-82cf-989e57d07d4a +:END: + +Based on the ideas we have already covered in these sections, the +following code block provides a complete, bespoke pair of color palettes +which override the defaults. They are implemented as a minor mode, as +explained before ([[#h:307d95dd-8dbd-4ece-a543-10ae86f155a6][Override colors]]). We call them "Summertime" for +convenience. + +#+begin_src emacs-lisp +;; Read the relevant blog post: +;; <https://protesilaos.com/codelog/2022-07-26-modus-themes-color-override-demo/> +(define-minor-mode modus-themes-summertime + "Refashion the Modus themes by overriding their colors. + +This is a complete technology demonstration to show how to +manually override the colors of the Modus themes. I have taken +good care of those overrides to make them work as a fully fledged +color scheme that is compatible with all user options of the +Modus themes. + +These overrides are usable by those who (i) like something more +fancy than the comparatively austere looks of the Modus themes, +and (ii) can cope with a lower contrast ratio. + +The overrides are set up as a minor mode, so that the user can +activate the effect on demand. Those who want to load the +overrides at all times can either add them directly to their +configuration or enable `modus-themes-summertime' BEFORE loading +either of the Modus themes (if the overrides are evaluated after +the theme, the theme must be reloaded). + +Remember that all changes to theme-related variables require a +reload of the theme to take effect (the Modus themes have lots of +user options, apart from those overrides). + +The `modus-themes-summertime' IS NOT an official extension to the +Modus themes and DOES NOT comply with its lofty accessibility +standards. It is included in the official manual as guidance for +those who want to make use of the color overriding facility we +provide." + :init-value nil + :global t + (if modus-themes-summertime + (setq modus-themes-operandi-color-overrides + '((bg-main . "#fff0f2") + (bg-dim . "#fbe6ef") + (bg-alt . "#f5dae6") + (bg-hl-line . "#fad8e3") + (bg-active . "#efcadf") + (bg-inactive . "#f3ddef") + (bg-active-accent . "#ffbbef") + (bg-region . "#dfc5d1") + (bg-region-accent . "#efbfef") + (bg-region-accent-subtle . "#ffd6ef") + (bg-header . "#edd3e0") + (bg-tab-active . "#ffeff2") + (bg-tab-inactive . "#f8d3ef") + (bg-tab-inactive-accent . "#ffd9f5") + (bg-tab-inactive-alt . "#e5c0d5") + (bg-tab-inactive-alt-accent . "#f3cce0") + (fg-main . "#543f78") + (fg-dim . "#5f476f") + (fg-alt . "#7f6f99") + (fg-unfocused . "#8f6f9f") + (fg-active . "#563068") + (fg-inactive . "#8a5698") + (fg-docstring . "#5f5fa7") + (fg-comment-yellow . "#a9534f") + (fg-escape-char-construct . "#8b207f") + (fg-escape-char-backslash . "#a06d00") + (bg-special-cold . "#d3e0f4") + (bg-special-faint-cold . "#e0efff") + (bg-special-mild . "#c4ede0") + (bg-special-faint-mild . "#e0f0ea") + (bg-special-warm . "#efd0c4") + (bg-special-faint-warm . "#ffe4da") + (bg-special-calm . "#f0d3ea") + (bg-special-faint-calm . "#fadff9") + (fg-special-cold . "#405fb8") + (fg-special-mild . "#407f74") + (fg-special-warm . "#9d6f4f") + (fg-special-calm . "#af509f") + (bg-completion . "#ffc5e5") + (bg-completion-subtle . "#f7cfef") + (red . "#ed2f44") + (red-alt . "#e0403d") + (red-alt-other . "#e04059") + (red-faint . "#ed4f44") + (red-alt-faint . "#e0603d") + (red-alt-other-faint . "#e06059") + (green . "#217a3c") + (green-alt . "#417a1c") + (green-alt-other . "#006f3c") + (green-faint . "#318a4c") + (green-alt-faint . "#518a2c") + (green-alt-other-faint . "#20885c") + (yellow . "#b06202") + (yellow-alt . "#a95642") + (yellow-alt-other . "#a06f42") + (yellow-faint . "#b07232") + (yellow-alt-faint . "#a96642") + (yellow-alt-other-faint . "#a08042") + (blue . "#275ccf") + (blue-alt . "#475cc0") + (blue-alt-other . "#3340ef") + (blue-faint . "#476ce0") + (blue-alt-faint . "#575ccf") + (blue-alt-other-faint . "#3f60d7") + (magenta . "#bf317f") + (magenta-alt . "#d033c0") + (magenta-alt-other . "#844fe4") + (magenta-faint . "#bf517f") + (magenta-alt-faint . "#d053c0") + (magenta-alt-other-faint . "#846fe4") + (cyan . "#007a9f") + (cyan-alt . "#3f709f") + (cyan-alt-other . "#107f7f") + (cyan-faint . "#108aaf") + (cyan-alt-faint . "#3f80af") + (cyan-alt-other-faint . "#3088af") + (red-active . "#cd2f44") + (green-active . "#116a6c") + (yellow-active . "#993602") + (blue-active . "#475ccf") + (magenta-active . "#7f2ccf") + (cyan-active . "#007a8f") + (red-nuanced-bg . "#ffdbd0") + (red-nuanced-fg . "#ed6f74") + (green-nuanced-bg . "#dcf0dd") + (green-nuanced-fg . "#3f9a4c") + (yellow-nuanced-bg . "#fff3aa") + (yellow-nuanced-fg . "#b47232") + (blue-nuanced-bg . "#e3e3ff") + (blue-nuanced-fg . "#201f6f") + (magenta-nuanced-bg . "#fdd0ff") + (magenta-nuanced-fg . "#c0527f") + (cyan-nuanced-bg . "#dbefff") + (cyan-nuanced-fg . "#0f3f60") + (bg-diff-heading . "#b7cfe0") + (fg-diff-heading . "#041645") + (bg-diff-added . "#d6f0d6") + (fg-diff-added . "#004520") + (bg-diff-changed . "#fcefcf") + (fg-diff-changed . "#524200") + (bg-diff-removed . "#ffe0ef") + (fg-diff-removed . "#891626") + (bg-diff-refine-added . "#84cfa4") + (fg-diff-refine-added . "#002a00") + (bg-diff-refine-changed . "#cccf8f") + (fg-diff-refine-changed . "#302010") + (bg-diff-refine-removed . "#da92b0") + (fg-diff-refine-removed . "#500010") + (bg-diff-focus-added . "#a6e5c6") + (fg-diff-focus-added . "#002c00") + (bg-diff-focus-changed . "#ecdfbf") + (fg-diff-focus-changed . "#392900") + (bg-diff-focus-removed . "#efbbcf") + (fg-diff-focus-removed . "#5a0010")) + modus-themes-vivendi-color-overrides + '((bg-main . "#25152a") + (bg-dim . "#2a1930") + (bg-alt . "#382443") + (bg-hl-line . "#332650") + (bg-active . "#463358") + (bg-inactive . "#2d1f3a") + (bg-active-accent . "#50308f") + (bg-region . "#5d4a67") + (bg-region-accent . "#60509f") + (bg-region-accent-subtle . "#3f285f") + (bg-header . "#3a2543") + (bg-tab-active . "#26162f") + (bg-tab-inactive . "#362647") + (bg-tab-inactive-accent . "#36265a") + (bg-tab-inactive-alt . "#3e2f5a") + (bg-tab-inactive-alt-accent . "#3e2f6f") + (fg-main . "#debfe0") + (fg-dim . "#d0b0da") + (fg-alt . "#ae85af") + (fg-unfocused . "#8e7f9f") + (fg-active . "#cfbfef") + (fg-inactive . "#b0a0c0") + (fg-docstring . "#c8d9f7") + (fg-comment-yellow . "#cf9a70") + (fg-escape-char-construct . "#ff75aa") + (fg-escape-char-backslash . "#dbab40") + (bg-special-cold . "#2a3f58") + (bg-special-faint-cold . "#1e283f") + (bg-special-mild . "#0f3f31") + (bg-special-faint-mild . "#0f281f") + (bg-special-warm . "#44331f") + (bg-special-faint-warm . "#372213") + (bg-special-calm . "#4a314f") + (bg-special-faint-calm . "#3a223f") + (fg-special-cold . "#c0b0ff") + (fg-special-mild . "#bfe0cf") + (fg-special-warm . "#edc0a6") + (fg-special-calm . "#ff9fdf") + (bg-completion . "#502d70") + (bg-completion-subtle . "#451d65") + (red . "#ff5f6f") + (red-alt . "#ff8f6d") + (red-alt-other . "#ff6f9d") + (red-faint . "#ffa0a0") + (red-alt-faint . "#f5aa80") + (red-alt-other-faint . "#ff9fbf") + (green . "#51ca5c") + (green-alt . "#71ca3c") + (green-alt-other . "#51ca9c") + (green-faint . "#78bf78") + (green-alt-faint . "#99b56f") + (green-alt-other-faint . "#88bf99") + (yellow . "#f0b262") + (yellow-alt . "#f0e242") + (yellow-alt-other . "#d0a272") + (yellow-faint . "#d2b580") + (yellow-alt-faint . "#cabf77") + (yellow-alt-other-faint . "#d0ba95") + (blue . "#778cff") + (blue-alt . "#8f90ff") + (blue-alt-other . "#8380ff") + (blue-faint . "#82b0ec") + (blue-alt-faint . "#a0acef") + (blue-alt-other-faint . "#80b2f0") + (magenta . "#ff70cf") + (magenta-alt . "#ff77f0") + (magenta-alt-other . "#ca7fff") + (magenta-faint . "#e0b2d6") + (magenta-alt-faint . "#ef9fe4") + (magenta-alt-other-faint . "#cfa6ff") + (cyan . "#30cacf") + (cyan-alt . "#60caff") + (cyan-alt-other . "#40b79f") + (cyan-faint . "#90c4ed") + (cyan-alt-faint . "#a0bfdf") + (cyan-alt-other-faint . "#a4d0bb") + (red-active . "#ff6059") + (green-active . "#64dc64") + (yellow-active . "#ffac80") + (blue-active . "#4fafff") + (magenta-active . "#cf88ff") + (cyan-active . "#50d3d0") + (red-nuanced-bg . "#440a1f") + (red-nuanced-fg . "#ffcccc") + (green-nuanced-bg . "#002904") + (green-nuanced-fg . "#b8e2b8") + (yellow-nuanced-bg . "#422000") + (yellow-nuanced-fg . "#dfdfb0") + (blue-nuanced-bg . "#1f1f5f") + (blue-nuanced-fg . "#bfd9ff") + (magenta-nuanced-bg . "#431641") + (magenta-nuanced-fg . "#e5cfef") + (cyan-nuanced-bg . "#042f49") + (cyan-nuanced-fg . "#a8e5e5") + (bg-diff-heading . "#304466") + (fg-diff-heading . "#dae7ff") + (bg-diff-added . "#0a383a") + (fg-diff-added . "#94ba94") + (bg-diff-changed . "#2a2000") + (fg-diff-changed . "#b0ba9f") + (bg-diff-removed . "#50163f") + (fg-diff-removed . "#c6adaa") + (bg-diff-refine-added . "#006a46") + (fg-diff-refine-added . "#e0f6e0") + (bg-diff-refine-changed . "#585800") + (fg-diff-refine-changed . "#ffffcc") + (bg-diff-refine-removed . "#952838") + (fg-diff-refine-removed . "#ffd9eb") + (bg-diff-focus-added . "#1d4c3f") + (fg-diff-focus-added . "#b4dfb4") + (bg-diff-focus-changed . "#424200") + (fg-diff-focus-changed . "#d0daaf") + (bg-diff-focus-removed . "#6f0f39") + (fg-diff-focus-removed . "#eebdba"))) + (setq modus-themes-operandi-color-overrides nil + modus-themes-vivendi-color-overrides nil))) +#+end_src + +** Font configurations for Org and others +:properties: +:custom_id: h:defcf4fc-8fa8-4c29-b12e-7119582cc929 +:end: +#+cindex: Font configurations + +The themes are designed to optionally cope well with mixed font +configurations. This mostly concerns ~org-mode~ and ~markdown-mode~, though +expect to find it elsewhere like in ~Info-mode~. + +[[#h:115e6c23-ee35-4a16-8cef-e2fcbb08e28b][Option for font mixing]]. + +In practice it means that the user can safely opt for a more +prose-friendly proportionately spaced typeface as their default, while +spacing-sensitive elements like tables and inline code always use a +monospaced font, by inheriting from the ~fixed-pitch~ face. + +Users can try the built-in {{{kbd(M-x variable-pitch-mode)}}} to see the +effect in action. + +To make everything use your desired font families, you need to configure +the ~variable-pitch~ (proportional spacing) and ~fixed-pitch~ (monospaced) +faces respectively. It may also be convenient to set your main typeface +by configuring the ~default~ face the same way. + +[ The =fontaine= package on GNU ELPA (by the author of the modus-themes) + is designed to handle this case. ] + +Put something like this in your initialization file (also consider +reading the doc string of ~set-face-attribute~): + +#+begin_src emacs-lisp +;; Main typeface +(set-face-attribute 'default nil :family "DejaVu Sans Mono" :height 110) + +;; Proportionately spaced typeface +(set-face-attribute 'variable-pitch nil :family "DejaVu Serif" :height 1.0) + +;; Monospaced typeface +(set-face-attribute 'fixed-pitch nil :family "DejaVu Sans Mono" :height 1.5) +#+end_src + +Or employ the ~face-attribute~ function to read an existing value, such as +if you want to make ~fixed-pitch~ use the font family of the ~default~ face: + +#+begin_src emacs-lisp +(set-face-attribute 'fixed-pitch nil :family (face-attribute 'default :family)) +#+end_src + +The next section shows how to make those work in a more elaborate setup +that is robust to changes between the Modus themes. + +[[#h:2793a224-2109-4f61-a106-721c57c01375][Configure bold and italic faces]]. + +Note the differences in the ~:height~ property. The ~default~ face must +specify an absolute value, which is the point size × 10. So if you want +to use a font at point size =11=, you set the height to =110=.[fn:: ~:height~ +values do not need to be rounded to multiples of ten: the likes of =115= +are perfectly valid—some typefaces will change to account for those +finer increments.] Whereas every other face must either not specify a +height or have a value that is relative to the default, represented as a +floating point. If you use an integer, then that means an absolute +height. This is of paramount importance: it ensures that all fonts can +scale gracefully when using something like the ~text-scale-adjust~ command +which only operates on the base font size (i.e. the ~default~ face's +absolute height). + +[[#h:e6c5451f-6763-4be7-8fdb-b4706a422a4c][Note for EWW and Elfeed fonts]]. + +** Configure bold and italic faces +:properties: +:custom_id: h:2793a224-2109-4f61-a106-721c57c01375 +:end: +#+cindex: Bold and italic fonts + +The Modus themes do not hardcode a ~:weight~ or ~:slant~ attribute in the +thousands of faces they cover. Instead, they configure the generic +faces called ~bold~ and ~italic~ to use the appropriate styles and then +instruct all relevant faces that require emphasis to inherit from them. + +This practically means that users can change the particularities of what +it means for a construct to be bold/italic, by tweaking the ~bold~ and +~italic~ faces. Cases where that can be useful include: + ++ The default typeface does not have a variant with slanted glyphs + (e.g. Fira Mono/Code as of this writing on 2021-07-07), so the user + wants to add another family for the italics, such as Hack. + ++ The typeface of choice provides a multitude of weights and the user + prefers the light one by default. To prevent the bold weight from + being too heavy compared to the light one, they opt to make ~bold~ use a + semibold weight. + ++ The typeface distinguishes between oblique and italic forms by + providing different font variants (the former are just slanted + versions of the upright forms, while the latter have distinguishing + features as well). In this case, the user wants to specify the font + that applies to the ~italic~ face. + +To achieve those effects, one must first be sure that the fonts they use +have support for those features. It then is a matter of following the +instructions for all typeface tweaks. + +[[#h:defcf4fc-8fa8-4c29-b12e-7119582cc929][Font configurations for Org and others]]. + +In this example, we set the default font family to Fira Code, while we +choose to render italics in the Hack typeface (obviously you need to +pick fonts that work well together): + +#+begin_src emacs-lisp +(set-face-attribute 'default nil :family "Fira Code" :height 110) +(set-face-attribute 'italic nil :family "Hack") +#+end_src + +And here we play with different weights, using Source Code Pro: + +#+begin_src emacs-lisp +(set-face-attribute 'default nil :family "Source Code Pro" :height 110 :weight 'light) +(set-face-attribute 'bold nil :weight 'semibold) +#+end_src + +To reset the font family, one can use this: + +#+begin_src emacs-lisp +(set-face-attribute 'italic nil :family 'unspecified) +#+end_src + +To ensure that the effects persist after switching between the Modus +themes (such as with {{{kbd(M-x modus-themes-toggle)}}}), the user needs to +write their configurations to a function and pass it to the +~modus-themes-after-load-theme-hook~. This is necessary because themes +set the styles of faces upon activation, overriding prior values where +conflicts occur between the previous and the current states (otherwise +changing themes would not be possible). + +[[#h:86f6906b-f090-46cc-9816-1fe8aeb38776][A theme-agnostic hook for theme loading]]. + +This is a minimal setup to preserve font configurations across theme +load phases. For a more permanent setup, it is better to rely on the +~custom-set-faces~ function: ~set-face-attribute~ works just fine, though it +probably is better suited for quick previews or for smaller scale +operations (~custom-set-faces~ follows the format used in the source code +of the themes, which can make it easier to redefine faces in bulk). + +#+begin_src emacs-lisp +;; our generic function +(defun my-modes-themes-bold-italic-faces () + (set-face-attribute 'default nil :family "Source Code Pro" :height 110) + (set-face-attribute 'bold nil :weight 'semibold)) + +;; or use this if you configure a lot of face and attributes and +;; especially if you plan to use `modus-themes-with-colors', as shown +;; elsewhere in the manual +(defun my-modes-themes-bold-italic-faces () + (custom-set-faces + '(default ((t :family "Source Code Pro" :height 110))) + '(bold ((t :weight semibold))))) + +;; and here is the hook +(add-hook 'modus-themes-after-load-theme-hook #'my-modes-themes-bold-italic-faces) +#+end_src + +[[#h:51ba3547-b8c8-40d6-ba5a-4586477fd4ae][Face specs at scale using the themes' palette]]. + +** Custom Org todo keyword and priority faces +:properties: +:custom_id: h:89f0678d-c5c3-4a57-a526-668b2bb2d7ad +:end: +#+cindex: Org custom todo faces + +Users of ~org-mode~ have the option to configure various keywords and +priority cookies to better match their workflow. User options are +~org-todo-keyword-faces~ and ~org-priority-faces~. + +As those are meant to be custom faces, it is futile to have the themes +guess what each user wants to use, which keywords to target, and so on. +Instead, we can provide guidelines on how to customize things to one's +liking with the intent of retaining the overall aesthetic of the themes. + +Please bear in mind that the end result of those is not controlled by +the active Modus theme but by how Org maps faces to its constructs. +Editing those while ~org-mode~ is active requires re-initialization of the +mode with {{{kbd(M-x org-mode-restart)}}} for changes to take effect. + +Let us assume you wish to visually differentiate your keywords. You +have something like this: + +#+begin_src emacs-lisp +(setq org-todo-keywords + '((sequence "TODO(t)" "|" "DONE(D)" "CANCEL(C)") + (sequence "MEET(m)" "|" "MET(M)") + (sequence "STUDY(s)" "|" "STUDIED(S)") + (sequence "WRITE(w)" "|" "WROTE(W)"))) +#+end_src + +You could then use a variant of the following to inherit from a face +that uses the styles you want and also to preserve the properties +applied by the ~org-todo~ face (in case there is a difference between the +two): + +#+begin_src emacs-lisp +(setq org-todo-keyword-faces + '(("MEET" . '(bold org-todo)) + ("STUDY" . '(warning org-todo)) + ("WRITE" . '(shadow org-todo)))) +#+end_src + +This will refashion the keywords you specify, while letting the other +items in ~org-todo-keywords~ use their original styles (which are defined +in the ~org-todo~ and ~org-done~ faces). + +If you want back the defaults, try specifying just the ~org-todo~ face: + +#+begin_src emacs-lisp +(setq org-todo-keyword-faces + '(("MEET" . org-todo) + ("STUDY" . org-todo) + ("WRITE" . org-todo))) +#+end_src + +When you inherit from multiple faces, you need to quote the list as +shown further above. The order is significant: the first entry is +applied on top of the second, overriding any properties that are +explicitly set for both of them: any property that is not specified is +not overridden, so, for example, if ~org-todo~ has a background and a +foreground, while ~font-lock-type-face~ only has a foreground, the merged +face will include the background of the former and the foreground of the +latter. If you do not want to blend multiple faces, you do not need a +quoted list. A pattern of =keyword . face= will suffice. + +Both approaches can be used simultaneously, as illustrated in this +configuration of the priority cookies: + +#+begin_src emacs-lisp +(setq org-priority-faces + '((?A . '(bold org-priority)) + (?B . org-priority) + (?C . '(shadow org-priority)))) +#+end_src + +To find all the faces that are loaded in your current Emacs session, use +{{{kbd(M-x list-faces-display)}}}. Try {{{kbd(M-x describe-variable)}}} as well and +then specify the name of each of those Org variables demonstrated above. +Their documentation strings will offer you further guidance. + +Recall that the themes let you retrieve a color from their palette. Do +it if you plan to control face attributes. + +[[#h:1487c631-f4fe-490d-8d58-d72ffa3bd474][Custom face specs using the themes' palette]]. + +[[#h:02e25930-e71a-493d-828a-8907fc80f874][Check color combinations]]. + +** Custom Org emphasis faces +:properties: +:custom_id: h:26026302-47f4-4471-9004-9665470e7029 +:end: +#+cindex: Org custom emphasis faces + +Org provides the user option ~org-emphasis-alist~ which associates a +character with a face, list of faces, or face attributes. The default +specification of that variable looks like this: + +#+begin_src emacs-lisp +(setq org-emphasis-alist + '(("*" bold) + ("/" italic) + ("_" underline) + ("=" org-verbatim verbatim) + ("~" org-code verbatim) + ("+" (:strike-through t)))) +#+end_src + +With the exception of ~org-verbatim~ and ~org-code~ faces, everything else +uses the corresponding type of emphasis: a bold typographic weight, or +italicised, underlined, and struck through text. + +The best way for users to add some extra attributes, such as a +foreground color, is to define their own faces and assign them to the +given emphasis marker/character. + +This is a custom face that extends the standard ~bold~ face with a red +foreground value (so it colorises the text in addition to the bold +weight): + +#+begin_src emacs-lisp +(defface my-org-emphasis-bold + '((default :inherit bold) + (((class color) (min-colors 88) (background light)) + :foreground "#a60000") + (((class color) (min-colors 88) (background dark)) + :foreground "#ff8059")) + "My bold emphasis for Org.") +#+end_src + +This face definition reads as follows: + ++ Always inherit the ~bold~ face ([[#h:2793a224-2109-4f61-a106-721c57c01375][Configure bold and italic faces]]). ++ For versions of Emacs that support at least 88 colors (graphical + Emacs, for example) and use a light background, apply the =#a60000= + value. ++ For the same kind of Emacs that has a dark background use the =#ff8059= + color instead. + +Same principle for how to extend ~italic~ and ~underline~ with, for example, +green and yellow hues, respectively: + +#+begin_src emacs-lisp +(defface my-org-emphasis-italic + '((default :inherit italic) + (((class color) (min-colors 88) (background light)) + :foreground "#005e00") + (((class color) (min-colors 88) (background dark)) + :foreground "#44bc44")) + "My italic emphasis for Org.") + +(defface my-org-emphasis-underline + '((default :inherit underline) + (((class color) (min-colors 88) (background light)) + :foreground "#813e00") + (((class color) (min-colors 88) (background dark)) + :foreground "#d0bc00")) + "My underline emphasis for Org.") +#+end_src + +In the case of a strike-through effect, we have no generic face to +inherit from, so we can write it as follows to also change the +foreground to a more subtle gray: + +#+begin_src emacs-lisp +(defface my-org-emphasis-strike-through + '((default :strike-through t) + (((class color) (min-colors 88) (background light)) + :foreground "#505050") + (((class color) (min-colors 88) (background dark)) + :foreground "#a8a8a8")) + "My strike-through emphasis for Org.") +#+end_src + +Or we can just change the color of the line that strikes through the +text to, for example, a shade of red: + +#+begin_src emacs-lisp +(defface my-org-emphasis-strike-through + '((((class color) (min-colors 88) (background light)) + :strike-through "#972500") + (((class color) (min-colors 88) (background dark)) + :strike-through "#ef8b50")) + "My strike-through emphasis for Org.") +#+end_src + +It is possible to combine those effects: + +#+begin_src emacs-lisp +(defface my-org-emphasis-strike-through + '((((class color) (min-colors 88) (background light)) + :strike-through "#972500" :foreground "#505050") + (((class color) (min-colors 88) (background dark)) + :strike-through "#ef8b50" :foreground "#a8a8a8")) + "My strike-through emphasis for Org.") +#+end_src + +One may inspect the variables ~modus-themes-operandi-colors~ and +~modus-themes-vivendi-colors~ for possible color values. Or call the +command ~modus-themes-list-colors~ to show a buffer that previews each +entry in the palette. + +[[#h:f4d4b71b-2ca5-4c3d-b0b4-9bfd7aa7fb4d][Visualize the active Modus theme's palette]]. + +Once we have defined the faces we need, we must update the +~org-emphasis-alist~. Given that ~org-verbatim~ and ~org-code~ are already +styled by the themes, it probably is best not to edit them: + +#+begin_src emacs-lisp +(setq org-emphasis-alist + '(("*" my-org-emphasis-bold) + ("/" my-org-emphasis-italic) + ("_" my-org-emphasis-underline) + ("=" org-verbatim verbatim) + ("~" org-code verbatim) + ("+" my-org-emphasis-strike-through))) +#+end_src + +That's it! For changes to take effect in already visited Org files, +invoke {{{kbd(M-x org-mode-restart)}}}. + +** Update Org block delimiter fontification +:properties: +:custom_id: h:f44cc6e3-b0f1-4a5e-8a90-9e48fa557b50 +:end: + +As noted in the section about ~modus-themes-org-blocks~, Org contains a +variable that determines whether the block's begin and end lines are +extended to the edge of the window ([[#h:b7e328c0-3034-4db7-9cdf-d5ba12081ca2][Option for org-mode block styles]]). +The variable is ~org-fontify-whole-block-delimiter-line~. + +Users who change the style of Org blocks from time to time may prefer to +automatically update delimiter line fontification, such as with the +following setup: + +#+begin_src emacs-lisp +(defun my-modus-themes-org-fontify-block-delimiter-lines () + "Match `org-fontify-whole-block-delimiter-line' to theme style. +Run this function at the post theme load phase, such as with the +`modus-themes-after-load-theme-hook'." + (if (eq modus-themes-org-blocks 'gray-background) + (setq org-fontify-whole-block-delimiter-line t) + (setq org-fontify-whole-block-delimiter-line nil))) + +(add-hook 'modus-themes-after-load-theme-hook + #'my-modus-themes-org-fontify-block-delimiter-lines) +#+end_src + +Then {{{kbd(M-x org-mode-restart)}}} for changes to take effect, though manual +intervention can be circumvented by tweaking the function thus: + +#+begin_src emacs-lisp +(defun my-modus-themes-org-fontify-block-delimiter-lines () + "Match `org-fontify-whole-block-delimiter-line' to theme style. +Run this function at the post theme load phase, such as with the +`modus-themes-after-load-theme-hook'." + (if (eq modus-themes-org-blocks 'gray-background) + (setq org-fontify-whole-block-delimiter-line t) + (setq org-fontify-whole-block-delimiter-line nil)) + (when (derived-mode-p 'org-mode) + (font-lock-flush))) +#+end_src + +** Measure color contrast +:properties: +:custom_id: h:02e25930-e71a-493d-828a-8907fc80f874 +:end: +#+findex: modus-themes-contrast +#+findex: modus-themes-wcag-formula +#+cindex: Color contrast + +The themes provide the functions ~modus-themes-wcag-formula~ and +~modus-themes-contrast~. The former is a direct implementation of the +WCAG formula: <https://www.w3.org/TR/WCAG20-TECHS/G18.html>. It +calculates the relative luminance of a color value that is expressed in +hexadecimal RGB notation. While the latter function is just a +convenient wrapper for comparing the relative luminance between two +colors. + +In practice, one needs to work only with ~modus-themes-contrast~. It +accepts two color values and returns their contrast ratio. Values range +from 1 to 21 (lowest to highest). The themes are designed to always be +equal or higher than 7 for each combination of background and foreground +that they use (this is the WCAG AAA standard---the most demanding of its +kind). + +A couple of examples (rounded numbers): + +#+begin_src emacs-lisp +;; Pure white with pure green +(modus-themes-contrast "#ffffff" "#00ff00") +;; => 1.37 +;; That is an outright inaccessible combo + +;; Pure black with pure green +(modus-themes-contrast "#000000" "#00ff00") +;; => 15.3 +;; That is a highly accessible combo +#+end_src + +It does not matter which color value comes first. The ratio is always +the same. + +If one does not wish to read all the decimal points, it is possible to +try something like this: + +#+begin_src emacs-lisp +(format "%0.2f" (modus-themes-contrast "#000000" "#00ff00")) +#+end_src + +While it is fine to perform such calculations on a case-by-case basis, +it is preferable to implement formulas and tables for more demanding +tasks. Such instruments are provided by ~org-mode~ or ~orgtbl-mode~, both +of which are built into Emacs. Below is such a table that derives the +contrast ratio of all colors in the first column (pure red, green, blue) +relative to the color specified in the first row of the second column +(pure white) and rounds the results: + +#+begin_example +| | #ffffff | +|---------+---------| +| #ff0000 | 4.00 | +| #00ff00 | 1.37 | +| #0000ff | 8.59 | +#+tblfm: $2='(modus-themes-contrast $1 @1$2);%0.2f +#+end_example + +To measure color contrast one needs to start from a known value. This +typically is the background. The Modus themes define an expanded +palette in large part because certain colors are only meant to be used +in combination with some others. Consult the source code for the +minutia and relevant commentary. + +Such knowledge may prove valuable while attempting to override some of +the themes' colors: [[#h:307d95dd-8dbd-4ece-a543-10ae86f155a6][Override colors]]. + +** Load theme depending on time of day +:properties: +:custom_id: h:1d1ef4b4-8600-4a09-993c-6de3af0ddd26 +:end: + +While we do provide ~modus-themes-toggle~ to manually switch between the +themes, users may also set up their system to perform such a task +automatically at sunrise and sunset. + +This can be accomplished by specifying the coordinates of one's location +using the built-in {{{file(solar.el)}}} and then configuring the =circadian= +package: + +#+begin_src emacs-lisp +(use-package solar ; built-in + :config + (setq calendar-latitude 35.17 + calendar-longitude 33.36)) + +(use-package circadian ; you need to install this + :ensure + :after solar + (setq circadian-themes '((:sunrise . modus-operandi) + (:sunset . modus-vivendi))) + (circadian-setup)) +#+end_src + +** Backdrop for pdf-tools +:properties: +:custom_id: h:ff69dfe1-29c0-447a-915c-b5ff7c5509cd +:end: +#+cindex: Remapping pdf-tools backdrop + +Most PDF files use a white background for their page, making it +impossible to discern the file's boundaries in the buffer while using +the Modus Operandi theme. To introduce a distinction between the +buffer's backdrop and the PDF page's background, the former must be +rendered as some shade of gray. Ideally, ~pdf-tools~ would provide a face +that the themes could support directly, though this does not seem to be +the case for the time being. We must thus employ the face remapping +technique that is documented elsewhere in this document to change the +buffer-local value of the ~default~ face. + +[[#h:7a93cb6f-4eca-4d56-a85c-9dcd813d6b0f][Remap face with local value]]. + +To remap the buffer's backdrop, we start with a function like this one: + +#+begin_src emacs-lisp +(defun my-pdf-tools-backdrop () + (face-remap-add-relative + 'default + `(:background ,(modus-themes-color 'bg-alt)))) + +(add-hook 'pdf-tools-enabled-hook #'my-pdf-tools-backdrop) +#+end_src + +The idea is to assign that function to a hook that gets called when +~pdf-tools~ renders the document: ~pdf-tools-enabled-hook~. This is enough +when you only use one theme. However it has the downside of setting the +background color value only at render time. In other words, the face +remapping function does not get evaluated anew whenever the theme +changes, such as upon invoking {{{kbd(M-x modus-themes-toggle)}}}. + +To have our face remapping adapt gracefully while switching between the +Modus themes, we need to also account for the current theme and control +the activation of ~pdf-view-midnight-minor-mode~. To which end we arrive +at something like the following, which builds on the above example: + +#+begin_src emacs-lisp +(defun my-pdf-tools-backdrop () + (face-remap-add-relative + 'default + `(:background ,(modus-themes-color 'bg-alt)))) + +(defun my-pdf-tools-midnight-mode-toggle () + (when (derived-mode-p 'pdf-view-mode) + (if (eq (car custom-enabled-themes) 'modus-vivendi) + (pdf-view-midnight-minor-mode 1) + (pdf-view-midnight-minor-mode -1)) + (my-pdf-tools-backdrop))) + +(defun my-pdf-tools-themes-toggle () + (mapc + (lambda (buf) + (with-current-buffer buf + (my-pdf-tools-midnight-mode-toggle))) + (buffer-list))) + +(add-hook 'pdf-tools-enabled-hook #'my-pdf-tools-midnight-mode-toggle) +(add-hook 'modus-themes-after-load-theme-hook #'my-pdf-tools-themes-toggle) +#+end_src + +With those in place, PDFs have a distinct backdrop for their page, while +buffers with major-mode as ~pdf-view-mode~ automatically switches to dark +mode when ~modus-themes-toggle~ is called. + +** Decrease mode line height +:properties: +:custom_id: h:03be4438-dae1-4961-9596-60a307c070b5 +:end: +#+cindex: Decrease mode line height + +By default, the mode line of the Modus themes is set to 1 pixel width +for its =:box= attribute. In contrast, the mode line of stock Emacs is -1 +pixel. This small difference is considered necessary for the purposes +of accessibility as our out-of-the-box design has a prominent color +around the mode line (a border) to make its boundaries clear. With a +negative width the border and the text on the mode line can feel a bit +more difficult to read under certain scenaria. + +Furthermore, the user option ~modus-themes-mode-line~ ([[#h:27943af6-d950-42d0-bc23-106e43f50a24][Mode line]]) does not +allow for such a negative value because there are many edge cases that +simply make for a counter-intuitive set of possibilities, such as a =0= +value not being acceptable by the underlying face infrastructure, and +negative values greater than =-2= not being particularly usable. + +For these reasons, users who wish to decrease the overall height of the +mode line must handle things on their own by implementing the methods +for face customization documented herein. + +[[#h:1487c631-f4fe-490d-8d58-d72ffa3bd474][Basic face customization]]. + +One such method is to create a function that configures the desired +faces and hook it to ~modus-themes-after-load-theme-hook~ so that it +persists while switching between the Modus themes with the command +~modus-themes-toggle~. + +This one simply disables the box altogether, which will reduce the +height of the mode lines, but also remove their border: + +#+begin_src emacs-lisp +(defun my-modus-themes-custom-faces () + (set-face-attribute 'mode-line nil :box nil) + (set-face-attribute 'mode-line-inactive nil :box nil)) + +(add-hook 'modus-themes-after-load-theme-hook #'my-modus-themes-custom-faces) +#+end_src + +The above relies on the ~set-face-attribute~ function, though users who +plan to re-use colors from the theme and do so at scale are better off +with the more streamlined combination of the ~modus-themes-with-colors~ +macro and ~custom-set-faces~. + +[[#h:51ba3547-b8c8-40d6-ba5a-4586477fd4ae][Face customization at scale]]. + +As explained before in this document, this approach has a syntax that is +consistent with the source code of the themes, so it probably is easier +to re-use parts of the design. + +The following emulates the stock Emacs style, while still using the +colors of the Modus themes (whichever attribute is not explicitly stated +is inherited from the underlying theme): + +#+begin_src emacs-lisp +(defun my-modus-themes-custom-faces () + (modus-themes-with-colors + (custom-set-faces + `(mode-line ((,class :box (:line-width -1 :style released-button)))) + `(mode-line-inactive ((,class :box (:line-width -1 :color ,bg-region))))))) + +(add-hook 'modus-themes-after-load-theme-hook #'my-modus-themes-custom-faces) +#+end_src + +And this one is like the out-of-the-box style of the Modus themes, but +with the -1 height instead of 1: + +#+begin_src emacs-lisp +(defun my-modus-themes-custom-faces () + (modus-themes-with-colors + (custom-set-faces + `(mode-line ((,class :box (:line-width -1 :color ,fg-alt)))) + `(mode-line-inactive ((,class :box (:line-width -1 :color ,bg-region))))))) + +(add-hook 'modus-themes-after-load-theme-hook #'my-modus-themes-custom-faces) +#+end_src + +Finally, to also change the background color of the active mode line, +such as that it looks like the "accented" variant which is possible via +the user option ~modus-themes-mode-line~, the =:background= attribute needs +to be specified as well: + +#+begin_src emacs-lisp +(defun my-modus-themes-custom-faces () + (modus-themes-with-colors + (custom-set-faces + `(mode-line ((,class :box (:line-width -1 :color ,fg-alt) :background ,bg-active-accent))) + `(mode-line-inactive ((,class :box (:line-width -1 :color ,bg-region))))))) + +(add-hook 'modus-themes-after-load-theme-hook #'my-modus-themes-custom-faces) +#+end_src + +** Toggle themes without reloading them +:properties: +:custom_id: h:b40aca50-a3b2-4c43-be58-2c26fcd14237 +:end: +#+cindex: Switch themes without load-theme + +Users who have a stable setup and who only ever need to toggle between +the themes without triggering a full reload, are better off defining +their own command which calls ~enable-theme~ instead of ~load-theme~: + +#+begin_src emacs-lisp +(defun my-modus-themes-toggle () + "Toggle between `modus-operandi' and `modus-vivendi' themes. +This uses `enable-theme' instead of the standard method of +`load-theme'. The technicalities are covered in the Modus themes +manual." + (interactive) + (pcase (modus-themes--current-theme) + ('modus-operandi (progn (enable-theme 'modus-vivendi) + (disable-theme 'modus-operandi))) + ('modus-vivendi (progn (enable-theme 'modus-operandi) + (disable-theme 'modus-vivendi))) + (_ (error "No Modus theme is loaded; evaluate `modus-themes-load-themes' first")))) +#+end_src + +[[#h:e68560b3-7fb0-42bc-a151-e015948f8a35][Differences between loading and enabling]]. + +Recall that ~modus-themes-toggle~ uses ~load-theme~. + +** A theme-agnostic hook for theme loading +:properties: +:custom_id: h:86f6906b-f090-46cc-9816-1fe8aeb38776 +:end: + +The themes are designed with the intent to be useful to Emacs users of +varying skill levels, from beginners to experts. This means that we try +to make things easier by not expecting anyone reading this document to +be proficient in Emacs Lisp or programming in general. + +Such a case is with the use of the ~modus-themes-after-load-theme-hook~, +which runs after ~modus-themes-toggle~, ~modus-themes-load-operandi~, or +~modus-themes-load-vivendi~ is evaluated. We recommend using that hook +for advanced customizations, because (1) we know for sure that it is +available once the themes are loaded, and (2) anyone consulting this +manual, especially the sections on enabling and loading the themes, will +be in a good position to benefit from that hook. + +Advanced users who have a need to switch between the Modus themes and +other items will find that such a hook does not meet their requirements: +it only works with the Modus themes and only with the aforementioned +functions. + +A theme-agnostic setup can be configured thus: + +#+begin_src emacs-lisp +(defvar after-enable-theme-hook nil + "Normal hook run after enabling a theme.") + +(defun run-after-enable-theme-hook (&rest _args) + "Run `after-enable-theme-hook'." + (run-hooks 'after-enable-theme-hook)) + +(advice-add 'enable-theme :after #'run-after-enable-theme-hook) +#+end_src + +This creates the ~after-enable-theme-hook~ and makes it run after each +call to ~enable-theme~, which means that it will work for all themes and +also has the benefit that it does not depend on functions such as +~modus-themes-toggle~ and the others mentioned above. ~enable-theme~ is +called internally by ~load-theme~, so the hook works everywhere. + +Now this specific piece of Elisp may be simple for experienced users, +but it is not easy to read for newcomers, including the author of the +Modus themes for the first several months of their time as an Emacs +user. Hence our hesitation to recommend it as part of the standard +setup of the Modus themes (it is generally a good idea to understand +what the implications are of advising a function). + +** Diffs with only the foreground +:properties: +:custom_id: h:e2aed9eb-5e1e-45ec-bbd7-bc4faeab3236 +:end: +#+cindex: Foreground-only diffs + +Buffers that show differences between versions of a file or buffer, such +as in ~diff-mode~ and ~ediff~ always use color-coded background and +foreground combinations. + +[[#h:ea7ac54f-5827-49bd-b09f-62424b3b6427][Option for diff buffer looks]]. + +User may, however, prefer a style that removes the color-coded +backgrounds from regular changes while keeping them for word-wise (aka +"refined") changes---backgrounds for word-wise diffs are helpful in +context. To make this happen, one can use the ~modus-themes-with-colors~ +macro ([[#h:51ba3547-b8c8-40d6-ba5a-4586477fd4ae][Face specs at scale using the themes' palette]]): + +#+begin_src emacs-lisp +(defun my-modus-themes-custom-faces () + (modus-themes-with-colors + (custom-set-faces + `(modus-themes-diff-added ((,class :background unspecified :foreground ,green))) ; OR ,blue for deuteranopia + `(modus-themes-diff-changed ((,class :background unspecified :foreground ,yellow))) + `(modus-themes-diff-removed ((,class :background unspecified :foreground ,red))) + + `(modus-themes-diff-refine-added ((,class :background ,bg-diff-added :foreground ,fg-diff-added))) + ;; `(modus-themes-diff-refine-added ((,class :background ,bg-diff-added-deuteran :foreground ,fg-diff-added-deuteran))) + `(modus-themes-diff-refine-changed ((,class :background ,bg-diff-changed :foreground ,fg-diff-changed))) + `(modus-themes-diff-refine-removed ((,class :background ,bg-diff-removed :foreground ,fg-diff-removed))) + + `(modus-themes-diff-focus-added ((,class :background ,bg-dim :foreground ,green))) ; OR ,blue for deuteranopia + `(modus-themes-diff-focus-changed ((,class :background ,bg-dim :foreground ,yellow))) + `(modus-themes-diff-focus-removed ((,class :background ,bg-dim :foreground ,red))) + + `(modus-themes-diff-heading ((,class :background ,bg-alt :foreground ,fg-main))) + + `(diff-indicator-added ((,class :foreground ,green))) ; OR ,blue for deuteranopia + `(diff-indicator-changed ((,class :foreground ,yellow))) + `(diff-indicator-removed ((,class :foreground ,red))) + + `(magit-diff-added ((,class :background unspecified :foreground ,green-faint))) + `(magit-diff-changed ((,class :background unspecified :foreground ,yellow-faint))) + `(magit-diff-removed ((,class :background unspecified :foreground ,red-faint))) + `(magit-diff-context-highlight ((,class :background ,bg-dim :foreground ,fg-dim)))))) + +;; This is so that the changes persist when switching between +;; `modus-operandi' and `modus-vivendi'. +(add-hook 'modus-themes-after-load-theme-hook #'my-modus-themes-custom-faces) +#+end_src + +This used to be an optional style of ~modus-themes-diffs~, but has been +removed since version =2.0.0= to ensure that the accessibility standard +and aesthetic quality of the themes is not compromised. + +** Ediff without diff color-coding +:properties: +:custom_id: h:b0b31802-0216-427e-b071-1a47adcfe608 +:end: + +Ediff uses the same color-coding as ordinary diffs in ~diff-mode~, Magit, +etc. ([[#h:ea7ac54f-5827-49bd-b09f-62424b3b6427][Option for diff buffer looks]]). This is consistent with the +principle of least surprise. + +Users may, however, prefer to treat Ediff differently on the premise +that it does not need any particular color-coding to show added or +removed lines/words: it does not use the =+= or =-= markers, after all. + +This can be achieved by customizing the Ediff faces with color +combinations that do not carry the same connotations as those of diffs. +Consider this example, which leverages the ~modus-themes-with-colors~ +macro ([[#h:51ba3547-b8c8-40d6-ba5a-4586477fd4ae][Face specs at scale using the themes' palette]]): + +#+begin_src emacs-lisp +(defun my-modus-themes-custom-faces () + (modus-themes-with-colors + (custom-set-faces + `(ediff-current-diff-A ((,class :inherit unspecified :background ,bg-special-faint-cold :foreground ,fg-special-cold))) + `(ediff-current-diff-B ((,class :inherit unspecified :background ,bg-special-faint-warm :foreground ,fg-special-warm))) + `(ediff-current-diff-C ((,class :inherit unspecified :background ,bg-special-faint-calm :foreground ,fg-special-calm))) + `(ediff-fine-diff-A ((,class :inherit unspecified :background ,bg-special-cold :foreground ,fg-special-cold))) + `(ediff-fine-diff-B ((,class :inherit unspecified :background ,bg-special-warm :foreground ,fg-special-warm))) + `(ediff-fine-diff-C ((,class :inherit unspecified :background ,bg-special-calm :foreground ,fg-special-calm)))))) + +;; This is so that the changes persist when switching between +;; `modus-operandi' and `modus-vivendi'. +(add-hook 'modus-themes-after-load-theme-hook #'my-modus-themes-custom-faces) +#+end_src + +Remove the =:foreground= and its value to preserve the underlying +coloration. + +[[#h:f4d4b71b-2ca5-4c3d-b0b4-9bfd7aa7fb4d][Visualize the active Modus theme's palette]]. + +** Near-monochrome syntax highlighting +:properties: +:custom_id: h:c1f3fa8e-7a63-4a6f-baf3-a7febc0661f0 +:end: +#+cindex: Monochrome code syntax + +While the Modus themes do provide a user option to control the overall +style of syntax highlighting in programming major modes, they do not +cover the possibility of a monochromatic or near-monochromatic design +([[#h:c119d7b2-fcd4-4e44-890e-5e25733d5e52][Option for syntax highlighting]]). This is due to the multitude of +preferences involved: one may like comments to be styled with an accent +value, another may want certain constructs to be bold, a third may apply +italics to doc strings but not comments... The possibilities are +virtually endless. As such, this sort of design is best handled at the +user level in accordance with the information furnished elsewhere in +this manual. + +[[#h:1487c631-f4fe-490d-8d58-d72ffa3bd474][Case-by-case face specs using the themes' palette]]. + +[[#h:51ba3547-b8c8-40d6-ba5a-4586477fd4ae][Face specs at scale using the themes' palette]]. + +The gist is that we want to override the font-lock faces. For our +changes to persist while switching between ~modus-operandi~ and +~modus-vivendi~ we wrap our face overrides in a function that we hook to +~modus-themes-after-load-theme-hook~. + +Users who want to replicate the structure of the themes' source code are +advised to use the examples with ~custom-set-faces~. Those who prefer a +different approach can use the snippets which call ~set-face-attribute~. +Below are the code blocks. + +The following uses a yellow accent value for comments and green hues for +strings. Regexp grouping constructs have color values that work in the +context of a green string. All other elements use the main foreground +color, except warnings such as the ~user-error~ function in Elisp +buffers which gets a subtle red tint (not to be confused with the +~warning~ face which is used for genuine warnings). Furthermore, notice +the ~modus-themes-bold~ and ~modus-themes-slant~ which apply the +preference set in the user options ~modus-themes-bold-constructs~ and +~modus-themes-italic-constructs~, respectively. Users who do not want +this conditionally must replace these faces with ~bold~ and ~italic~ +respectively (or ~unspecified~ to disable the effect altogether). + +#+begin_src emacs-lisp +;; This is the hook. It will not be replicated across all code samples. +(add-hook 'modus-themes-after-load-theme-hook #'my-modus-themes-subtle-syntax) + +(defun my-modus-themes-subtle-syntax () + (modus-themes-with-colors + (custom-set-faces + `(font-lock-builtin-face ((,class :inherit modus-themes-bold :foreground unspecified))) + `(font-lock-comment-delimiter-face ((,class :inherit font-lock-comment-face))) + `(font-lock-comment-face ((,class :inherit unspecified :foreground ,fg-comment-yellow))) + `(font-lock-constant-face ((,class :foreground unspecified))) + `(font-lock-doc-face ((,class :inherit modus-themes-slant :foreground ,fg-special-mild))) + `(font-lock-function-name-face ((,class :foreground unspecified))) + `(font-lock-keyword-face ((,class :inherit modus-themes-bold :foreground unspecified))) + `(font-lock-negation-char-face ((,class :inherit modus-themes-bold :foreground unspecified))) + `(font-lock-preprocessor-face ((,class :foreground unspecified))) + `(font-lock-regexp-grouping-backslash ((,class :inherit bold :foreground ,yellow))) + `(font-lock-regexp-grouping-construct ((,class :inherit bold :foreground ,blue-alt-other))) + `(font-lock-string-face ((,class :foreground ,green-alt-other))) + `(font-lock-type-face ((,class :inherit modus-themes-bold :foreground unspecified))) + `(font-lock-variable-name-face ((,class :foreground unspecified))) + `(font-lock-warning-face ((,class :inherit modus-themes-bold :foreground ,red-nuanced-fg)))))) + +;; Same as above with `set-face-attribute' instead of `custom-set-faces' +(defun my-modus-themes-subtle-syntax () + (modus-themes-with-colors + (set-face-attribute 'font-lock-builtin-face nil :inherit 'modus-themes-bold :foreground 'unspecified) + (set-face-attribute 'font-lock-comment-delimiter-face nil :inherit 'font-lock-comment-face) + (set-face-attribute 'font-lock-comment-face nil :inherit 'unspecified :foreground fg-comment-yellow) + (set-face-attribute 'font-lock-constant-face nil :foreground 'unspecified) + (set-face-attribute 'font-lock-doc-face nil :inherit 'modus-themes-slant :foreground fg-special-mild) + (set-face-attribute 'font-lock-function-name-face nil :foreground 'unspecified) + (set-face-attribute 'font-lock-keyword-face nil :inherit 'modus-themes-bold :foreground 'unspecified) + (set-face-attribute 'font-lock-negation-char-face nil :inherit 'modus-themes-bold :foreground 'unspecified) + (set-face-attribute 'font-lock-preprocessor-face nil :foreground 'unspecified) + (set-face-attribute 'font-lock-regexp-grouping-backslash nil :inherit 'bold :foreground yellow) + (set-face-attribute 'font-lock-regexp-grouping-construct nil :inherit 'bold :foreground blue-alt-other) + (set-face-attribute 'font-lock-string-face nil :foreground green-alt-other) + (set-face-attribute 'font-lock-type-face nil :inherit 'modus-themes-bold :foreground 'unspecified) + (set-face-attribute 'font-lock-variable-name-face nil :foreground 'unspecified) + (set-face-attribute 'font-lock-warning-face nil :inherit 'modus-themes-bold :foreground red-nuanced-fg))) +#+end_src + +The following sample is the same as above, except strings are blue and +comments are gray. Regexp constructs are adapted accordingly. + +#+begin_src emacs-lisp +(defun my-modus-themes-subtle-syntax () + (modus-themes-with-colors + (custom-set-faces + `(font-lock-builtin-face ((,class :inherit modus-themes-bold :foreground unspecified))) + `(font-lock-comment-delimiter-face ((,class :inherit font-lock-comment-face))) + `(font-lock-comment-face ((,class :inherit unspecified :foreground ,fg-alt))) + `(font-lock-constant-face ((,class :foreground unspecified))) + `(font-lock-doc-face ((,class :inherit modus-themes-slant :foreground ,fg-docstring))) + `(font-lock-function-name-face ((,class :foreground unspecified))) + `(font-lock-keyword-face ((,class :inherit modus-themes-bold :foreground unspecified))) + `(font-lock-negation-char-face ((,class :inherit modus-themes-bold :foreground unspecified))) + `(font-lock-preprocessor-face ((,class :foreground unspecified))) + `(font-lock-regexp-grouping-backslash ((,class :inherit bold :foreground ,fg-escape-char-backslash))) + `(font-lock-regexp-grouping-construct ((,class :inherit bold :foreground ,fg-escape-char-construct))) + `(font-lock-string-face ((,class :foreground ,blue-alt))) + `(font-lock-type-face ((,class :inherit modus-themes-bold :foreground unspecified))) + `(font-lock-variable-name-face ((,class :foreground unspecified))) + `(font-lock-warning-face ((,class :inherit modus-themes-bold :foreground ,red-nuanced-fg)))))) + +;; Same as above with `set-face-attribute' instead of `custom-set-faces' +(defun my-modus-themes-subtle-syntax () + (modus-themes-with-colors + (set-face-attribute 'font-lock-builtin-face nil :inherit 'modus-themes-bold :foreground 'unspecified) + (set-face-attribute 'font-lock-comment-delimiter-face nil :inherit 'font-lock-comment-face) + (set-face-attribute 'font-lock-comment-face nil :inherit 'unspecified :foreground fg-alt) + (set-face-attribute 'font-lock-constant-face nil :foreground 'unspecified) + (set-face-attribute 'font-lock-doc-face nil :inherit 'modus-themes-slant :foreground fg-docstring) + (set-face-attribute 'font-lock-function-name-face nil :foreground 'unspecified) + (set-face-attribute 'font-lock-keyword-face nil :inherit 'modus-themes-bold :foreground 'unspecified) + (set-face-attribute 'font-lock-negation-char-face nil :inherit 'modus-themes-bold :foreground 'unspecified) + (set-face-attribute 'font-lock-preprocessor-face nil :foreground 'unspecified) + (set-face-attribute 'font-lock-regexp-grouping-backslash nil :inherit 'bold :foreground fg-escape-char-backslash) + (set-face-attribute 'font-lock-regexp-grouping-construct nil :inherit 'bold :foreground fg-escape-char-construct) + (set-face-attribute 'font-lock-string-face nil :foreground blue-alt) + (set-face-attribute 'font-lock-type-face nil :inherit 'modus-themes-bold :foreground 'unspecified) + (set-face-attribute 'font-lock-variable-name-face nil :foreground 'unspecified) + (set-face-attribute 'font-lock-warning-face nil :inherit 'modus-themes-bold :foreground red-nuanced-fg))) +#+end_src + +** Custom hl-todo colors +:PROPERTIES: +:CUSTOM_ID: h:2ef83a21-2f0a-441e-9634-473feb940743 +:END: + +The =hl-todo= package provides the user option ~hl-todo-keyword-faces~: +it specifies a pair of keyword and corresponding color value. The Modus +themes configure that option in the interest of legibility. While this +works for our purposes, users may still prefer to apply their custom +values, in which case the following approach is necessary: + +#+begin_src emacs-lisp +(defun my-modus-themes-hl-todo-faces () + (setq hl-todo-keyword-faces '(("TODO" . "#ff0000") + ("HACK" . "#ffff00") + ("XXX" . "#00ffff") + ("NOTE" . "#ff00ff")))) + +(add-hook 'modus-themes-after-load-theme-hook #'my-modus-themes-hl-todo-faces) +#+end_src + +Or include a ~let~ form, if needed: + +#+begin_src emacs-lisp +(defun my-modus-themes-hl-todo-faces () + (let ((red "#ff0000") + (blue "#0000ff")) + (setq hl-todo-keyword-faces `(("TODO" . ,blue) + ("HACK" . ,red) + ("XXX" . ,red) + ("NOTE" . ,blue))))) + +(add-hook 'modus-themes-after-load-theme-hook #'my-modus-themes-hl-todo-faces) +#+end_src + +Normally, we do not touch user options, though this is an exception: +otherwise the defaults are not always legible. + +** Add support for solaire-mode +:PROPERTIES: +:CUSTOM_ID: h:439c9e46-52e2-46be-b1dc-85841dd99671 +:END: + +The =solaire-mode= package dims the background of what it considers +ancillary "UI" buffers, such as the minibuffer and Dired buffers. The +Modus themes used to support Solaire on the premise that the user was +(i) opting in to it, (ii) understood why certain buffers were more gray, +and (iii) knew what other adjustments had to be made to prevent broken +visuals (e.g. the default style of the ~modus-themes-completions~ uses a +subtle gray background for the selection, which with Solaire becomes +practically invisible). + +However, the assumption that users opt in to this feature does not +always hold true. There are cases where it is enabled by defaultsuch as +in the popular Doom Emacs configuration. Thus, the unsuspecting user +who loads ~modus-operandi~ or ~modus-vivendi~ without the requisite +customizations is getting a sub-par experience; an experience that we +did not intend and cannot genuinely fix. + +Because the Modus themes are meant to work everywhere, we cannot make an +exception for Doom Emacs and/or Solaire users. Furthermore, we shall +not introduce hacks, such as by adding a check in all relevant faces to +be adjusted based on Solaire or whatever other package. Hacks of this +sort are unsustainable and penalize the entire userbase. Besides, the +themes are built into Emacs and we must keep their standard high. + +The fundamental constraint with Solaire is that Emacs does not have a +real distinction between "content" and "UI" buffers. For themes to work +with Solaire, they need to be designed around that package. Such is an +arrangement that compromises on our accessibility standards and/or +hinders our efforts to provide the best possible experience while using +the Modus themes. + +As such, =solaire-mode= is not---and will not be---supported by the +Modus themes (or any other of my themes, for that matter). Users who +want it must style the faces manually. Below is some sample code, based +on what we cover at length elsewhere in this manual: + +[[#h:f4651d55-8c07-46aa-b52b-bed1e53463bb][Advanced customization]]. + +[[#h:51ba3547-b8c8-40d6-ba5a-4586477fd4ae][Face specs at scale using the themes' palette]]. + +#+begin_src emacs-lisp +(defun my-modus-themes-custom-faces () + (modus-themes-with-colors + (custom-set-faces + `(solaire-default-face ((,class :inherit default :background ,bg-alt :foreground ,fg-dim))) + `(solaire-line-number-face ((,class :inherit solaire-default-face :foreground ,fg-unfocused))) + `(solaire-hl-line-face ((,class :background ,bg-active))) + `(solaire-org-hide-face ((,class :background ,bg-alt :foreground ,bg-alt)))))) + +(add-hook 'modus-themes-after-load-theme-hook #'my-modus-themes-custom-faces) +#+end_src + +As always, re-load the theme for changes to take effect. + +* Face coverage +:properties: +:custom_id: h:a9c8f29d-7f72-4b54-b74b-ddefe15d6a19 +:end: + +The Modus themes try to provide as close to full face coverage as +possible. This is necessary to ensure a consistently accessible reading +experience across all available interfaces. + +** Full support for packages or face groups +:properties: +:alt_title: Supported packages +:description: Full list of covered face groups +:custom_id: h:60ed4275-60d6-49f8-9287-9a64e54bea0e +:end: +#+cindex: Explicitly supported packages + +This list will always be updated to reflect the current state of the +project. The idea is to offer an overview of the known status of all +affected face groups. The items with an appended asterisk =*= tend to +have lots of extensions, so the "full support" may not be 100% true… + ++ ace-window ++ alert ++ all-the-icons ++ all-the-icons-dired ++ all-the-icons-ibuffer ++ annotate ++ ansi-color ++ anzu ++ apropos ++ artbollocks-mode ++ auctex and TeX ++ auto-dim-other-buffers ++ avy ++ awesome-tray ++ bbdb ++ binder ++ bm ++ bongo ++ boon ++ bookmark ++ breakpoint (provided by the built-in {{{file(gdb-mi.el)}}} library) ++ calendar and diary ++ calfw ++ calibredb ++ cfrs ++ change-log and log-view (such as ~vc-print-log~, ~vc-print-root-log~) ++ chart ++ cider ++ circe ++ citar ++ color-rg ++ column-enforce-mode ++ company-mode* ++ company-posframe ++ compilation-mode ++ completions ++ consult ++ corfu ++ corfu-quick ++ counsel* ++ counsel-css ++ cov ++ cperl-mode ++ css-mode ++ csv-mode ++ ctrlf ++ custom (what you get with {{{kbd(M-x customize)}}}) ++ dap-mode ++ deadgrep ++ debbugs ++ deft ++ denote ++ devdocs ++ dictionary ++ diff-hl ++ diff-mode ++ dim-autoload ++ dir-treeview ++ dired ++ dired-async ++ dired-git ++ dired-git-info ++ dired-narrow ++ dired-subtree ++ diredfl ++ diredp (dired+) ++ display-fill-column-indicator-mode ++ doom-modeline ++ easy-jekyll ++ ebdb ++ ediff ++ ein (Emacs IPython Notebook) ++ eglot ++ el-search ++ eldoc-box ++ elfeed ++ elfeed-score ++ elpher ++ embark ++ ement ++ emms ++ enh-ruby-mode (enhanced-ruby-mode) ++ epa ++ equake ++ erc ++ eros ++ ert ++ eshell ++ eshell-fringe-status ++ eshell-git-prompt ++ eshell-prompt-extras (epe) ++ eshell-syntax-highlighting ++ evil* (evil-mode) ++ evil-goggles ++ evil-snipe ++ evil-visual-mark-mode ++ eww ++ exwm ++ eyebrowse ++ fancy-dabbrev ++ flycheck ++ flycheck-color-mode-line ++ flycheck-indicator ++ flycheck-posframe ++ flymake ++ flyspell ++ flx ++ freeze-it ++ focus ++ fold-this ++ font-lock (generic syntax highlighting) ++ forge ++ fountain (fountain-mode) ++ geiser ++ git-commit ++ git-gutter (and variants) ++ git-rebase ++ git-timemachine ++ gnus ++ gotest ++ golden-ratio-scroll-screen ++ helm* ++ helm-ls-git ++ helm-switch-shell ++ helm-xref ++ helpful ++ highlight-indentation ++ highlight-numbers ++ highlight-parentheses ([[#h:24bab397-dcb2-421d-aa6e-ec5bd622b913][Note on highlight-parentheses.el]]) ++ highlight-thing ++ hl-defined ++ hl-fill-column ++ hl-line-mode ++ hl-todo ++ hydra ++ ibuffer ++ icomplete ++ icomplete-vertical ++ ido-mode ++ iedit ++ iflipb ++ image-dired ++ imenu-list ++ indium ++ info ++ info+ (info-plus) ++ info-colors ++ interaction-log ++ ioccur ++ isearch, occur, etc. ++ ivy* ++ ivy-posframe ++ jira (org-jira) ++ journalctl-mode ++ js2-mode ++ julia ++ jupyter ++ kaocha-runner ++ keycast ++ ledger-mode ++ leerzeichen ++ line numbers (~display-line-numbers-mode~ and global variant) ++ lsp-mode ++ lsp-ui ++ macrostep ++ magit ++ magit-imerge ++ make-mode ++ man ++ marginalia ++ markdown-mode ++ markup-faces (~adoc-mode~) ++ mentor ++ messages ++ mini-modeline ++ minimap ++ mmm-mode ++ mode-line ++ mood-line ++ moody ++ mpdel ++ mu4e ++ multiple-cursors ++ nano-modeline ++ neotree ++ notmuch ++ num3-mode ++ nxml-mode ++ orderless ++ org* ++ org-journal ++ org-noter ++ org-pomodoro ++ org-recur ++ org-roam ++ org-superstar ++ org-table-sticky-header ++ org-tree-slide ++ origami ++ outline-mode ++ outline-minor-faces ++ package (what you get with {{{kbd(M-x list-packages)}}}) ++ page-break-lines ++ pandoc-mode ++ paren-face ++ pass ++ pdf-tools ++ persp-mode ++ perspective ++ phi-grep ++ pomidor ++ popup ++ powerline ++ powerline-evil ++ prism ([[#h:a94272e0-99da-4149-9e80-11a7e67a2cf2][Note for prism.el]]) ++ proced ++ prodigy ++ pulse ++ pyim ++ quick-peek ++ racket-mode ++ rainbow-blocks ++ rainbow-delimiters ++ rcirc ++ recursion-indicator ++ regexp-builder (also known as ~re-builder~) ++ rg (rg.el) ++ ripgrep ++ rmail ++ ruler-mode ++ selectrum ++ selectrum-prescient ++ semantic ++ sesman ++ shell-script-mode ++ shortdoc ++ show-paren-mode ++ shr ++ side-notes ++ sieve-mode ++ skewer-mode ++ slime (slbd) ++ sly ++ smart-mode-line ++ smartparens ++ smerge ++ spaceline ++ speedbar ++ stripes ++ suggest ++ switch-window ++ swiper ++ sx ++ symbol-overlay ++ syslog-mode ++ tab-bar-groups ++ tab-bar-mode ++ tab-line-mode ++ table (built-in table.el) ++ telega ++ telephone-line ++ terraform-mode ++ term ++ textsec ++ tomatinho ++ transient (pop-up windows such as Magit's) ++ trashed ++ tree-sitter ++ treemacs ++ tty-menu ++ tuareg ++ typescript ++ undo-tree ++ vc (vc-dir.el, vc-hooks.el) ++ vertico ++ vertico-quick ++ vimish-fold ++ visible-mark ++ visual-regexp ++ vterm ++ vundo ++ wcheck-mode ++ web-mode ++ wgrep ++ which-function-mode ++ which-key ++ whitespace-mode ++ window-divider-mode ++ winum ++ writegood-mode ++ woman ++ xah-elisp-mode ++ xref ++ xterm-color (and ansi-colors) ++ yaml-mode ++ yasnippet ++ ztree + +Plus many other miscellaneous faces that are provided by the upstream +GNU Emacs distribution. + +** Indirectly covered packages +:properties: +:custom_id: h:2cb359c7-3a84-4262-bab3-dcdc1d0034d7 +:end: +#+cindex: Implicitly supported packages + +These do not require any extra styles because they are configured to +inherit from some basic faces or their dependencies which are directly +supported by the themes. + ++ ag ++ apt-sources-list ++ buffer-expose ++ bufler ++ counsel-notmuch ++ counsel-org-capture-string ++ dashboard (emacs-dashboard) ++ define-word ++ disk-usage ++ dtache ++ dynamic-ruler ++ easy-kill ++ edit-indirect ++ egerrit ++ elfeed-summary ++ evil-owl ++ flyspell-correct ++ fortran-mode ++ git-walktree ++ goggles ++ highlight-defined ++ highlight-escape-sequences (~hes-mode~) ++ i3wm-config-mode ++ minibuffer-line ++ no-emoji ++ org-remark ++ parrot ++ perl-mode ++ php-mode ++ rjsx-mode ++ side-hustle ++ spell-fu ++ swift-mode ++ tab-bar-echo-area ++ tide ++ undo-hl ++ vdiff ++ vertico-indexed ++ vertico-mouse + +* Notes on individual packages +:properties: +:custom_id: h:4c4d901a-84d7-4f20-bd99-0808c2b06eba +:end: + +This section covers information that may be of interest to users of +individual packages. + +** Note on calendar.el weekday and weekend colors +:properties: +:custom_id: h:b2db46fb-32f4-44fd-8e11-d2b261cf51ae +:end: + +By default, the {{{kbd(M-x calendar)}}} interface differentiates weekdays from +weekends by applying a gray color to the former and a faint red to the +latter. The idea for this approach is that the weekend should serve as +a subtle warning that no work is supposed to be done on that day, per +the design of traditional calendars. + +Users who prefer all days to look the same can configure the variable +~calendar-weekend-days~ to either use gray of weekdays or the faint red of +weekends uniformly. + +#+begin_src emacs-lisp +;; All are treated like weekdays (gray color) +(setq calendar-weekend-days nil) + +;; All are treated like weekends (red-faint color) +(setq calendar-weekend-days (number-sequence 0 6)) + +;; The default marks the Saturday and Sunday as the weekend +(setq calendar-weekend-days '(0 6)) +#+end_src + +For changes to take effect, the Calendar buffer needs to be generated +anew. + +** Note on git-gutter in Doom Emacs +:PROPERTIES: +:CUSTOM_ID: h:a195e37c-e58c-4148-b254-8ba1ed8a731a +:END: + +The =git-gutter= and =git-gutter-fr= packages default to drawing bitmaps +for the indicators they display (e.g. bitmap of a plus sign for added +lines). In Doom Emacs, these bitmaps are replaced with contiguous lines +which may look nicer, but require a change to the foreground of the +relevant faces to yield the desired color combinations. + +Since this is Doom-specific, we urge users to apply changes in their +local setup. Below is some sample code, based on what we cover at +length elsewhere in this manual: + +[[#h:f4651d55-8c07-46aa-b52b-bed1e53463bb][Advanced customization]]. + +[[#h:51ba3547-b8c8-40d6-ba5a-4586477fd4ae][Face specs at scale using the themes' palette]]. + +#+begin_src emacs-lisp +(defun my-modus-themes-custom-faces () + (modus-themes-with-colors + (custom-set-faces + ;; Replace green with blue if you use `modus-themes-deuteranopia'. + `(git-gutter-fr:added ((,class :foreground ,green-fringe-bg))) + `(git-gutter-fr:deleted ((,class :foreground ,red-fringe-bg))) + `(git-gutter-fr:modified ((,class :foreground ,yellow-fringe-bg)))))) + +(add-hook 'modus-themes-after-load-theme-hook #'my-modus-themes-custom-faces) +#+end_src + +As always, re-load the theme for changes to take effect. + +If the above does not work, try this instead: + +#+begin_src emacs-lisp +(after! modus-themes + (modus-themes-with-colors + (custom-set-faces + ;; Replace green with blue if you use `modus-themes-deuteranopia'. + `(git-gutter-fr:added ((,class :foreground ,green-fringe-bg))) + `(git-gutter-fr:deleted ((,class :foreground ,red-fringe-bg))) + `(git-gutter-fr:modified ((,class :foreground ,yellow-fringe-bg)))))) +#+end_src + +Replace ~green-fringe-bg~ with ~blue-fringe-bg~ if you want to optimize +for red-green color deficiency. + +[[#h:3ed03a48-20d8-4ce7-b214-0eb7e4c79abe][Option for red-green color deficiency or deuteranopia]]. + +** Note on php-mode multiline comments +:PROPERTIES: +:CUSTOM_ID: h:d0a3157b-9c04-46e8-8742-5fb2a7ae8798 +:END: + +Depending on your build of Emacs and/or the environment it runs in, +multiline comments in PHP with the =php-mode= package use the +~font-lock-doc-face~ instead of ~font-lock-comment-face~. + +This seems to make all comments use the appropriate face: + +#+begin_src emacs-lisp +(defun my-multine-comments () + (setq-local c-doc-face-name 'font-lock-comment-face)) + +(add-hook 'php-mode-hook #'my-multine-comments) +#+end_src + +As always, re-load the theme for changes to take effect. + +** Note on underlines in compilation buffers +:properties: +:custom_id: h:420f5a33-c7a9-4112-9b04-eaf2cbad96bd +:end: + +Various buffers that produce compilation results or run tests on code +apply an underline to the file names they reference or to relevant +messages. Users may consider this unnecessary or excessive. + +To outright disable the effect, use this (buffers need to be generated +anew): + +#+begin_src emacs-lisp +(setq compilation-message-face nil) +#+end_src + +If some element of differentiation is still desired, a good option is to +render the affected text with the ~italic~ face: + +#+begin_src emacs-lisp +(setq compilation-message-face 'italic) +#+end_src + +[[#h:2793a224-2109-4f61-a106-721c57c01375][Configure bold and italic faces]]. + +** Note on inline Latex in Org buffers +:properties: +:custom_id: h:dd8478da-f56a-45cd-b199-b836c85c3c5a +:end: + +Org can work with inline latex and related syntax. To actually fontify +those constructs, set the variable ~org-highlight-latex-and-related~ to +the desired list of values (per its doc string). For example: + +#+begin_src emacs-lisp +(setq org-highlight-latex-and-related '(latex script)) +#+end_src + +Remember to use {{{kbd(M-x org-mode-restart)}}} for changes to take effect. + +** Note on dimmer.el +:properties: +:custom_id: h:8eb4b758-d318-4480-9ead-357a571beb93 +:end: + +The {{{file(dimmer.el)}}} library by Neil Okamoto can be configured to +automatically dim the colors of inactive Emacs windows. To guarantee +consistent results with the Modus themes, we suggest some tweaks to the +default styles, such as in this minimal setup: + +#+begin_src emacs-lisp +(use-package dimmer + :config + (setq dimmer-fraction 0.3) + (setq dimmer-adjustment-mode :foreground) + (setq dimmer-use-colorspace :rgb) + + (dimmer-mode 1)) +#+end_src + +Of the above, we strongly recommend the RGB color space because it is +the one that remains faithful to the hueness of the colors used by the +themes. Whereas the default CIELAB space has a tendency to distort +colors in addition to applying the dim effect, which can be somewhat +disorienting. + +The value of the ~dimmer-fraction~ has been selected empirically. Users +might prefer to tweak it further (increasing it makes the dim effect +more pronounced). + +Changing the ~dimmer-adjustment-mode~ is a matter of preference. Though +because the Modus themes use black and white as their base colors, any +other value for that variable will turn the main background gray. This +inadvertently leads to the opposite of the intended utility of this +package: it draws too much attention to unfocused windows. + +** Note on display-fill-column-indicator-mode +:properties: +:custom_id: h:2a602816-bc1b-45bf-9675-4cbbd7bf6cab +:end: + +The ~display-fill-column-indicator-mode~ uses a typographic character to +draw its line. This has the downside of creating a dashed line. The +dashes are further apart depending on how tall the font's glyph height +is and what integer the ~line-spacing~ is set to. + +At the theme level we eliminate this effect by making the character one +pixel tall: the line is contiguous. Users who prefer the dashed line +are advised to change the ~fill-column-indicator~ face, as explained +elsewhere in this document. For example: + +#+begin_src emacs-lisp +(modus-themes-with-colors + (custom-set-faces + `(fill-column-indicator ((,class :foreground ,bg-active))))) +#+end_src + +[[#h:51ba3547-b8c8-40d6-ba5a-4586477fd4ae][Face specs at scale using the themes' palette]]. + +To make the line thicker, set the height to be equal to the base font +size instead of the one pixel we use. This is done by specifying a rate +instead of an absolute number, as in =:height 1.0= versus =:height 1=. +For example: + +#+begin_src emacs-lisp +(modus-themes-with-colors + (custom-set-faces + `(fill-column-indicator ((,class :height 1.0 :background ,bg-inactive :foreground ,bg-inactive))))) +#+end_src + +** Note on highlight-parentheses.el +:PROPERTIES: +:CUSTOM_ID: h:24bab397-dcb2-421d-aa6e-ec5bd622b913 +:END: + +The =highlight-parentheses= package provides contextual coloration of +surrounding parentheses, highlighting only those which are around the +point. The package expects users to customize the applicable colors on +their own by configuring certain variables. + +To make the Modus themes work as expected with this, we need to use some +of the techniques that are discussed at length in the various +"Do-It-Yourself" (DIY) sections, which provide insight into the more +advanced customization options of the themes. + +[[#h:f4651d55-8c07-46aa-b52b-bed1e53463bb][Advanced customization]]. + +In the following example, we are assuming that the user wants to (i) +re-use color variables provided by the themes, (ii) be able to retain +their tweaks while switching between ~modus-operandi~ and ~modus-vivendi~, +and (iii) have the option to highlight either the foreground of the +parentheses or the background as well. + +We start by defining our own variable, which will serve as a toggle +between foreground and background coloration styles: + +#+begin_src emacs-lisp +(defvar my-highlight-parentheses-use-background t + "Prefer `highlight-parentheses-background-colors'.") +#+end_src + +Then we can update our preference with this: + +#+begin_src emacs-lisp +;; Set to nil to disable backgrounds. +(setq my-highlight-parentheses-use-background nil) +#+end_src + +To re-use colors from the themes, we must wrap our code in the +~modus-themes-with-colors~ macro. Our implementation must interface with +the variables ~highlight-parentheses-background-colors~ and/or +~highlight-parentheses-colors~. + +So we can have something like this (the doc string of +~modus-themes-with-colors~ explains where the names of the colors can be +found): + +#+begin_src emacs-lisp +(modus-themes-with-colors + ;; Our preference for setting either background or foreground + ;; styles, depending on `my-highlight-parentheses-use-background'. + (if my-highlight-parentheses-use-background + + ;; Here we set color combinations that involve both a background + ;; and a foreground value. + (setq highlight-parentheses-background-colors (list cyan-refine-bg + magenta-refine-bg + green-refine-bg + yellow-refine-bg) + highlight-parentheses-colors (list cyan-refine-fg + magenta-refine-fg + green-refine-fg + yellow-refine-fg)) + + ;; And here we pass only foreground colors while disabling any + ;; backgrounds. + (setq highlight-parentheses-colors (list green-intense + magenta-intense + blue-intense + red-intense) + highlight-parentheses-background-colors nil))) + +;; Include this if you also want to make the parentheses bold: +(set-face-attribute 'highlight-parentheses-highlight nil :inherit 'bold) + +;; Our changes must be evaluated before enabling the relevant mode, so +;; this comes last. +(global-highlight-parentheses-mode 1) +#+end_src + +For our changes to persist while switching between the Modus themes, we +need to include them in a function which can then get passed to +~modus-themes-after-load-theme-hook~. This is the complete +implementation: + +#+begin_src emacs-lisp +;; Configurations for `highlight-parentheses': +(require 'highlight-parentheses) + +(defvar my-highlight-parentheses-use-background t + "Prefer `highlight-parentheses-background-colors'.") + +(setq my-highlight-parentheses-use-background nil) ; Set to nil to disable backgrounds + +(defun my-modus-themes-highlight-parentheses () + (modus-themes-with-colors + ;; Our preference for setting either background or foreground + ;; styles, depending on `my-highlight-parentheses-use-background'. + (if my-highlight-parentheses-use-background + + ;; Here we set color combinations that involve both a background + ;; and a foreground value. + (setq highlight-parentheses-background-colors (list cyan-refine-bg + magenta-refine-bg + green-refine-bg + yellow-refine-bg) + highlight-parentheses-colors (list cyan-refine-fg + magenta-refine-fg + green-refine-fg + yellow-refine-fg)) + + ;; And here we pass only foreground colors while disabling any + ;; backgrounds. + (setq highlight-parentheses-colors (list green-intense + magenta-intense + blue-intense + red-intense) + highlight-parentheses-background-colors nil))) + + ;; Include this if you also want to make the parentheses bold: + (set-face-attribute 'highlight-parentheses-highlight nil :inherit 'bold) + + ;; Our changes must be evaluated before enabling the relevant mode, so + ;; this comes last. + (global-highlight-parentheses-mode 1)) + +(add-hook 'modus-themes-after-load-theme-hook #'my-modus-themes-highlight-parentheses) +#+end_src + +As always, re-load the theme for changes to take effect. + +** Note on mmm-mode.el background colors +:properties: +:custom_id: h:99cf0d6c-e478-4e26-9932-3bf3427d13f6 +:end: + +The faces used by {{{file(mmm-mode.el)}}} are expected to have a colorful +background, while they should not touch any foreground value. The idea +is that they must not interfere with existing fontification. Those +background colors need to be distinct from each other, such as an +unambiguous red juxtaposed with a clear blue. + +While this design may be internally consistent with the raison d'être of +that library, it inevitably produces inaccessible color combinations. + +There are two competing goals at play: + +1. Legibility of the text, understood as the contrast ratio between the + background and the foreground. + +2. Semantic precision of each face which entails faithfulness to + color-coding of the underlying background. + +As the Modus themes are designed with the express purpose of conforming +with the first point, we have to forgo the apparent color-coding of the +background elements. Instead we use subtle colors that do not undermine +the legibility of the affected text while they still offer a sense of +added context. + +Users who might prefer to fall below the minimum 7:1 contrast ratio in +relative luminance (the accessibility target we conform with), can opt +to configure the relevant faces on their own. + +[[#h:51ba3547-b8c8-40d6-ba5a-4586477fd4ae][Face specs at scale using the themes' palette]]. + +This example uses more vivid background colors, though it comes at the +very high cost of degraded legibility. + +#+begin_src emacs-lisp +(modus-themes-with-colors + (custom-set-faces + `(mmm-cleanup-submode-face ((,class :background ,yellow-refine-bg))) + `(mmm-code-submode-face ((,class :background ,bg-active))) + `(mmm-comment-submode-face ((,class :background ,blue-refine-bg))) + `(mmm-declaration-submode-face ((,class :background ,cyan-refine-bg))) + `(mmm-default-submode-face ((,class :background ,bg-alt))) + `(mmm-init-submode-face ((,class :background ,magenta-refine-bg))) + `(mmm-output-submode-face ((,class :background ,red-refine-bg))) + `(mmm-special-submode-face ((,class :background ,green-refine-bg))))) +#+end_src + +** Note on prism.el +:properties: +:alt_title: Note for prism +:custom_id: h:a94272e0-99da-4149-9e80-11a7e67a2cf2 +:end: + +This package by Adam Porter, aka "alphapapa" or "github-alphapapa", +implements an alternative to the typical coloration of code. Instead of +highlighting the syntactic constructs, it applies color to different +levels of depth in the code structure. + +As {{{file(prism.el)}}} offers a broad range of customizations, we cannot +style it directly at the theme level: that would run contrary to the +spirit of the package. Instead, we may offer preset color schemes. +Those should offer a starting point for users to adapt to their needs. + +In the following code snippets, we employ the ~modus-themes-with-colors~ +macro: [[#h:51ba3547-b8c8-40d6-ba5a-4586477fd4ae][Face specs at scale using the themes' palette]]. + +These are the minimum recommended settings with 16 colors: + +#+begin_src emacs-lisp +(setq prism-num-faces 16) + +(prism-set-colors + :desaturations '(0) ; do not change---may lower the contrast ratio + :lightens '(0) ; same + :colors (modus-themes-with-colors + (list fg-main + magenta + cyan-alt-other + magenta-alt-other + blue + magenta-alt + cyan-alt + red-alt-other + green + fg-main + cyan + yellow + blue-alt + red-alt + green-alt-other + fg-special-warm))) +#+end_src + +With 8 colors: + +#+begin_src emacs-lisp +(setq prism-num-faces 8) + +(prism-set-colors + :desaturations '(0) ; do not change---may lower the contrast ratio + :lightens '(0) ; same + :colors (modus-themes-with-colors + (list blue + magenta + magenta-alt-other + cyan-alt-other + fg-main + blue-alt + red-alt-other + cyan))) +#+end_src + +And this is with 4 colors, which produces results that are the closest +to the themes' default aesthetic: + +#+begin_src emacs-lisp +(setq prism-num-faces 4) + +(prism-set-colors + :desaturations '(0) ; do not change---may lower the contrast ratio + :lightens '(0) ; same + :colors (modus-themes-with-colors + (list blue + magenta + magenta-alt-other + green-alt))) +#+end_src + +If you need to apply desaturation and lightening, you can use what the +{{{file(prism.el)}}} documentation recommends, like this (adapting to the +examples with the 4, 8, 16 colors): + +#+begin_src emacs-lisp +(prism-set-colors + :desaturations (cl-loop for i from 0 below 16 collect (* i 2.5)) + :lightens (cl-loop for i from 0 below 16 collect (* i 2.5)) + :colors (modus-themes-with-colors + (list fg-main + cyan-alt-other + magenta-alt-other + magenta))) +#+end_src + +** Note on god-mode.el +:properties: +:alt_title: Note for god-mode +:custom_id: h:4da1d515-3e05-47ef-9e45-8251fc7e986a +:end: + +The ~god-mode~ library does not provide faces that could be configured by +the Modus themes. Users who would like to get some visual feedback on +the status of {{{kbd(M-x god-mode)}}} are instead encouraged by upstream to +set up their own configurations, such as by changing the ~mode-line~ face +([[#h:f4651d55-8c07-46aa-b52b-bed1e53463bb][Advanced customization]]). This is an adaptation of the approach +followed in the upstream README: + +#+begin_src emacs-lisp +(defun my-god-mode-update-mode-line () + "Make `mode-line' blue if God local mode is active." + (modus-themes-with-colors + (if god-local-mode + (set-face-attribute 'mode-line nil + :foreground blue-active + :background bg-active-accent + :box blue) + (set-face-attribute 'mode-line nil + :foreground fg-active + :background bg-active + :box fg-alt)))) + +(add-hook 'post-command-hook 'my-god-mode-update-mode-line) +#+end_src + +We employ the ~modus-themes-with-colors~ which provides access to color +variables defined by the active theme. Its use is covered elsewhere in +this manual ([[#h:51ba3547-b8c8-40d6-ba5a-4586477fd4ae][Face specs at scale using the themes' palette]]). As for the +attributes that can be passed to each face, start by consulting the +documentation string of ~set-face-attribute~. + +** Note on company-mode overlay pop-up +:properties: +:custom_id: h:20cef8c4-d11f-4053-8b2c-2872925780b1 +:end: + +By default, the ~company-mode~ pop-up that lists completion candidates is +drawn using an overlay. This creates alignment issues every time it is +placed above a piece of text that has a different height than the +default. + +The solution recommended by the project's maintainer is to use an +alternative front-end for drawing the pop-up which draws child frames +instead of overlays.[fn:: +https://github.com/company-mode/company-mode/issues/1010][fn:: +https://github.com/tumashu/company-posframe/] + +** Note on ERC escaped color sequences +:properties: +:custom_id: h:98bdf319-1e32-4469-8a01-771200fba65c +:end: + +The built-in IRC client ~erc~ has the ability to colorise any text using +escape sequences that start with =^C= (inserted with {{{kbd(C-q C-c)}}}) and are +followed by a number for the foreground and background.[fn:: This page +explains the basics, though it is not specific to Emacs: +https://www.mirc.com/colors.html] Possible numbers are 0-15, with the +first entry being the foreground and the second the background, +separated by a comma. Like this =^C1,6=. The minimum setup is this: + +#+begin_src emacs-lisp +(add-to-list 'erc-modules 'irccontrols) +(setq erc-interpret-controls-p t + erc-interpret-mirc-color t) +#+end_src + +As this allows users the chance to make arbitrary combinations, it is +impossible to guarantee a consistently high contrast ratio. All we can +we do is provide guidance on the combinations that satisfy the +accessibility standard of the themes: + ++ Modus Operandi :: Use foreground color 1 for all backgrounds from + 2-15. Like so: {{{kbd(C-q C-c1,N)}}} where =N= is the background. + ++ Modus Vivendi :: Use foreground color 0 for all backgrounds from + 2-13. Use foreground =1= for backgrounds 14, 15. + +Colors 0 and 1 are white and black respectively. So combine them +together, if you must. + +** Note on powerline or spaceline +:properties: +:custom_id: h:9130a8ba-d8e3-41be-a58b-3cb1eb7b6d17 +:end: + +Both Powerline and Spaceline package users will likely need to use the +command ~powerline-reset~ whenever they make changes to their themes +and/or mode line setup. + +** Note on SHR colors +:properties: +:custom_id: h:4cc767dc-ffef-4c5c-9f10-82eb7b8921bf +:end: + +Emacs' HTML rendering library ({{{file(shr.el)}}}) may need explicit +configuration to respect the theme's colors instead of whatever +specifications the webpage provides. + +Consult the doc string of ~shr-use-colors~. + +** Note on SHR fonts +:properties: +:custom_id: h:e6c5451f-6763-4be7-8fdb-b4706a422a4c +:end: +#+cindex: Fonts in EWW, Elfeed, Ement, and SHR + +By default, packages that build on top of the Simple HTML Remember (=shr=) +use proportionately spaced fonts. This is controlled by the user option +~shr-use-fonts~, which is set to non-nil by default. To use the standard +font instead, set that variable to nil. + +[[#h:defcf4fc-8fa8-4c29-b12e-7119582cc929][Font configurations for Org and others]]. + +Packages affected by this are: + ++ elfeed ++ ement ++ eww + +This is a non-exhaustive list. + +** Note on Ement colors and fonts +:properties: +:custom_id: h:8e636056-356c-4ca7-bc78-ebe61031f585 +:end: + +The =ement.el= library by Adam Porter (also known as "alphapapa") defaults +to a method of colorizing usernames in a rainbow style. This is +controlled by the user option ~ement-room-prism~ and can be disabled with: + +#+begin_src emacs-lisp +(setq ement-room-prism nil) +#+end_src + +The contrast ratio of these colors is governed by another user option: +~ement-room-prism-minimum-contrast~. By default, it is set to 6 which is +slightly below our nominal target. Try this instead: + +#+begin_src emacs-lisp +(setq ement-room-prism-minimum-contrast 7) +#+end_src + +With regard to fonts, Ement depends on =shr= ([[#h:e6c5451f-6763-4be7-8fdb-b4706a422a4c][Note on SHR fonts]]). + +Since we are here, here is an excerpt from Ement's source code: + +#+begin_src emacs-lisp +(defcustom ement-room-prism-minimum-contrast 6 + "Attempt to enforce this minimum contrast ratio for user faces. +This should be a reasonable number from, e.g. 0-7 or so." + ;; Prot would almost approve of this default. :) I would go all the way + ;; to 7, but 6 already significantly dilutes the colors in some cases. + :type 'number) +#+end_src + +Yes, I do approve of that default. Even a 4.5 (the WCAG AA rating) +would be a good baseline for many themes and/or user configurations. +Our target is the highest of the sort, though we do not demand that +everyone conforms with it. + +** Note on Helm grep +:properties: +:custom_id: h:d28879a2-8e4b-4525-986e-14c0f873d229 +:end: + +There is one face from the Helm package that is meant to highlight the +matches of a grep or grep-like command (=ag= or =ripgrep=). It is +~helm-grep-match~. However, this face can only apply when the user does +not pass =--color=always= as a command-line option for their command. + +Here is the docstring for that face, which is defined in the +{{{file(helm-grep.el)}}} library (you can always visit the source code with +{{{kbd(M-x find-library)}}}). + +#+begin_quote +Face used to highlight grep matches. Have no effect when grep backend +use "--color=" +#+end_quote + +The user must either remove =--color= from the flags passed to the grep +function, or explicitly use =--color=never= (or equivalent). Helm +provides user-facing customization options for controlling the grep +function's parameters, such as ~helm-grep-default-command~ and +~helm-grep-git-grep-command~. + +When =--color=always= is in effect, the grep output will use red text in +bold letter forms to present the matching part in the list of +candidates. That style still meets the contrast ratio target of >= 7:1 +(accessibility standard WCAG AAA), because it draws the reference to +ANSI color number 1 (red) from the already-supported array of +~ansi-color-names-vector~. + +** Note on pdf-tools link hints +:properties: +:custom_id: h:2659d13e-b1a5-416c-9a89-7c3ce3a76574 +:end: + +Hints are drawn by [[https://imagemagick.org/][ImageMagick]], not Emacs, i.e., ImageMagick doesn't +know about the hint face unless you tell ImageMagick about it. By +default, only the foreground and background color attributes are +passed. The below snippet adds to those the various font attributes. As +it queries various faces, specifically ~pdf-links-read-link~ and the faces +it inherits, it needs to be added to your initialization file after +you've customized any faces. + +#+begin_src emacs-lisp +(use-package pdf-links + :config + (let ((spec + (apply #'append + (mapcar + (lambda (name) + (list name + (face-attribute 'pdf-links-read-link + name nil 'default))) + '(:family :width :weight :slant))))) + (setq pdf-links-read-link-convert-commands + `("-density" "96" + "-family" ,(plist-get spec :family) + "-stretch" ,(let* ((width (plist-get spec :width)) + (name (symbol-name width))) + (replace-regexp-in-string "-" "" + (capitalize name))) + "-weight" ,(pcase (plist-get spec :weight) + ('ultra-light "Thin") + ('extra-light "ExtraLight") + ('light "Light") + ('semi-bold "SemiBold") + ('bold "Bold") + ('extra-bold "ExtraBold") + ('ultra-bold "Black") + (_weight "Normal")) + "-style" ,(pcase (plist-get spec :slant) + ('italic "Italic") + ('oblique "Oblique") + (_slant "Normal")) + "-pointsize" "%P" + "-undercolor" "%f" + "-fill" "%b" + "-draw" "text %X,%Y '%c'")))) +#+end_src + +** Note on the Notmuch logo +:properties: +:custom_id: h:636af312-54a5-4918-84a6-0698e85a3c6d +:end: + +By default, the "hello" buffer of Notmuch includes a header with the +programs' logo and a couple of buttons. The logo has the effect of +enlarging the height of the line, which negatively impacts the shape of +those buttons. Disabling the logo fixes the problem: + +#+begin_src emacs-lisp +(setq notmuch-show-logo nil) +#+end_src + +* Frequently Asked Questions +:properties: +:custom_id: h:b3384767-30d3-4484-ba7f-081729f03a47 +:end: +#+cindex: Frequently Asked Questions + +In this section we provide answers related to some aspects of the Modus +themes' design and application. + +** Is the contrast ratio about adjacent colors? +:properties: +:custom_id: h:5ce7ae2e-9348-4e55-b4cf-9302345b1826 +:end: +#+cindex: Contrast between adjacent colors + +The minimum contrast ratio in relative luminance that the themes conform +with always refers to any given combination of background and foreground +colors. If we have some blue colored text next to a magenta one, both +against a white background, we do not mean to imply that blue:magenta is +7:1 in terms of relative luminance. Rather, we state that blue:white +and magenta:white each are 7:1 or higher. + +The point of reference is always the background. Because colors have +about the same minimum distance in luminance from their backdrop, they +necessarily are fairly close to each other in this measure. A possible +blue:magenta combination would naturally be around 1:1 in contrast of +the sort here considered. + +To differentiate between sequential colors, we rely on hueness by +mapping contrasting hues to adjacent constructs, while avoiding +exaggerations. A blue next to a magenta can be told apart regardless of +their respective contrast ratio against their common background. +Exceptions would be tiny characters in arguably not so realistic cases, +such as two dots drawn side-by-side which for some reason would need to +be colored differently. They would still be legible though, which is +the primary objective of the Modus themes. + +** What does it mean to avoid exaggerations? +:properties: +:custom_id: h:44284e1f-fab8-4c4f-92f0-544728a7c91e +:end: +#+cindex: Avoiding exaggerations in design + +The Modus themes are designed with restraint, so that their default +looks do not overdo it with the application of color. + +[[#h:bf1c82f2-46c7-4eb2-ad00-dd11fdd8b53f][Customization Options]]. + +This is the non-quantifiable aspect of the themes' design: the artistic +part, if you will. There are a lot of cases where color can be used +inconsiderately, without accounting for layout, typographic, or other +properties of the presentation. For example, two headings with distinct +markers, such as leading asterisks in Org buffers, do not have to have +highly contrasting hues between them in order to be told apart: the +added element of contrast in hueness does not contribute significantly +more to the distinction between the headings than colors whose hues are +relatively closer to each other in the color space. + +Exaggerations can be hard to anticipate or identify. Multiple shades of +blue and magenta in the same context may not seem optimal: one might +think that it would be better to use highly contrasting hues to ensure +that all colors stand out, such as by placing blue next to yellow, next +to magenta, and green. That would, however, be a case of design for its +own sake; a case where color is being applied without consideration of +its end results in the given context. Too many contrasting hues in +close proximity force an erratic rate to how the eye jumps from one +piece of text to the next. Whereas multiple shades of, say, blue and +magenta can suffice to tell things apart and avoid excess coloration: a +harmonious rhythm. + +** Why are colors mostly variants of blue, magenta, cyan? +:properties: +:custom_id: h:0b26cb47-9733-4cb1-87d9-50850cb0386e +:end: +#+cindex: Innate color qualities of the palette + +Due to the innate properties of color, some options are better than +others for the accessibility purposes of the themes, the stylistic +consistency between ~modus-operandi~ and ~modus-vivendi~, and the avoidance +of exaggerations in design. + +[[#h:44284e1f-fab8-4c4f-92f0-544728a7c91e][What does it mean to avoid exaggerations?]] + +What we describe as color is a function of three distinct channels of +light: red, green, blue. In hexadecimal RGB notation, a color value is +read as three pairs of red, green, and blue light: =#RRGGBB=. Of those +three, the most luminant is green, while the least luminant is blue. + +The three basic colors represent each of the channels of light. They +can be intermixed to give us six colors: red and green derive yellow, +green and blue make cyan, red and blue turn into magenta. + +We can test the luminance of each of those against white and black to +get a sense of how not all colors are equally good for accessibility +(white is =#ffffff=, which means that all three light channels are fully +luminated, while black is =#000000= meaning that no light is present +(notwithstanding display technology)). + +#+begin_example +| Name | | #ffffff | #000000 | +|---------+---------+---------+---------| +| red | #ff0000 | 4.00 | 5.25 | +| yellow | #ffff00 | 1.07 | 19.56 | +| green | #00ff00 | 1.37 | 15.30 | +| cyan | #00ffff | 1.25 | 16.75 | +| blue | #0000ff | 8.59 | 2.44 | +| magenta | #ff00ff | 3.14 | 6.70 | +#+end_example + +[[#h:02e25930-e71a-493d-828a-8907fc80f874][Measure color contrast]]. + +By reading this table we learn that every color that has a high level of +green light (green, yellow, cyan) is virtually unreadable against a +white background and, conversely, can be easily read against black. + +We can then infer that red and blue, in different combinations, with +green acting as calibrator for luminance, will give us fairly moderate +colors that pass the 7:1 target. Blue with a bit of green produce +appropriate variants of cyan. Similarly, blue combined with some red +and hints of green give us suitable shades of purple. + +Due to the need of maintaining some difference in hueness between +adjacent colors, it is not possible to make red, green, and yellow the +main colors, because blue cannot be used to control their luminance and, +thus the relevant space will shrink considerably. + +[[#h:5ce7ae2e-9348-4e55-b4cf-9302345b1826][Is the contrast ratio about adjacent colors?]] + +This phenomenon is best illustrated by the following table that measures +the relative luminance of shades of red, yellow, magenta against white: + +#+begin_example +| | #ffffff | +|---------+---------| +| #990000 | 8.92 | +| #995500 | 5.75 | +| #990099 | 7.46 | +#+end_example + +We notice that equal values of red and blue light in =#990099= (magenta +shade) do not lead to a considerable change in luminance compared with +=#990000= (red variant). Whereas less amount of green light in =#995500= +leads to a major drop in luminance relative to white. It follows that +using the green channel of light to calibrate the luminance of colors is +more effective than trying to do the same with either red or blue (the +latter is the least effective in that regard). + +When we need to work with several colors, it is always better to have +sufficient manoeuvring space, especially since we cannot pick arbitrary +colors but only those that satisfy the accessibility objectives of the +themes. + +As for why we do not mostly use green, yellow, cyan for the dark theme, +it is because those colors are far more luminant than their counterparts +on the other side of the spectrum, so to ensure that they all have about +the same contrast ratios we would have to alter their hueness +considerably. In short, the effect would not be optimal as it would +lead to exaggerations. Plus, it would make ~modus-vivendi~ look +completely different than ~modus-operandi~, to the effect that the two +could not be properly considered part of the same project. + +** What is the best setup for legibility? +:properties: +:custom_id: h:f60cc2ae-129d-47c0-9849-4f6bbd87d8be +:end: +#+cindex: General setup for readability + +The Modus themes can be conceptually simplified as combinations of color +values that account for relative luminance and inner harmony. Those +qualities do not guarantee that every end-user will have the same +experience, due to differences between people, but also because of +variances in hardware capabilities and configurations. For the purposes +of this document, we may only provide suggestions pertaining to the +latter case. + +~modus-operandi~ is best used outdoors or in a room that either gets +direct sunlight or has plenty of light. Whereas ~modus-vivendi~ works +better when there is not a lot of sunshine or the room has a source of +light that is preferably a faint and/or warm one. It is possible to use +~modus-operandi~ at night and ~modus-vivendi~ during the day, though that +will depend on several variables, such as one's overall perception of +color, the paint on the walls and how that contributes to the impression +of lightness in the room, the sense of space within the eye's peripheral +vision, hardware specifications, and environmental factors. + +In general, an additional source of light other than that of the monitor +can help reduce eye strain: the eyes are more relaxed when they do not +have to focus on one point to gather light. + +The monitor's display settings must be accounted for. Gamma values, in +particular, need to be calibrated to neither amplify nor distort the +perception of black. Same principle for sharpness, brightness, and +contrast as determined by the hardware, which all have an effect on how +text is read on the screen. + +There are software level methods on offer, such as the XrandR utility +for the X Window System (X.org), which can make gamma corrections for +each of the three channels of light (red, green, blue). For example: + +: xrandr --output LVDS1 --brightness 1.0 --gamma 0.76:0.75:0.68 + +Typography is another variable. Some font families are blurry at small +point sizes. Others may have a regular weight that is lighter (thiner) +than that of their peers which may, under certain circumstances, cause a +halo effect around each glyph. + +The gist is that legibility cannot be fully solved at the theme level. +The color combinations may have been optimized for accessibility, though +the remaining contributing factors in each case need to be considered in +full. + +** Are these color schemes? +:properties: +:custom_id: h:a956dbd3-8fd2-4f5d-8b01-5f881268cf2b +:end: +#+cindex: Themes, not color schemes + +No, the Modus themes are not color schemes. + +A color scheme is a collection of colors. A good color scheme is a +combination of colors with an inner logic or abstract structure. + +A theme is a set of patterns that are applied across different contexts. +A good theme is one that does so with consistency, though not +uniformity. + +In practical terms, a color scheme is what one uses when, for example, +they edit the first sixteen escape sequences of a terminal emulator to +the hues of their preference. The terminal offers the option to choose, +say, the exact value of what counts as "red", but does not provide the +means to control where that is mapped to and whether it should also have +other qualities such as a bold weight for the underlying text or an +added background color. In contradistinction, Emacs uses constructs +known as "faces" which allow the user/developer to specify where a given +color will be used and whether it should be accompanied by other +typographic or stylistic attributes. + +By configuring the multitude of faces on offer we thus control both +which colors are applied and how they appear in their context. When a +package wants to render each instance of "foo" with the "bar" face, it +is not requesting a specific color, which makes things considerably more +flexible as we can treat "bar" in its own right without necessarily +having to use some color value that we hardcoded somewhere. + +Which brings us to the distinction between consistency and uniformity +where our goal is always the former: we want things to look similar +across all interfaces, but we must never force a visual identity where +that runs contrary to the functionality of the given interface. For +instance, all links are underlined by default yet there are cases such +as when viewing listings of emails in Gnus (and Mu4e, Notmuch) where (i) +it is already understood that one must follow the indicator or headline +to view its contents and (ii) underlining everything would make the +interface virtually unusable. + +[[#h:5808be52-361a-4d18-88fd-90129d206f9b][Option for links]]. + +Again, one must exercise judgement in order to avoid discrimination, +where "discrimination" refers to: + ++ The treatment of substantially different magnitudes as if they were of + the same class. ++ Or the treatment of the same class of magnitudes as if they were of a + different class. + +(To treat similar things differently; to treat dissimilar things alike.) + +If, in other words, one was to enforce uniformity without accounting for +the particular requirements of each case---the contextual demands for +usability beyond matters of color---they would be making a +not-so-obvious error of treating different cases as if they were the +same. + +The Modus themes prioritise "thematic consistency" over abstract harmony +or regularity among their applicable colors. In concrete terms, we do +not claim that, say, our yellows are the best complements for our blues +because we generally avoid using complementary colors side-by-side, so +it is wrong to optimise for a decontextualised blue+yellow combination. +Not to imply that our colors do not work well together because they do, +just to clarify that consistency of context is what themes must strive +for, and that requires widening the scope of the design beyond the +particularities of a color scheme. + +Long story short: color schemes and themes have different requirements. +Please do not conflate the two. + +** Port the Modus themes to other platforms? +:properties: +:custom_id: h:7156b949-917d-488e-9a72-59f70d80729c +:end: +#+cindex: Porting the themes to other editors + +There is no plan to port the themes to other platforms or text editors. +I (Protesilaos) only use GNU Emacs and thus cannot maintain code that +targets software I am either not familiar with or am not using on a +daily basis. + +While it is possible to produce a simulacrum based on a given template, +doing so would run contrary to how this project is maintained where +details matter greatly. + +Each program has its own requirements so it won't always be +possible---or indeed desirable---to have 1:1 correspondence between what +applies to Emacs and what should be done elsewhere. No port should ever +strive to be a faithful copy of the Emacs implementation, as no other +program is an Emacs equivalent, but instead try to follow the spirit of +the design. For example, some of the customization options accept a +list as their value, or an alist, which may not be possible to reproduce +on other platforms. + +[[#h:bf1c82f2-46c7-4eb2-ad00-dd11fdd8b53f][Customization options]]. + +In other words, if something must be done differently on a certain +editor then that is acceptable so long as (i) the accessibility +standards are not compromised and (ii) the overall character of the +themes remains consistent. + +The former criterion should be crystal clear as it pertains to the +scientific foundations of the themes: high legibility and taking care of +the needs of users with red-green color deficiency (deuteranopia) by +avoiding red+green color coding paradigms and/or by providing red+blue +variants. + +The latter criterion is the "je ne sais quoi" of the artistic aspect of +the themes, which is partially fleshed out in this manual. + +[[#h:b3384767-30d3-4484-ba7f-081729f03a47][Frequently Asked Questions]]. + +With regard to the artistic aspect (where "art" qua skill may amount to +an imprecise science), there is no hard-and-fast rule in effect as it +requires one to exercise discretion and make decisions based on +context-dependent information or constraints. As is true with most +things in life, when in doubt, do not cling on to the letter of the law +but try to understand its spirit. + +For a trivial example: the curly underline that Emacs draws for spelling +errors is thinner than, e.g., what a graphical web browser has, so if I +was to design for an editor than has a thicker curly underline I would +make the applicable colors less intense to counterbalance the +typographic intensity of the added thickness. + +With those granted, if anyone is willing to develop a port of the +themes, they are welcome to contact me and I will do my best to help +them in their efforts. + +* Contributing +:properties: +:custom_id: h:9c3cd842-14b7-44d7-84b2-a5c8bc3fc3b1 +:end: + +This section documents the canonical sources of the themes and the ways +in which you can contribute to their ongoing development. + +** Sources of the themes +:properties: +:custom_id: h:89504f1c-c9a1-4bd9-ab39-78fd0eddb47c +:end: +#+cindex: Sources of the themes + +The ~modus-operandi~ and ~modus-vivendi~ themes are built into Emacs 28. + +The source code of the themes is [[https://git.sr.ht/~protesilaos/modus-themes][available on SourceHut]]. Or check the +[[https://gitlab.com/protesilaos/modus-themes/][GitLab mirror (former main source)]] and the [[https://github.com/protesilaos/modus-themes/][GitHub mirror]]. + +An HTML version of this manual is provided as an extension of the +[[https://protesilaos.com/emacs/modus-themes/][author's personal website]] (does not rely on any non-free code). + +** Issues you can help with +:properties: +:custom_id: h:6536c8d5-3f98-43ab-a787-b94120e735e8 +:end: +#+cindex: Contributing + +#+findex: modus-themes-report-bug +A few tasks you can help with by sending an email to the general +[[https://lists.sr.ht/~protesilaos/modus-themes][modus-themes public mailing list]] (or use the command +~modus-themes-report-bug~). + ++ Suggest refinements to packages that are covered. ++ Report packages not covered thus far. ++ Report bugs, inconsistencies, shortcomings. ++ Help expand the documentation of covered-but-not-styled packages. ++ Suggest refinements to the color palette. ++ Help expand this document or any other piece of documentation. ++ Send patches for code refinements (if you need, ask me for help with + Git---we all start out as beginners). + +[[#h:111773e2-f26f-4b68-8c4f-9794ca6b9633][Patches require copyright assignment to the FSF]]. + +It is preferable that your feedback includes some screenshots, GIFs, or +short videos, as well as further instructions to reproduce a given +setup. Though this is not a requirement. + +#+findex: modus-themes-version +Also consider mentioning the version of the themes you are using, such +as by invoking the command ~modus-themes-version~. + +Whatever you do, bear in mind the overarching objective of the Modus +themes: to keep a contrast ratio that is greater or equal to 7:1 between +background and foreground colors. If a compromise is ever necessary +between aesthetics and accessibility, it shall always be made in the +interest of the latter. + +** Patches require copyright assignment to the FSF +:properties: +:custom_id: h:111773e2-f26f-4b68-8c4f-9794ca6b9633 +:end: + +Code contributions are most welcome. For any major edit (more than 15 +lines, or so, in aggregate per person), you need to make a copyright +assignment to the Free Software Foundation. This is necessary because +the themes are part of the upstream Emacs distribution: the FSF must at +all times be in a position to enforce the GNU General Public License. + +Copyright assignment is a simple process. Check the request form below +(please adapt it accordingly). You must write an email to the address +mentioned in the form and then wait for the FSF to send you a legal +agreement. Sign the document and file it back to them. This could all +happen via email and take about a week. You are encouraged to go +through this process. You only need to do it once. It will allow you +to make contributions to Emacs in general. + +#+begin_example text +Please email the following information to assign@gnu.org, and we +will send you the assignment form for your past and future changes. + +Please use your full legal name (in ASCII characters) as the subject +line of the message. + +REQUEST: SEND FORM FOR PAST AND FUTURE CHANGES + +[What is the name of the program or package you're contributing to?] + +GNU Emacs + +[Did you copy any files or text written by someone else in these changes? +Even if that material is free software, we need to know about it.] + +Copied a few snippets from the same files I edited. Their author, +Protesilaos Stavrou, has already assigned copyright to the Free Software +Foundation. + +[Do you have an employer who might have a basis to claim to own +your changes? Do you attend a school which might make such a claim?] + + +[For the copyright registration, what country are you a citizen of?] + + +[What year were you born?] + + +[Please write your email address here.] + + +[Please write your postal address here.] + + + + + +[Which files have you changed so far, and which new files have you written +so far?] + +#+end_example + +* Acknowledgements +:properties: +:custom_id: h:95c3da23-217f-404e-b5f3-56c75760ebcf +:end: +#+cindex: Contributors + +The Modus themes are a collective effort. Every bit of work matters. + ++ Author/maintainer :: Protesilaos Stavrou. + ++ Contributions to code or documentation :: Alex Griffin, Anders + Johansson, Basil L.{{{space()}}} Contovounesios, Björn Lindström, + Carlo Zancanaro, Christian Tietze, Daniel Mendler, Eli Zaretskii, + Fritz Grabo, Illia Ostapyshyn, Kévin Le Gouguec, Kostadin Ninev, + Madhavan Krishnan, Manuel Giraud, Markus Beppler, Matthew Stevenson, + Mauro Aranda, Nicolas De Jaeghere, Paul David, Philip Kaludercic, + Pierre Téchoueyres, Rudolf Adamkovič, Stephen Gildea, Shreyas Ragavan, + Stefan Kangas, Utkarsh Singh, Vincent Murphy, Xinglu Chen, Yuanchen + Xie. + ++ Ideas and user feedback :: Aaron Jensen, Adam Porter, Adam Spiers, + Adrian Manea, Alex Griffin, Alex Koen, Alex Peitsinis, Alexey Shmalko, + Alok Singh, Anders Johansson, André Alexandre Gomes, Andrew Tropin, + Antonio Hernández Blas, Arif Rezai, Augusto Stoffel, Basil + L.{{{space()}}} Contovounesios, Burgess Chang, Christian Tietze, + Christopher Dimech, Christopher League, Damien Cassou, Daniel Mendler, + Dario Gjorgjevski, David Edmondson, Davor Rotim, Divan Santana, Eliraz + Kedmi, Emanuele Michele Alberto Monterosso, Farasha Euker, Feng Shu, + Gautier Ponsinet, Gerry Agbobada, Gianluca Recchia, Gonçalo Marrafa, + Guilherme Semente, Gustavo Barros, Hörmetjan Yiltiz, Ilja Kocken, Iris + Garcia, Ivan Popovych, Jeremy Friesen, Jerry Zhang, Johannes Grødem, + John Haman, Jonas Collberg, Jorge Morais, Joshua O'Connor, Julio + C. Villasante, Kenta Usami, Kevin Fleming, Kévin Le Gouguec, Kostadin + Ninev, Len Trigg, Lennart C. Karssen, Magne Hov, Manuel Uberti, Mark + Bestley, Mark Burton, Markus Beppler, Matt Armstrong, Mauro Aranda, + Maxime Tréca, Michael Goldenberg, Morgan Smith, Morgan Willcock, + Murilo Pereira, Nicky van Foreest, Nicolas De Jaeghere, Paul Poloskov, + Pengji Zhang, Pete Kazmier, Peter Wu, Philip Kaludercic, Pierre + Téchoueyres, Przemysław Kryger, Robert Hepple, Roman Rudakov, Ryan + Phillips, Rytis Paškauskas, Rudolf Adamkovič, Sam Kleinman, Samuel + Culpepper, Saša Janiška, Shreyas Ragavan, Simon Pugnet, Tassilo Horn, + Thibaut Verron, Thomas Heartman, Togan Muftuoglu, Tony Zorman, Trey + Merkley, Tomasz Hołubowicz, Toon Claes, Uri Sharf, Utkarsh Singh, + Vincent Foley. As well as users: Ben, CsBigDataHub1, Emacs Contrib, + Eugene, Fourchaux, Fredrik, Moesasji, Nick, Summer Emacs, TheBlob42, + Trey, bepolymathe, bit9tream, derek-upham, doolio, fleimgruber, + gitrj95, iSeeU, jixiuf, okamsn, pRot0ta1p. + ++ Packaging :: Basil L.{{{space()}}} Contovounesios, Eli Zaretskii, + Glenn Morris, Mauro Aranda, Richard Stallman, Stefan Kangas (core + Emacs), Stefan Monnier (GNU Elpa), André Alexandre Gomes, Andrew + Tropin, Dimakakos Dimos, Morgan Smith, Nicolas Goaziou (Guix), Dhavan + Vaidya (Debian). + ++ Inspiration for certain features :: Bozhidar Batsov (zenburn-theme), + Fabrice Niessen (leuven-theme). + +Special thanks (from A-Z) to Daniel Mendler, Gustavo Barros, Manuel +Uberti, Nicolas De Jaeghere, and Omar Antolín Camarena for their long +time contributions and insightful commentary on key aspects of the +themes' design and/or aspects of their functionality. + +All errors are my own. + +* Other notes about the project +:properties: +:custom_id: h:13752581-4378-478c-af17-165b6e76bc1b +:end: +#+cindex: Development notes + +If you are curious about the principles that govern the development of +this project read the essay [[https://protesilaos.com/codelog/2020-03-17-design-modus-themes-emacs/][On the design of the Modus themes]] +(2020-03-17). + +Here are some more publications for those interested in the kind of work +that goes into this project (sometimes the commits also include details +of this sort): + ++ [[https://protesilaos.com/codelog/2020-05-10-modus-operandi-palette-review/][Modus Operandi theme subtle palette review]] (2020-05-10) ++ [[https://protesilaos.com/codelog/2020-06-13-modus-vivendi-palette-review/][Modus Vivendi theme subtle palette review]] (2020-06-13) ++ [[https://protesilaos.com/codelog/2020-07-04-modus-themes-faint-colours/][Modus themes: new "faint syntax" option]] (2020-07-04) ++ [[https://protesilaos.com/codelog/2020-07-08-modus-themes-nuanced-colours/][Modus themes: major review of "nuanced" colours]] (2020-07-08) ++ [[https://protesilaos.com/codelog/2020-09-14-modus-themes-review-blues/][Modus themes: review of blue colours]] (2020-09-14) ++ [[https://protesilaos.com/codelog/2020-12-27-modus-themes-review-rainbow-delimiters/][Modus themes: review rainbow-delimiters faces]] (2020-12-27) ++ [[https://protesilaos.com/codelog/2021-01-11-modus-themes-review-select-faint-colours/][Modus themes: review of select "faint" colours]] (2021-01-11) ++ [[https://protesilaos.com/codelog/2021-02-25-modus-themes-diffs-deuteranopia/][The Modus themes now cover deuteranopia in diffs]] (2021-02-25) ++ [[https://protesilaos.com/codelog/2021-06-02-modus-themes-org-agenda/][Introducing the variable modus-themes-org-agenda]] (2021-06-02) ++ [[https://protesilaos.com/codelog/2022-01-02-review-modus-themes-org-habit-colours/][Modus themes: review of the org-habit graph colours]] (2022-01-02) ++ [[https://protesilaos.com/codelog/2022-01-03-modus-themes-port-faq/][Re: VSCode or Vim ports of the Emacs modus-themes?]] (2022-01-03) ++ [[https://protesilaos.com/codelog/2022-04-20-modus-themes-case-study-avy/][Modus themes: case study on Avy faces and colour combinations]] (2022-04-20) ++ [[https://protesilaos.com/codelog/2022-04-21-modus-themes-colour-theory/][Emacs: colour theory and techniques used in the Modus themes]] (2022-04-21) + +And here are the canonical sources of this project: + ++ Manual :: <https://protesilaos.com/emacs/modus-themes> ++ Change Log :: <https://protesilaos.com/emacs/modus-themes-changelog> ++ Screenshots :: <https://protesilaos.com/emacs/modus-themes-pictures> ++ Git repository :: https://git.sr.ht/~protesilaos/modus-themes ++ Mailing list :: https://lists.sr.ht/~protesilaos/modus-themes + +* GNU Free Documentation License +:properties: +:appendix: t +:custom_id: h:3077c3d2-7f90-4228-8f0a-73124f4026f6 +:end: + +#+texinfo: @include doclicense.texi + +#+begin_export html +<pre> + + GNU Free Documentation License + Version 1.3, 3 November 2008 + + + Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. + <https://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +0. PREAMBLE + +The purpose of this License is to make a manual, textbook, or other +functional and useful document "free" in the sense of freedom: to +assure everyone the effective freedom to copy and redistribute it, +with or without modifying it, either commercially or noncommercially. +Secondarily, this License preserves for the author and publisher a way +to get credit for their work, while not being considered responsible +for modifications made by others. + +This License is a kind of "copyleft", which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + + +1. APPLICABILITY AND DEFINITIONS + +This License applies to any manual or other work, in any medium, that +contains a notice placed by the copyright holder saying it can be +distributed under the terms of this License. Such a notice grants a +world-wide, royalty-free license, unlimited in duration, to use that +work under the conditions stated herein. The "Document", below, +refers to any such manual or work. Any member of the public is a +licensee, and is addressed as "you". You accept the license if you +copy, modify or distribute the work in a way requiring permission +under copyright law. + +A "Modified Version" of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +A "Secondary Section" is a named appendix or a front-matter section of +the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document's overall +subject (or to related matters) and contains nothing that could fall +directly within that overall subject. (Thus, if the Document is in +part a textbook of mathematics, a Secondary Section may not explain +any mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +The "Invariant Sections" are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. If a +section does not fit the above definition of Secondary then it is not +allowed to be designated as Invariant. The Document may contain zero +Invariant Sections. If the Document does not identify any Invariant +Sections then there are none. + +The "Cover Texts" are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. A Front-Cover Text may +be at most 5 words, and a Back-Cover Text may be at most 25 words. + +A "Transparent" copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, that is suitable for revising the document +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup, or absence of markup, has been arranged to thwart +or discourage subsequent modification by readers is not Transparent. +An image format is not Transparent if used for any substantial amount +of text. A copy that is not "Transparent" is called "Opaque". + +Examples of suitable formats for Transparent copies include plain +ASCII without markup, Texinfo input format, LaTeX input format, SGML +or XML using a publicly available DTD, and standard-conforming simple +HTML, PostScript or PDF designed for human modification. Examples of +transparent image formats include PNG, XCF and JPG. Opaque formats +include proprietary formats that can be read and edited only by +proprietary word processors, SGML or XML for which the DTD and/or +processing tools are not generally available, and the +machine-generated HTML, PostScript or PDF produced by some word +processors for output purposes only. + +The "Title Page" means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, "Title Page" means +the text near the most prominent appearance of the work's title, +preceding the beginning of the body of the text. + +The "publisher" means any person or entity that distributes copies of +the Document to the public. + +A section "Entitled XYZ" means a named subunit of the Document whose +title either is precisely XYZ or contains XYZ in parentheses following +text that translates XYZ in another language. (Here XYZ stands for a +specific section name mentioned below, such as "Acknowledgements", +"Dedications", "Endorsements", or "History".) To "Preserve the Title" +of such a section when you modify the Document means that it remains a +section "Entitled XYZ" according to this definition. + +The Document may include Warranty Disclaimers next to the notice which +states that this License applies to the Document. These Warranty +Disclaimers are considered to be included by reference in this +License, but only as regards disclaiming warranties: any other +implication that these Warranty Disclaimers may have is void and has +no effect on the meaning of this License. + +2. VERBATIM COPYING + +You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no +other conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +You may also lend copies, under the same conditions stated above, and +you may publicly display copies. + + +3. COPYING IN QUANTITY + +If you publish printed copies (or copies in media that commonly have +printed covers) of the Document, numbering more than 100, and the +Document's license notice requires Cover Texts, you must enclose the +copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a computer-network location from which the general network-using +public has access to download using public-standard network protocols +a complete Transparent copy of the Document, free of added material. +If you use the latter option, you must take reasonably prudent steps, +when you begin distribution of Opaque copies in quantity, to ensure +that this Transparent copy will remain thus accessible at the stated +location until at least one year after the last time you distribute an +Opaque copy (directly or through your agents or retailers) of that +edition to the public. + +It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to +give them a chance to provide you with an updated version of the +Document. + + +4. MODIFICATIONS + +You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + +A. Use in the Title Page (and on the covers, if any) a title distinct + from that of the Document, and from those of previous versions + (which should, if there were any, be listed in the History section + of the Document). You may use the same title as a previous version + if the original publisher of that version gives permission. +B. List on the Title Page, as authors, one or more persons or entities + responsible for authorship of the modifications in the Modified + Version, together with at least five of the principal authors of the + Document (all of its principal authors, if it has fewer than five), + unless they release you from this requirement. +C. State on the Title page the name of the publisher of the + Modified Version, as the publisher. +D. Preserve all the copyright notices of the Document. +E. Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices. +F. Include, immediately after the copyright notices, a license notice + giving the public permission to use the Modified Version under the + terms of this License, in the form shown in the Addendum below. +G. Preserve in that license notice the full lists of Invariant Sections + and required Cover Texts given in the Document's license notice. +H. Include an unaltered copy of this License. +I. Preserve the section Entitled "History", Preserve its Title, and add + to it an item stating at least the title, year, new authors, and + publisher of the Modified Version as given on the Title Page. If + there is no section Entitled "History" in the Document, create one + stating the title, year, authors, and publisher of the Document as + given on its Title Page, then add an item describing the Modified + Version as stated in the previous sentence. +J. Preserve the network location, if any, given in the Document for + public access to a Transparent copy of the Document, and likewise + the network locations given in the Document for previous versions + it was based on. These may be placed in the "History" section. + You may omit a network location for a work that was published at + least four years before the Document itself, or if the original + publisher of the version it refers to gives permission. +K. For any section Entitled "Acknowledgements" or "Dedications", + Preserve the Title of the section, and preserve in the section all + the substance and tone of each of the contributor acknowledgements + and/or dedications given therein. +L. Preserve all the Invariant Sections of the Document, + unaltered in their text and in their titles. Section numbers + or the equivalent are not considered part of the section titles. +M. Delete any section Entitled "Endorsements". Such a section + may not be included in the Modified Version. +N. Do not retitle any existing section to be Entitled "Endorsements" + or to conflict in title with any Invariant Section. +O. Preserve any Warranty Disclaimers. + +If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version's license notice. +These titles must be distinct from any other section titles. + +You may add a section Entitled "Endorsements", provided it contains +nothing but endorsements of your Modified Version by various +parties--for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. + + +5. COMBINING DOCUMENTS + +You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice, and that you preserve all their Warranty Disclaimers. + +The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +In the combination, you must combine any sections Entitled "History" +in the various original documents, forming one section Entitled +"History"; likewise combine any sections Entitled "Acknowledgements", +and any sections Entitled "Dedications". You must delete all sections +Entitled "Endorsements". + + +6. COLLECTIONS OF DOCUMENTS + +You may make a collection consisting of the Document and other +documents released under this License, and replace the individual +copies of this License in the various documents with a single copy +that is included in the collection, provided that you follow the rules +of this License for verbatim copying of each of the documents in all +other respects. + +You may extract a single document from such a collection, and +distribute it individually under this License, provided you insert a +copy of this License into the extracted document, and follow this +License in all other respects regarding verbatim copying of that +document. + + +7. AGGREGATION WITH INDEPENDENT WORKS + +A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, is called an "aggregate" if the copyright +resulting from the compilation is not used to limit the legal rights +of the compilation's users beyond what the individual works permit. +When the Document is included in an aggregate, this License does not +apply to the other works in the aggregate which are not themselves +derivative works of the Document. + +If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one half of +the entire aggregate, the Document's Cover Texts may be placed on +covers that bracket the Document within the aggregate, or the +electronic equivalent of covers if the Document is in electronic form. +Otherwise they must appear on printed covers that bracket the whole +aggregate. + + +8. TRANSLATION + +Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License, and all the license notices in the +Document, and any Warranty Disclaimers, provided that you also include +the original English version of this License and the original versions +of those notices and disclaimers. In case of a disagreement between +the translation and the original version of this License or a notice +or disclaimer, the original version will prevail. + +If a section in the Document is Entitled "Acknowledgements", +"Dedications", or "History", the requirement (section 4) to Preserve +its Title (section 1) will typically require changing the actual +title. + + +9. TERMINATION + +You may not copy, modify, sublicense, or distribute the Document +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense, or distribute it is void, and +will automatically terminate your rights under this License. + +However, if you cease all violation of this License, then your license +from a particular copyright holder is reinstated (a) provisionally, +unless and until the copyright holder explicitly and finally +terminates your license, and (b) permanently, if the copyright holder +fails to notify you of the violation by some reasonable means prior to +60 days after the cessation. + +Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, receipt of a copy of some or all of the same material does +not give you any rights to use it. + + +10. FUTURE REVISIONS OF THIS LICENSE + +The Free Software Foundation may publish new, revised versions of the +GNU Free Documentation License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in +detail to address new problems or concerns. See +https://www.gnu.org/licenses/. + +Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License "or any later version" applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. If the Document +specifies that a proxy can decide which future versions of this +License can be used, that proxy's public statement of acceptance of a +version permanently authorizes you to choose that version for the +Document. + +11. RELICENSING + +"Massive Multiauthor Collaboration Site" (or "MMC Site") means any +World Wide Web server that publishes copyrightable works and also +provides prominent facilities for anybody to edit those works. A +public wiki that anybody can edit is an example of such a server. A +"Massive Multiauthor Collaboration" (or "MMC") contained in the site +means any set of copyrightable works thus published on the MMC site. + +"CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0 +license published by Creative Commons Corporation, a not-for-profit +corporation with a principal place of business in San Francisco, +California, as well as future copyleft versions of that license +published by that same organization. + +"Incorporate" means to publish or republish a Document, in whole or in +part, as part of another Document. + +An MMC is "eligible for relicensing" if it is licensed under this +License, and if all works that were first published under this License +somewhere other than this MMC, and subsequently incorporated in whole or +in part into the MMC, (1) had no cover texts or invariant sections, and +(2) were thus incorporated prior to November 1, 2008. + +The operator of an MMC Site may republish an MMC contained in the site +under CC-BY-SA on the same site at any time before August 1, 2009, +provided the MMC is eligible for relicensing. + + +ADDENDUM: How to use this License for your documents + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and +license notices just after the title page: + + Copyright (c) YEAR YOUR NAME. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.3 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. + A copy of the license is included in the section entitled "GNU + Free Documentation License". + +If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, +replace the "with...Texts." line with this: + + with the Invariant Sections being LIST THEIR TITLES, with the + Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. + +If you have Invariant Sections without Cover Texts, or some other +combination of the three, merge those two alternatives to suit the +situation. + +If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of +free software license, such as the GNU General Public License, +to permit their use in free software. +</pre> +#+end_export + +#+html: <!-- + +* Indices +:properties: +:custom_id: h:55104b26-8e94-46cf-9975-43ea00316489 +:end: + +** Function index +:properties: +:index: fn +:custom_id: h:6bec5005-529c-4521-ae05-3d990baffb5b +:end: + +** Variable index +:properties: +:index: vr +:custom_id: h:16ad8df6-b015-40a9-9259-03d4f7a23ee4 +:end: + +** Concept index +:properties: +:index: cp +:custom_id: h:6aa7a656-884b-4c39-b759-087e412eec13 +:end: + +#+html: --> |