]> git.eshelyaron.com Git - emacs.git/commitdiff
Tag themes with properties
authorPhilip Kaludercic <philipk@posteo.net>
Sat, 17 Sep 2022 18:11:42 +0000 (20:11 +0200)
committerPhilip Kaludercic <philipk@posteo.net>
Sat, 15 Oct 2022 15:22:48 +0000 (17:22 +0200)
* doc/emacs/custom.texi (Custom Themes): Document 'theme-choose-variant'.
* doc/lispref/customize.texi (Custom Themes): Document the new
optional argument to 'deftheme'.
(Autoload): Mention that 'deftheme' is not copied verbatim.
* etc/themes/adwaita-theme.el (adwaita): Add properties.
* etc/themes/deeper-blue-theme.el (deeper-blue): Add properties.
* etc/themes/dichromacy-theme.el (dichromacy): Add properties.
* etc/themes/light-blue-theme.el (light-blue): Add properties.
* etc/themes/manoj-dark-theme.el (manoj-dark): Add properties.
* etc/themes/misterioso-theme.el (misterioso): Add properties.
* etc/themes/tango-dark-theme.el (tango-dark): Add properties.
* etc/themes/tango-theme.el (tango): Add properties.
* etc/themes/tsdh-dark-theme.el (tsdh-dark): Add properties.
* etc/themes/tsdh-light-theme.el (tsdh-light): Add properties.
* etc/themes/wheatgrass-theme.el (wheatgrass): Add properties.
* etc/themes/whiteboard-theme.el (whiteboard): Add properties.
* etc/themes/wombat-theme.el (wombat): Add properties.
* etc/themes/modus-operandi-theme.el: Add properties.
* etc/themes/modus-vivendi-theme.el: Add properties.
* etc/themes/leuven-dark-theme.el (leuven-dark): Add properties.
* etc/themes/leuven-theme.el (leuven): Add properties.
* lisp/custom.el (deftheme): Allow for optional arguments to set the
property list.
(custom-declare-theme): Accept the same optional arguments as 'deftheme'.
(theme-list-variants): Add new function.
(theme-choose-variant): Add new command for switching between members
of a theme family.
(toggle-theme): Add an alias for 'theme-choose-variant'.
* lisp/emacs-lisp/loaddefs-gen.el (loaddefs-generate--make-autoload):
Handle 'defcustom's by extracting the properties.  (Bug#57639)

22 files changed:
doc/emacs/custom.texi
doc/lispref/customize.texi
doc/lispref/loading.texi
etc/themes/adwaita-theme.el
etc/themes/deeper-blue-theme.el
etc/themes/dichromacy-theme.el
etc/themes/leuven-dark-theme.el
etc/themes/leuven-theme.el
etc/themes/light-blue-theme.el
etc/themes/manoj-dark-theme.el
etc/themes/misterioso-theme.el
etc/themes/modus-operandi-theme.el
etc/themes/modus-vivendi-theme.el
etc/themes/tango-dark-theme.el
etc/themes/tango-theme.el
etc/themes/tsdh-dark-theme.el
etc/themes/tsdh-light-theme.el
etc/themes/wheatgrass-theme.el
etc/themes/whiteboard-theme.el
etc/themes/wombat-theme.el
lisp/custom.el
lisp/emacs-lisp/loaddefs-gen.el

index ff7ab83190c682183d0950c981f99f61bfd0822a..f98527bf9a77c1d5390f515c4b087fa2495865f9 100644 (file)
@@ -667,6 +667,16 @@ type @kbd{M-x disable-theme}.
 the @file{*Custom Themes*} buffer; or type @kbd{M-x describe-theme}
 anywhere in Emacs and enter the theme name.
 
+@findex theme-choose-variant
+Some themes have variants (most often just two: light and dark).  You
+can switch to another variant using @kbd{M-x theme-choose-variant}.
+If the currently active theme has only one other variant, it will be
+selected; if there are more variants, the command will prompt you
+which one to switch to.
+
+Note that @code{theme-choose-variant} only works if a single theme
+is active.
+
 @node Creating Custom Themes
 @subsection Creating Custom Themes
 @cindex custom themes, creating
index 6ba35cffffe176cccbacf3d3668d81147315f533..204719e942b71bdcb722a8205bae3ea35d1d9306 100644 (file)
@@ -1428,12 +1428,32 @@ emacs, The GNU Emacs Manual}.)
 be a call to @code{deftheme}, and the last form should be a call to
 @code{provide-theme}.
 
