-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmultitheme.el
executable file
·123 lines (98 loc) · 4.2 KB
/
multitheme.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
;;; multitheme.el --- Use multiple themes together -*- lexical-binding: t; -*-
;; Copyright (C) 2016 Aaron Harris
;; Author: Aaron Harris <meerwolf@gmail.com>
;; Keywords: themes
;; Dependencies: `dash', `validate' (optional)
;; This program 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.
;; This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; Because custom themes are additive in Emacs (that is,
;; `enable-theme' doesn't disable any themes that were previously
;; enabled), it can be tricky to switch between different themes. It
;; can be even trickier if you want certain themes to be used
;; simultaneously. This module attempts to provide support for this
;; sort of use-case.
;;
;; To use this module, you should first set the variable
;; `multitheme-base-theme-list' to contain a list of themes (symbols)
;; that you'd like to use. Then call the command `multitheme-cycle'
;; to enable to the first theme in the list; subsequent invocations
;; will cycle through the remaining themes.
;;
;; In addition, if you set the variable `multitheme-overtheme', its
;; value (again, a symbol naming a theme) will be applied on top of
;; whatever base theme is currently in use.
;;; Code:
(require 'dash) ; For `-drop-while'
;;;; User Options
;;===============
(defgroup multitheme nil
"Use multiple themes at once."
:prefix "multitheme-"
:link '(emacs-commentary-link "multitheme")
:group 'faces)
(defcustom multitheme-base-theme-list nil
"A list of themes to be used as multitheme bases."
:type '(repeat symbol))
(defcustom multitheme-overtheme nil
"A theme used on top of the multitheme base.
If this variable is non-nil, it should be the name of a theme.
Whenever the multitheme base is changed (e.g., by
`multitheme-cycle'), this theme will be applied on top of the new
base theme. Hence this theme should be \"thin\", overriding only
those elements that you wish to change in all base themes."
:type 'symbol)
(defcustom multitheme-base-theme-change-hook nil
"Hook run when the multitheme base is changed.
When this hook is run, the new base has already been loaded."
:type 'hook)
;;;; Subroutines
;;==============
(defun multitheme--enable (theme)
"As `enable-theme', but load the theme if necessary.
Respect `custom-safe-themes'."
(if (custom-theme-p theme)
(enable-theme theme)
(load-theme theme)))
;;;; Commands
;;===========
;;;###autoload
(defun multitheme-cycle ()
"Cycle between the themes in `multitheme-base-theme-list'.
If none of these themes is currently active, instead enable the
first element of `multitheme-base-theme-list'.
Also re-enable `multitheme-overtheme' so it remains \"on top\" of
the base theme.
If a theme to be enabled is not yet defined, attempt to load it
first (using `load-theme'). Respect `custom-safe-themes'.
After all theme changes have been made, run
`multitheme-base-change-hook'."
(interactive)
(when (require 'validate nil :noerror)
(validate-variable 'multitheme-base-theme-list)
(validate-variable 'multitheme-overtheme)
(validate-variable 'multitheme-base-theme-change-hook))
(let ((themes (-drop-while
(lambda (thm) (not (custom-theme-enabled-p thm)))
multitheme-base-theme-list)))
;; Cycle base theme
(if (null themes)
(multitheme--enable (car multitheme-base-theme-list))
(disable-theme (car themes))
(multitheme--enable (or (cadr themes)
(car multitheme-base-theme-list))))
;; Reassert overtheme
(when multitheme-overtheme
(multitheme--enable multitheme-overtheme))
;; Run hooks
(run-hooks 'multitheme-base-theme-change-hook)))
(provide 'multitheme)
;;; multitheme.el ends here