;;; ef-themes.el --- Colorful and legible themes -*- lexical-binding:t -*- ;; Copyright (C) 2022-2026 Free Software Foundation, Inc. ;; Author: Protesilaos Stavrou ;; Maintainer: Protesilaos Stavrou ;; URL: https://github.com/protesilaos/ef-themes ;; Version: 2.0.1 ;; Package-Requires: ((emacs "28.1") (modus-themes "5.0.0")) ;; Keywords: faces, theme, accessibility ;; This file is NOT part of GNU Emacs. ;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; ;; GNU Emacs is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . ;;; Commentary: ;; ;; The `ef-themes' are a collection of light and dark themes for GNU ;; Emacs whose goal is to provide colorful ("pretty") yet legible ;; options for users who want something with a bit more flair than the ;; `modus-themes' (also designed by me). ;; ;; "Ef" is a Greek word (ευ), commonly used as a prefix to denote ;; something good, nice, and/or easy. For example, eftopia (ευτοπία) ;; is the opposite of dystopia (δυστοπία): a good place as opposed to ;; a bad place. ;; ;; The backronym of the `ef-themes' is: Eclectic Fashion in Themes ;; Hides Exaggerated Markings, Embellishments, and Sparkles. ;;; Code: (require 'modus-themes) (eval-when-compile (require 'subr-x)) ;;;; Basics for building on top of Modus (defgroup ef-themes () "Colorful and legible themes. The `ef-themes' are built on top of the `modus-themes'. To make all the Modus commands that operate on a theme only consider Ef themes, enable the `ef-themes-take-over-modus-themes-mode'. Or, if you prefer to blend Ef and Modus into a single group, enable `modus-themes-include-derivatives-mode'." :group 'faces :group 'modus-themes :link '(info-link "(ef-themes) Top") :link '(info-link "(modus-themes) Top") :prefix "ef-themes-" :tag "Ef Themes") (defconst ef-themes-light-themes '(ef-arbutus ef-cyprus ef-day ef-deuteranopia-light ef-duo-light ef-eagle ef-elea-light ef-frost ef-kassio ef-light ef-maris-light ef-melissa-light ef-orange ef-reverie ef-spring ef-summer ef-trio-light ef-tritanopia-light) "List of symbols with the light Ef themes.") (defconst ef-themes-dark-themes '(ef-autumn ef-bio ef-cherie ef-dark ef-deuteranopia-dark ef-dream ef-duo-dark ef-elea-dark ef-fig ef-maris-dark ef-melissa-dark ef-night ef-owl ef-rosa ef-symbiosis ef-trio-dark ef-tritanopia-dark ef-winter) "List of symbols with the dark Ef themes.") (defvaralias 'ef-themes-collection 'ef-themes-items "Alias for `ef-themes-items'.") (defconst ef-themes-items (append ef-themes-light-themes ef-themes-dark-themes) "Symbols of all the Ef themes.") (defconst ef-themes-custom-faces '( `(magit-section-highlight ((,c :background ,bg-alt))) `(magit-diff-file-heading-highlight ((,c :inherit magit-diff-file-heading :background ,bg-alt))))) (defconst ef-themes-with-properties '((ef-arbutus ef-themes "Legible light pink theme with red and green colors." light ef-arbutus-palette nil ef-arbutus-palette-overrides) (ef-autumn ef-themes "Legible dark brown-black theme with warm colors (red, yellow, green, teal)." dark ef-autumn-palette nil ef-autumn-palette-overrides) (ef-bio ef-themes "Legible dark green-black theme with green, teal, blue, purple colors." dark ef-bio-palette nil ef-bio-palette-overrides) (ef-cherie ef-themes "Legible dark purple-black theme with warm colors (mostly pink, magenta, gold)." dark ef-cherie-palette nil ef-cherie-palette-overrides) (ef-cyprus ef-themes "Legible light ochre theme with green, yellow, teal, red colors." light ef-cyprus-palette nil ef-cyprus-palette-overrides) (ef-dark ef-themes "Legible dark theme with blue, magenta, cyan, purple colors." dark ef-dark-palette nil ef-dark-palette-overrides) (ef-day ef-themes "Legible light sandy theme with warm, varied colors (yellow, red, green, purple)." light ef-day-palette nil ef-day-palette-overrides) (ef-deuteranopia-dark ef-themes "Legible dark theme, optimized for red-green color deficiency." dark ef-deuteranopia-dark-palette nil ef-deuteranopia-dark-palette-overrides) (ef-deuteranopia-light ef-themes "Legible light theme, optimized for red-green color deficiency." light ef-deuteranopia-light-palette nil ef-deuteranopia-light-palette-overrides) (ef-dream ef-themes "Legible dark purple grey theme with gold and nuanced colors." dark ef-dream-palette nil ef-dream-palette-overrides) (ef-duo-dark ef-themes "Legible dark theme with mostly blue and orange colors." dark ef-duo-dark-palette nil ef-duo-dark-palette-overrides) (ef-duo-light ef-themes "Legible light theme with mostly blue and yellow colors." light ef-duo-light-palette nil ef-duo-light-palette-overrides) (ef-eagle ef-themes "Legible light beige theme with brown, red, and desatured colors." light ef-eagle-palette nil ef-eagle-palette-overrides) (ef-elea-dark ef-themes "Legible dark green theme with brown, magenta, and green colors." dark ef-elea-dark-palette nil ef-elea-dark-palette-overrides) (ef-elea-light ef-themes "Legible light green theme with brown, magenta, and green colors." light ef-elea-light-palette nil ef-elea-light-palette-overrides) (ef-fig ef-themes "Legible dark theme with warm green, yellow, and magenta colors." dark ef-fig-palette nil ef-fig-palette-overrides) (ef-frost ef-themes "Legible light cool theme with blue, cyan, teal, purple colors." light ef-frost-palette nil ef-frost-palette-overrides) (ef-kassio ef-themes "Legible light grey theme with blue, red, magenta, and earthly colors." light ef-kassio-palette nil ef-kassio-palette-overrides) (ef-light ef-themes "Legible light theme with blue, magenta, cyan, purple colors." light ef-light-palette nil ef-light-palette-overrides) (ef-maris-dark ef-themes "Legible dark marine theme with blue, cyan, and green colors." dark ef-maris-dark-palette nil ef-maris-dark-palette-overrides) (ef-maris-light ef-themes "Legible light marine theme with blue, cyan, and green colors." light ef-maris-light-palette nil ef-maris-light-palette-overrides) (ef-melissa-dark ef-themes "Legible dark honeybee theme with warm colors (yellow, red, green, cyan)." dark ef-melissa-dark-palette nil ef-melissa-dark-palette-overrides) (ef-melissa-light ef-themes "Legible light honeybee theme with warm colors (yellow, red, green, cyan)." light ef-melissa-light-palette nil ef-melissa-light-palette-overrides) (ef-night ef-themes "Legible dark sky blue theme with mostly green, blue, purple colors." dark ef-night-palette nil ef-night-palette-overrides) (ef-orange ef-themes "Legible light theme with orange, yellow, and green colors." light ef-orange-palette nil ef-orange-palette-overrides) (ef-owl ef-themes "Legible dark grey theme with blue, cyan, magenta and desaturated colors." dark ef-owl-palette nil ef-owl-palette-overrides) (ef-reverie ef-themes "Legible light cream theme with gold and nuanced colors." light ef-reverie-palette nil ef-reverie-palette-overrides) (ef-rosa ef-themes "Legible dark rosewood theme with magenta and green colors." dark ef-rosa-palette nil ef-rosa-palette-overrides) (ef-spring ef-themes "Legible light floral theme with cool, varied colors (green, cyan, red)." light ef-spring-palette nil ef-spring-palette-overrides) (ef-summer ef-themes "Legible light warm pink theme with magenta, purple, gold, cyan colors." light ef-summer-palette nil ef-summer-palette-overrides) (ef-symbiosis ef-themes "Legible dark brown-black theme with blue, green, cyan, gold colors." dark ef-symbiosis-palette nil ef-symbiosis-palette-overrides) (ef-trio-dark ef-themes "Legible dark purple grey theme with magenta, blue, teal colors." dark ef-trio-dark-palette nil ef-trio-dark-palette-overrides) (ef-trio-light ef-themes "Legible light purple grey theme with magenta, blue, and teal colors." light ef-trio-light-palette nil ef-trio-light-palette-overrides) (ef-tritanopia-dark ef-themes "Legible dark theme, optimized for blue-yellow color deficiency." dark ef-tritanopia-dark-palette nil ef-tritanopia-dark-palette-overrides) (ef-tritanopia-light ef-themes "Legible light theme, optimized for blue-yellow color deficiency." light ef-tritanopia-light-palette nil ef-tritanopia-light-palette-overrides) (ef-winter ef-themes "Legible dark purple-black theme with magenta, purple, fawn, teal colors." dark ef-winter-palette nil ef-winter-palette-overrides))) (defvar ef-themes--declared-p nil) (defun ef-themes-declare-themes () "Declare the Ef themes." (unless ef-themes--declared-p (dolist (theme ef-themes-with-properties) (apply #'modus-themes-declare theme) (modus-themes-register (car theme))) (setq ef-themes--declared-p t))) (ef-themes-declare-themes) (defconst ef-themes-palette-common '((fringe unspecified) (property variable) (fg-region unspecified) (bg-diff-context bg-dim) (bg-tab-bar bg-alt) (bg-tab-current bg-main) (bg-tab-other bg-active) (fg-link-symbolic fg-alt) (underline-link border) (underline-link-visited border) (underline-link-symbolic border) (border-mode-line-active border) (bg-mode-line-inactive bg-alt) (fg-mode-line-inactive fg-dim) (border-mode-line-inactive border) (bg-line-number-active unspecified) (fg-line-number-active accent-0) (bg-line-number-inactive unspecified) (bg-prominent-err bg-err) (bg-prominent-warning bg-warning) (bg-prominent-note bg-info) (fg-prominent-err err) (fg-prominent-warning warning) (fg-prominent-note info) (bg-space unspecified) (fg-space border) (bg-active-argument bg-warning) (fg-active-argument warning) (bg-active-value bg-info) (fg-active-value info) (bg-mark-delete bg-err) (fg-mark-delete err) (bg-mark-select bg-info) (fg-mark-select info) (bg-mark-other bg-warning) (fg-mark-other warning) (fg-search-current fg-main) (fg-search-lazy fg-main) (fg-search-static fg-main) (fg-search-replace fg-main) (fg-search-rx-group-0 fg-main) (fg-search-rx-group-1 fg-main) (fg-search-rx-group-2 fg-main) (fg-search-rx-group-3 fg-main) (fg-completion-match-0 accent-0) (fg-completion-match-1 accent-1) (fg-completion-match-2 accent-2) (fg-completion-match-3 accent-3) (fg-heading-0 rainbow-0) (fg-heading-1 rainbow-1) (fg-heading-2 rainbow-2) (fg-heading-3 rainbow-3) (fg-heading-4 rainbow-4) (fg-heading-5 rainbow-5) (fg-heading-6 rainbow-6) (fg-heading-7 rainbow-7) (fg-heading-8 rainbow-8)) "Common palette mappings for the Ef themes.") ;;;; Compatibility with older versions of the Ef themes (defvar ef-themes--aliased-p nil) (defun ef-themes-define-alias (prefix suffix &optional is-function) "Make alias for the Modus themes symbol with PREFIX and SUFFIX. If IS-FUNCTION is non-nil, use the appropriate calls for functions, else assume this is a variable." (let ((our-symbol (intern (format "%s-%s" prefix suffix))) (modus-symbol (intern-soft (format "modus-themes-%s" suffix)))) (when (symbolp modus-symbol) (funcall (if is-function #'defalias #'defvaralias) our-symbol modus-symbol (format "`%s' is an alias for `%s'. Since version 2.0.0, `ef-themes' derive from the `modus-themes'. You can configure the `ef-themes' via the user options of the `modus-themes'. To make all the Modus commands that operate on a theme consider only Ef themes, enable `ef-themes-take-over-modus-themes-mode'. Or, if you prefer to blend Ef and Modus into a single group, enable `modus-themes-include-derivatives-mode' instead. Alternatively, use the commands `ef-themes-rotate', `ef-themes-select', `ef-themes-load-random', `ef-themes-load-random-dark', `ef-themes-load-random-light', `ef-themes-list-colors', `ef-themes-list-colors-current'. They are all designed to only consider Ef themes." our-symbol modus-symbol))))) (defun ef-themes-define-option-aliases () "Define aliases for the user options of the Modus themes." (unless ef-themes--aliased-p (dolist (suffix '( disable-other-themes to-toggle to-rotate after-load-theme-hook post-load-hook italic-constructs bold-constructs variable-pitch-ui mixed-fonts headings completions prompts common-palette-overrides)) (ef-themes-define-alias "ef-themes" suffix)) (setq ef-themes--aliased-p t))) (ef-themes-define-option-aliases) (defalias 'ef-themes-load-theme 'modus-themes-load-theme "Alias for `modus-themes-load-theme'.") (defalias 'ef-themes-with-colors 'modus-themes-with-colors "Alias for `modus-themes-with-colors.") ;;;; Limit the Modus themes to only Ef themes ;;;###autoload (define-minor-mode ef-themes-take-over-modus-themes-mode "When enabled, all Modus themes commands consider only Ef themes. Alternatively, use the commands `ef-themes-rotate', `ef-themes-select', `ef-themes-load-random', `ef-themes-load-random-dark', `ef-themes-load-random-light', `ef-themes-list-colors', `ef-themes-list-colors-current'. They are all designed to only consider Ef themes." :global t :init-value nil) (cl-defmethod modus-themes-get-themes (&context (ef-themes-take-over-modus-themes-mode (eql t))) "Return list of Ef themes, per `ef-themes-take-over-modus-themes-mode'." (if-let* ((themes (modus-themes-get-all-known-themes 'ef-themes)) (sorted-a-z (sort themes #'string-lessp)) (sorted-light-dark (modus-themes-sort sorted-a-z 'light))) sorted-light-dark ef-themes-items)) ;;;; Convenience commands ;;;###autoload (autoload 'ef-themes-toggle "ef-themes") (modus-themes-define-derivative-command ef-themes toggle) ;;;###autoload (autoload 'ef-themes-rotate "ef-themes") (modus-themes-define-derivative-command ef-themes rotate) ;;;###autoload (autoload 'ef-themes-select "ef-themes") (modus-themes-define-derivative-command ef-themes select) ;;;###autoload (autoload 'ef-themes-select-dark "ef-themes") (modus-themes-define-derivative-command ef-themes select-dark) ;;;###autoload (autoload 'ef-themes-select-light "ef-themes") (modus-themes-define-derivative-command ef-themes select-light) ;;;###autoload (autoload 'ef-themes-load-random "ef-themes") (modus-themes-define-derivative-command ef-themes load-random) ;;;###autoload (autoload 'ef-themes-load-random-dark "ef-themes") (modus-themes-define-derivative-command ef-themes load-random-dark) ;;;###autoload (autoload 'ef-themes-load-random-light "ef-themes") (modus-themes-define-derivative-command ef-themes load-random-light) ;;;###autoload (autoload 'ef-themes-list-colors "ef-themes") (modus-themes-define-derivative-command ef-themes list-colors) ;;;###autoload (autoload 'ef-themes-list-colors-current "ef-themes") (modus-themes-define-derivative-command ef-themes list-colors-current) ;;;; Add themes from package to path ;;;###autoload (when load-file-name (let ((dir (file-name-directory load-file-name))) (unless (file-equal-p dir (expand-file-name "themes/" data-directory)) (add-to-list 'custom-theme-load-path dir)))) (provide 'ef-themes) ;;; ef-themes.el ends here