-@defmac deftheme theme &optional doc
+@defmac deftheme theme &optional doc &rest properties
 This macro declares @var{theme} (a symbol) as the name of a Custom
 theme.  The optional argument @var{doc} should be a string describing
 the theme; this is the description shown when the user invokes the
 @code{describe-theme} command or types @kbd{?} in the @samp{*Custom
-Themes*} buffer.
+Themes*} buffer.  The remaining arguments @var{properties} are used
+pass a property list with theme attributes.
+
+The following attributes are supported:
+
+@table @code
+@item :family
+A symbol designating what ``family'' a theme belongs to.  A
+@dfn{family} of themes is a set of similar themes that differ by minor
+aspects, such as face colors that are meant for the light vs dark
+background of the frame.
+@item :kind
+A symbol.  If a theme is enabled and this property has the value
+@code{color-scheme}, then the @code{theme-choose-variant} command will
+look for other available themes that belong to the same family in
+order to switch the themes.  Other values are currently unspecified
+and should not be used.
+@item :background-mode
+A symbol, either @code{light} or @code{dark}.  This attribute is
+currently unused, but should still be specified.
+@end table
 
 Two special theme names are disallowed (using them causes an error):
 @code{user} is a dummy theme that stores the user's direct
index 4e4f12dc324e1626e6b6f56545da23f0bdd29b96..c7fbdac1d76a754fa6773770502b0cac8c1f55c5 100644 (file)
@@ -662,7 +662,7 @@ and @code{define-overloadable-function} (see the commentary in
 and @code{define-global-minor-mode}.
 
 @item Other definition types:
-@code{defcustom}, @code{defgroup}, @code{defclass}
+@code{defcustom}, @code{defgroup}, @code{deftheme}, @code{defclass}
 (@pxref{Top,EIEIO,,eieio,EIEIO}), and @code{define-skeleton}
 (@pxref{Top,Autotyping,,autotype,Autotyping}).
 @end table
index ba83a0578cdcc2712a9fa6745b96cdc205912ba8..6ad84055595f5c87a5a0601d3fc915ae6c0bf471 100644 (file)
 
 ;;; Code:
 
+;;;###theme-autoload
 (deftheme adwaita
   "Face colors similar to the default theme of Gnome 3 (Adwaita).
 The colors are chosen to match Adwaita window decorations and the
-default look of the Gnome 3 desktop.")
+default look of the Gnome 3 desktop."
+  :background-mode 'light
+  :kind 'color-scheme)
 
 (let ((class '((class color) (min-colors 89))))
   (custom-theme-set-faces
index 8f19147f916ae3b05658cd7868cfb694a01205de..48ed9ba061dabd15364dcecc3114434b849e8282 100644 (file)
 
 ;;; Code:
 
+;;;###theme-autoload
 (deftheme deeper-blue
-  "Face colors using a deep blue background.")
+  "Face colors using a deep blue background."
+  :background-mode 'dark
+  :kind 'color-scheme)
 
 (let ((class '((class color) (min-colors 89))))
   (custom-theme-set-faces
index d53c075d9236fc2747d64188cf737100cb4dbe1f..fe44d520cca766a9e437b295c13c2a4e28c82a8e 100644 (file)
@@ -21,6 +21,7 @@
 
 ;;; Code:
 
+;;;###theme-autoload
 (deftheme dichromacy
   "Face colors suitable for red/green color-blind users.
 The color palette is from B. Wong, Nature Methods 8, 441 (2011).
@@ -28,7 +29,9 @@ It is intended to provide good variability while being easily
 differentiated by individuals with protanopia or deuteranopia.
 
 Basic, Font Lock, Isearch, Gnus, Message, Flyspell, and
-Ansi-Color faces are included.")
+Ansi-Color faces are included."
+  :background-mode 'light
+  :kind 'color-scheme)
 
 (let ((class '((class color) (min-colors 89)))
       (orange "#e69f00")
index 0e162c8bab99889fc78b013c73cfaee551f450e7..08978a26682c50fd42bb2486493492a0e3094d63 100644 (file)
@@ -5,7 +5,7 @@
 ;; Author: Fabrice Niessen <(concat "fniessen" at-sign "pirilampo.org")>
 ;; Contributor: Thibault Polge <(concat "thibault" at-sign "thb.lt")>
 ;; URL: https://github.com/fniessen/emacs-leuven-dark-theme
-;; Version: 20220202.1126
+;; Version: 20221010.1208
 ;; Keywords: color theme
 
 ;; This file is part of GNU Emacs.
@@ -93,11 +93,15 @@ CONTROL can be a number, nil, or t.  When t, use DEFAULT-HEIGHT."
 
 ;;; Theme Faces.
 
+;;;###theme-autoload
 (deftheme leuven-dark
   "Face colors with a light background.
 Basic, Font Lock, Isearch, Gnus, Message, Org mode, Diff, Ediff,
 Flyspell, Semantic, and Ansi-Color faces are included -- and much
-more...")
+more..."
+  :background-mode 'dark
+  :family 'leuven
+  :kind 'color-scheme)
 
 (let ((class '((class color) (min-colors 89)))
 
index d9a8d5391ae14a8b54757be025ae76f0be90227d..e712a79adf1c48ef8e48ba7dab3b3572b5b260b0 100644 (file)
@@ -4,7 +4,7 @@
 
 ;; Author: Fabrice Niessen <(concat "fniessen" at-sign "pirilampo.org")>
 ;; URL: https://github.com/fniessen/emacs-leuven-theme
-;; Version: 20200513.1928
+;; Version: 20221010.1209
 ;; Keywords: color theme
 
 ;; This file is part of GNU Emacs.
@@ -74,11 +74,15 @@ CONTROL can be a number, nil, or t.  When t, use DEFAULT-HEIGHT."
 
 ;;; Theme Faces.
 
+;;;###theme-autoload
 (deftheme leuven
   "Face colors with a light background.
 Basic, Font Lock, Isearch, Gnus, Message, Org mode, Diff, Ediff,
 Flyspell, Semantic, and Ansi-Color faces are included -- and much
-more...")
+more..."
+  :background-mode 'light
+  :kind 'color-scheme
+  :family 'leuven)
 
 (let ((class '((class color) (min-colors 89)))
 
index eeca46210cc0cbe185d63e14a60373dcdefb27a3..808fcbfeb2d1ad65516f6dff469fdff1d1fb281d 100644 (file)
 
 ;;; Code:
 
+;;;###theme-autoload
 (deftheme light-blue
-  "Face colors utilizing a light blue background.")
+  "Face colors utilizing a light blue background."
+  :background-mode 'light
+  :kind 'color-scheme)
 
 (make-obsolete 'light-blue nil "29.1")
 
index af5576386c669c21516ddf68cabc8da6efe645a6..f9aaa97c2582ba0530aa5808bed8224c82dcaf26 100644 (file)
 
 ;;; Code:
 
+;;;###theme-autoload
 (deftheme manoj-dark
   "Very high contrast faces with a black background.
 This theme avoids subtle color variations, while avoiding the
-jarring angry fruit salad look to reduce eye fatigue.")
+jarring angry fruit salad look to reduce eye fatigue."
+  :background-mode 'dark
+  :kind 'color-scheme)
 
 (custom-theme-set-faces
  'manoj-dark
index 55186384ad19fde0c952010ced12ab78b7de7697..3fd6cdb5afbcb15d11065312c1ef1e10497f8cc9 100644 (file)
 
 ;;; Code:
 
+;;;###theme-autoload
 (deftheme misterioso
-  "Predominantly blue/cyan faces on a dark cyan background.")
+  "Predominantly blue/cyan faces on a dark cyan background."
+  :background-mode 'dark
+  :kind 'color-scheme)
 
 (let ((class '((class color) (min-colors 89))))
 
index 6e609c08036bb95bc28a9f20405183592fcd7f95..0f0630a6d1d08d4bae082b19aa6e7fe154b46da1 100644 (file)
@@ -71,4 +71,6 @@ which corresponds to a minimum contrast in relative luminance of
 
   (provide-theme 'modus-operandi))
 
+;;;###theme-autoload (put 'modus-operandi 'theme-properties '(:background-mode light :kind color-scheme :family modus))
+
 ;;; modus-operandi-theme.el ends here
index 0983e26c786b44a531eaf53226113e37f56ead0d..02c2d9e129a89907be05d7b1d8b441f33ab6ae6a 100644 (file)
@@ -71,4 +71,6 @@ which corresponds to a minimum contrast in relative luminance of
 
   (provide-theme 'modus-vivendi))
 
+;;;###theme-autoload (put 'modus-vivendi 'theme-properties '(:background-mode dark :kind color-scheme :family modus))
+
 ;;; modus-vivendi-theme.el ends here
index ef00d2ac49fa04dd212c28cce076703e372d515f..85995e4e995a785aa3e1ed87a7ff63b721e8130a 100644 (file)
 
 ;;; Code:
 
+;;;###theme-autoload
 (deftheme tango-dark
   "Face colors using the Tango palette (dark background).
 Basic, Font Lock, Isearch, Gnus, Message, Ediff, Flyspell,
-Semantic, and Ansi-Color faces are included.")
+Semantic, and Ansi-Color faces are included."
+  :background-mode 'dark
+  :kind 'color-scheme
+  :family 'tango)
+
 
 (let ((class '((class color) (min-colors 89)))
       ;; Tango palette colors.
index ecbbf037536f6f75a9a0efef16a2cdc75fd65a8d..2ac1b42294b196c9471363126b2a30060f5d33ba 100644 (file)
 
 ;;; Code:
 
+;;;###theme-autoload
 (deftheme tango
   "Face colors using the Tango palette (light background).
 Basic, Font Lock, Isearch, Gnus, Message, Ediff, Flyspell,
-Semantic, and Ansi-Color faces are included.")
+Semantic, and Ansi-Color faces are included."
+  :background-mode 'light
+  :kind 'color-scheme
+  :family 'tango)
 
 (let ((class '((class color) (min-colors 89)))
       ;; Tango palette colors.
index a88ad75520b3bee794d19fa7e600a80e82a0891d..6b1e865e427c264c274cc29e2df4c5130b6750e3 100644 (file)
 
 ;;; Code:
 
+;;;###theme-autoload
 (deftheme tsdh-dark
-  "A dark theme used and created by Tassilo Horn.")
+  "A dark theme used and created by Tassilo Horn."
+  :background-mode 'dark
+  :kind 'color-scheme
+  :family 'tsdh)
 
 (custom-theme-set-faces
  'tsdh-dark
index d9d09b702b7cc4c66b8783e856a326bc8035424c..ac964d66d67348aa7ce1fb20c73ff06635fe316c 100644 (file)
 
 ;;; Code:
 
+;;;###theme-autoload
 (deftheme tsdh-light
   "A light Emacs theme.
-Used and created by Tassilo Horn.")
+Used and created by Tassilo Horn."
+  :background-mode 'light
+  :kind 'color-scheme
+  :family 'tsdh)
 
 (custom-theme-set-faces
  'tsdh-light
index c56c8a2d8a479ba7c03a34254a55645702564084..20e7bbbac2994f1ef31e5c674b68790c2e3d30ff 100644 (file)
 
 ;;; Code:
 
+;;;###theme-autoload
 (deftheme wheatgrass
   "High-contrast green/blue/brown faces on a black background.
 Basic, Font Lock, Isearch, Gnus, and Message faces are included.
 The default face foreground is wheat, with other faces in shades
-of green, brown, and blue.")
+of green, brown, and blue."
+  :background-mode 'dark
+  :kind 'color-scheme)
 
 (let ((class '((class color) (min-colors 89))))
   (custom-theme-set-faces
index f21b18b421dd9118701cdda82a34b58746d48abf..2f86234b32a9db05629cc0c1cf743987d554a6d2 100644 (file)
 
 ;;; Code:
 
+;;;###theme-autoload
 (deftheme whiteboard
-  "Face colors similar to markers on a whiteboard.")
+  "Face colors similar to markers on a whiteboard."
+  :background-mode 'light
+  :kind 'color-scheme)
 
 (let ((class '((class color) (min-colors 89))))
   (custom-theme-set-faces
index d9fab8ac78234cd7a1d010d582d5ee4f741183da..9bb026ead14c3b8d89c9a6cbd5b173a57c35c50f 100644 (file)
 
 ;;; Code:
 
+;;;###theme-autoload
 (deftheme wombat
   "Medium-contrast faces with a dark gray background.
 Adapted, with permission, from a Vim color scheme by Lars H. Nielsen.
 Basic, Font Lock, Isearch, Gnus, Message, and Ansi-Color faces
-are included.")
+are included."
+  :background-mode 'dark
+  :kind 'color-scheme)
 
 (let ((class '((class color) (min-colors 89))))
   (custom-theme-set-faces
index 604b1a3ff485afb3042c0ef0d10b475af4529757..0d3e2e5d0c2c66ac6e0c0d6596a7fec9d3372124 100644 (file)
@@ -1152,9 +1152,11 @@ list, in which A occurs before B if B was defined with a
 ;;   (provide-theme 'THEME)
 
 
-(defmacro deftheme (theme &optional doc)
+(defmacro deftheme (theme &optional doc &rest properties)
   "Declare THEME to be a Custom theme.
 The optional argument DOC is a doc string describing the theme.
+PROPERTIES are interpreted as a property list that will be stored
+in the `theme-properties' property for THEME.
 
 Any theme `foo' should be defined in a file called `foo-theme.el';
 see `custom-make-theme-feature' for more information."
@@ -1164,18 +1166,25 @@ see `custom-make-theme-feature' for more information."
     ;; It is better not to use backquote in this file,
     ;; because that makes a bootstrapping problem
     ;; if you need to recompile all the Lisp files using interpreted code.
-    (list 'custom-declare-theme (list 'quote theme) (list 'quote feature) doc)))
+    (list 'custom-declare-theme (list 'quote theme) (list 'quote feature) doc
+          (cons 'list properties))))
 
-(defun custom-declare-theme (theme feature &optional doc)
+(defun custom-declare-theme (theme feature &optional doc properties)
   "Like `deftheme', but THEME is evaluated as a normal argument.
-FEATURE is the feature this theme provides.  Normally, this is a symbol
-created from THEME by `custom-make-theme-feature'."
+FEATURE is the feature this theme provides.  Normally, this is a
+symbol created from THEME by `custom-make-theme-feature'.  The
+optional argument DOC may contain the documentation for THEME.
+The optional argument PROPERTIES may contain a property list of
+attributes associated with THEME."
   (unless (custom-theme-name-valid-p theme)
     (error "Custom theme cannot be named %S" theme))
   (unless (memq theme custom-known-themes)
     (push theme custom-known-themes))
   (put theme 'theme-feature feature)
-  (when doc (put theme 'theme-documentation doc)))
+  (when doc
+    (put theme 'theme-documentation doc))
+  (when properties
+    (put theme 'theme-properties properties)))
 
 (defun custom-make-theme-feature (theme)
   "Given a symbol THEME, create a new symbol by appending \"-theme\".
@@ -1372,6 +1381,58 @@ Return t if THEME was successfully loaded, nil otherwise."
     (enable-theme theme))
   t)
 
+(defun theme-list-variants (theme &rest list)
+  "Return a list of theme variants for THEME.
+By default this will use all known custom themes (see
+`custom-available-themes') to check for variants.  This can be
+restricted if the optional argument LIST containing a list of
+theme symbols to consider."
+  (let* ((properties (get theme 'theme-properties))
+         (family (plist-get properties :family)))
+    (seq-filter
+     (lambda (variant)
+       (and (eq (plist-get (get variant 'theme-properties) :family)
+                family)
+            (not (eq variant theme))))
+     (or list (custom-available-themes)))))
+
+(defun theme-choose-variant (&optional no-confirm no-enable)
+  "Switch from the current theme to one of its variants.
+The current theme will be disabled before variant is enabled.  If
+the current theme has only one variant, switch to that variant
+without prompting, otherwise prompt for the variant to select.
+See `load-theme' for the meaning of NO-CONFIRM and NO-ENABLE."
+  (interactive)
+  (let ((active-color-schemes
+         (seq-filter
+          (lambda (theme)
+            ;; FIXME: As most themes currently do not have a `:kind'
+            ;; tag, it is assumed that a theme is a color scheme by
+            ;; default.  This should be reconsidered in the future.
+            (memq (plist-get (get theme 'theme-properties) :kind)
+                  '(color-scheme nil)))
+          custom-enabled-themes)))
+    (cond
+     ((length= active-color-schemes 0)
+      (user-error "No theme is active, cannot toggle"))
+     ((length> active-color-schemes 1)
+      (user-error "More than one theme active, cannot unambiguously toggle")))
+    (let* ((theme (car active-color-schemes))
+           (family (plist-get (get theme 'theme-properties) :family)))
+      (unless family
+        (error "Theme `%s' does not have any known variants" theme))
+      (let* ((variants (theme-list-variants theme))
+             (choice (cond
+                      ((null variants)
+                       (error "`%s' has no variants" theme))
+                      ((length= variants 1)
+                       (car variants))
+                      ((intern (completing-read "Load custom theme: " variants))))))
+        (disable-theme theme)
+        (load-theme choice no-confirm no-enable)))))
+
+(defalias 'toggle-theme #'theme-choose-variant)
+
 (defun custom-theme-load-confirm (hash)
   "Query the user about loading a Custom theme that may not be safe.
 The theme should be in the current buffer.  If the user agrees,
index 964d23c770e0be6c3b40062681b2815479998d40..d2654fb2064c2121a411962edc4bc9723f9af782 100644 (file)
@@ -283,6 +283,12 @@ expression, in which case we want to handle forms differently."
            ,@(when-let ((safe (plist-get props :safe)))
                `((put ',varname 'safe-local-variable ,safe))))))
 
+     ;; Extract theme properties.
+     ((eq car 'deftheme)
+      (let* ((name (car-safe (cdr-safe form)))
+            (props (nthcdr 3 form)))
+       `(put ',name 'theme-properties (list ,@props))))
+
      ((eq car 'defgroup)
       ;; In Emacs this is normally handled separately by cus-dep.el, but for
       ;; third party packages, it can be convenient to explicitly autoload