]>
Commit | Line | Data |
---|---|---|
1 | ;;; solarized.el --- Solarized theme -*- lexical-binding: t -*- | |
2 | ||
3 | ;; Copyright (C) 2011-2021 Bozhidar Batsov | |
4 | ||
5 | ;; Author: Bozhidar Batsov <bozhidar@batsov.dev> | |
6 | ;; Author: Thomas Frössman <thomasf@jossystem.se> | |
7 | ||
8 | ;; This program is free software; you can redistribute it and/or modify | |
9 | ;; it under the terms of the GNU General Public License as published by | |
10 | ;; the Free Software Foundation, either version 3 of the License, or | |
11 | ;; (at your option) any later version. | |
12 | ||
13 | ;; This program is distributed in the hope that it will be useful, | |
14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | ;; GNU General Public License for more details. | |
17 | ||
18 | ;; You should have received a copy of the GNU General Public License | |
19 | ;; along with this program. If not, see <http://www.gnu.org/licenses/>. | |
20 | ||
21 | ;;; Commentary: | |
22 | ||
23 | ;; Main solarized file | |
24 | ||
25 | ;;; Code: | |
26 | ||
27 | (require 'cl-lib) | |
28 | (require 'color) | |
29 | (require 'solarized-faces) | |
30 | ||
31 | ;;; Options | |
32 | ||
33 | (defgroup solarized nil | |
34 | "Solarized theme options. | |
35 | The theme has to be reloaded after changing anything in this group." | |
36 | :group 'faces) | |
37 | ||
38 | (defcustom solarized-theme-dir (locate-user-emacs-file "themes/") | |
39 | "Directory to save theme file." | |
40 | :type 'directory | |
41 | :group 'solarized) | |
42 | ||
43 | (defcustom solarized-distinct-fringe-background nil | |
44 | "Make the fringe background different from the normal background color. | |
45 | Also affects `linum-mode' background." | |
46 | :type 'boolean | |
47 | :group 'solarized) | |
48 | ||
49 | (defcustom solarized-distinct-doc-face nil | |
50 | "Make `font-lock-doc-face' stand out more. | |
51 | Related discussion: https://github.com/bbatsov/solarized-emacs/issues/158" | |
52 | :type 'boolean | |
53 | :group 'solarized) | |
54 | ||
55 | (defcustom solarized-use-variable-pitch t | |
56 | "Use variable pitch face for some headings and titles." | |
57 | :type 'boolean | |
58 | :group 'solarized) | |
59 | ||
60 | (defcustom solarized-use-less-bold nil | |
61 | "Use bold weight less often." | |
62 | :type 'boolean | |
63 | :group 'solarized) | |
64 | ||
65 | (defcustom solarized-use-more-italic nil | |
66 | "Use italic slant more often." | |
67 | :type 'boolean | |
68 | :group 'solarized) | |
69 | ||
70 | (defcustom solarized-emphasize-indicators t | |
71 | "Use more colors for indicators such as git:gutter, flycheck and similar." | |
72 | :type 'boolean | |
73 | :group 'solarized) | |
74 | ||
75 | (defcustom solarized-high-contrast-mode-line nil | |
76 | "Make the active/inactive mode line stand out more." | |
77 | :type 'boolean | |
78 | :group 'solarized) | |
79 | ||
80 | (defcustom solarized-height-minus-1 0.8 | |
81 | "Font size -1." | |
82 | :type 'number | |
83 | :group 'solarized) | |
84 | ||
85 | (defcustom solarized-height-plus-1 1.1 | |
86 | "Font size +1." | |
87 | :type 'number | |
88 | :group 'solarized) | |
89 | ||
90 | (defcustom solarized-height-plus-2 1.15 | |
91 | "Font size +2." | |
92 | :type 'number | |
93 | :group 'solarized) | |
94 | ||
95 | (defcustom solarized-height-plus-3 1.2 | |
96 | "Font size +3." | |
97 | :type 'number | |
98 | :group 'solarized) | |
99 | ||
100 | (defcustom solarized-height-plus-4 1.3 | |
101 | "Font size +4." | |
102 | :type 'number | |
103 | :group 'solarized) | |
104 | ||
105 | (defcustom solarized-scale-org-headlines t | |
106 | "Whether `org-mode' headlines should be scaled." | |
107 | :type 'boolean | |
108 | :group 'solarized) | |
109 | ||
110 | (defcustom solarized-scale-markdown-headlines nil | |
111 | "Whether `markdown-mode' headlines should be scaled." | |
112 | :type 'boolean | |
113 | :group 'solarized) | |
114 | ||
115 | (defcustom solarized-scale-outline-headlines t | |
116 | "Whether `outline-mode' headlines should be scaled." | |
117 | :type 'boolean | |
118 | :group 'solarized) | |
119 | ||
120 | ;;; Utilities | |
121 | ||
122 | (defun solarized-color-clamp-lab (lab) | |
123 | "Restricts a LAB colorspace color if it is out of bounds." | |
124 | (list (min (max (nth 0 lab) 0.0) 100.0) | |
125 | (min (max (nth 1 lab) -128) 127) | |
126 | (min (max (nth 2 lab) -128) 127))) | |
127 | ||
128 | (defun solarized-color-rgb-to-hex (red green blue &optional digits-per-component round) | |
129 | "Return hexadecimal #RGB notation for the color specified by RED GREEN BLUE. | |
130 | RED, GREEN, and BLUE should be numbers between 0.0 and 1.0, inclusive. | |
131 | Optional argument DIGITS-PER-COMPONENT can be either 4 (the default) | |
132 | or 2; use the latter if you need a 24-bit specification of a color. | |
133 | Optional argument ROUND rounds values which probably is what you usually want." | |
134 | (or digits-per-component (setq digits-per-component 4)) | |
135 | (let* ((maxval (if (= digits-per-component 2) 255 65535)) | |
136 | (fmt (if (= digits-per-component 2) "#%02x%02x%02x" "#%04x%04x%04x"))) | |
137 | (if round | |
138 | (format fmt (+ 0.5 (* red maxval)) (+ 0.5 (* green maxval)) (+ 0.5(* blue maxval))) | |
139 | (format fmt (* red maxval) (* green maxval) (* blue maxval))))) | |
140 | ||
141 | ;;;###autoload | |
142 | (defun solarized-color-blend (color1 color2 alpha &optional digits-per-component) | |
143 | "Blends COLOR1 onto COLOR2 with ALPHA. | |
144 | ||
145 | COLOR1 and COLOR2 should be color names (e.g. \"white\") or RGB | |
146 | triplet strings (e.g. \"#ff12ec\"). | |
147 | ||
148 | Alpha should be a float between 0 and 1. | |
149 | ||
150 | Optional argument DIGITS-PER-COMPONENT can be either 4 (the default) or 2; | |
151 | use the latter if you need a 24-bit specification of a color." | |
152 | (let ((args (mapcar 'color-clamp | |
153 | (apply 'color-lab-to-srgb | |
154 | (solarized-color-clamp-lab | |
155 | (cl-mapcar | |
156 | (lambda (v1 v2) (+ v1 (* alpha (- v2 v1)))) | |
157 | (apply 'color-srgb-to-lab (color-name-to-rgb color2)) | |
158 | (apply 'color-srgb-to-lab (color-name-to-rgb color1)))))))) | |
159 | (apply 'solarized-color-rgb-to-hex `(,@args ,digits-per-component t)))) | |
160 | ||
161 | ;;;###autoload | |
162 | (defun solarized-create-color-palette (core-palette) | |
163 | "Create color-palette from CORE-PALETTE. | |
164 | ||
165 | The Returned color-palette has the same format as `solarized-color-palette'" | |
166 | (let ((darkest-base (nth 0 core-palette)) | |
167 | (brightest-base (nth 1 core-palette)) | |
168 | (yellow (nth 2 core-palette)) | |
169 | (orange (nth 3 core-palette)) | |
170 | (red (nth 4 core-palette)) | |
171 | (magenta (nth 5 core-palette)) | |
172 | (violet (nth 6 core-palette)) | |
173 | (blue (nth 7 core-palette)) | |
174 | (cyan (nth 8 core-palette)) | |
175 | (green (nth 9 core-palette))) | |
176 | ||
177 | `((base03 . ,(solarized-color-blend darkest-base brightest-base 1.00 2)) | |
178 | (base02 . ,(solarized-color-blend darkest-base brightest-base 0.97 2)) | |
179 | (base01 . ,(solarized-color-blend darkest-base brightest-base 0.65 2)) | |
180 | (base00 . ,(solarized-color-blend darkest-base brightest-base 0.60 2)) | |
181 | (base0 . ,(solarized-color-blend darkest-base brightest-base 0.48 2)) | |
182 | (base1 . ,(solarized-color-blend darkest-base brightest-base 0.42 2)) | |
183 | (base2 . ,(solarized-color-blend darkest-base brightest-base 0.06 2)) | |
184 | (base3 . ,(solarized-color-blend darkest-base brightest-base 0.00 2)) | |
185 | ||
186 | ;; Solarized accented colors | |
187 | (yellow . ,yellow) | |
188 | (orange . ,orange) | |
189 | (red . ,red) | |
190 | (magenta . ,magenta) | |
191 | (violet . ,violet) | |
192 | (blue . ,blue) | |
193 | (cyan . ,cyan) | |
194 | (green . ,green) | |
195 | ||
196 | ;; Darker and lighter accented colors | |
197 | ;; Only use these in exceptional circumstances! | |
198 | (yellow-d . ,(solarized-color-blend darkest-base yellow 0.80 2)) | |
199 | (yellow-l . ,(solarized-color-blend brightest-base yellow 0.80 2)) | |
200 | (orange-d . ,(solarized-color-blend darkest-base orange 0.80 2)) | |
201 | (orange-l . ,(solarized-color-blend brightest-base orange 0.80 2)) | |
202 | (red-d . ,(solarized-color-blend darkest-base red 0.80 2)) | |
203 | (red-l . ,(solarized-color-blend brightest-base red 0.80 2)) | |
204 | (magenta-d . ,(solarized-color-blend darkest-base magenta 0.80 2)) | |
205 | (magenta-l . ,(solarized-color-blend brightest-base magenta 0.80 2)) | |
206 | (violet-d . ,(solarized-color-blend darkest-base violet 0.80 2)) | |
207 | (violet-l . ,(solarized-color-blend brightest-base violet 0.80 2)) | |
208 | (blue-d . ,(solarized-color-blend darkest-base blue 0.80 2)) | |
209 | (blue-l . ,(solarized-color-blend brightest-base blue 0.80 2)) | |
210 | (cyan-d . ,(solarized-color-blend darkest-base cyan 0.80 2)) | |
211 | (cyan-l . ,(solarized-color-blend brightest-base cyan 0.80 2)) | |
212 | (green-d . ,(solarized-color-blend darkest-base green 0.80 2)) | |
213 | (green-l . ,(solarized-color-blend brightest-base green 0.80 2)) | |
214 | ||
215 | (yellow-1bg . ,(solarized-color-blend darkest-base yellow 0.85 2)) | |
216 | (orange-1bg . ,(solarized-color-blend darkest-base orange 0.85 2)) | |
217 | (red-1bg . ,(solarized-color-blend darkest-base red 0.85 2)) | |
218 | (magenta-1bg . ,(solarized-color-blend darkest-base magenta 0.85 2)) | |
219 | (blue-1bg . ,(solarized-color-blend darkest-base blue 0.85 2)) | |
220 | (cyan-1bg . ,(solarized-color-blend darkest-base cyan 0.85 2)) | |
221 | (green-1bg . ,(solarized-color-blend darkest-base green 0.85 2)) | |
222 | (violet-1bg . ,(solarized-color-blend darkest-base violet 0.85 2)) | |
223 | ||
224 | (yellow-1fg . ,(solarized-color-blend brightest-base yellow 0.30 2)) | |
225 | (orange-1fg . ,(solarized-color-blend brightest-base orange 0.30 2)) | |
226 | (red-1fg . ,(solarized-color-blend brightest-base red 0.30 2)) | |
227 | (magenta-1fg . ,(solarized-color-blend brightest-base magenta 0.30 2)) | |
228 | (violet-1fg . ,(solarized-color-blend brightest-base violet 0.30 2)) | |
229 | (blue-1fg . ,(solarized-color-blend brightest-base blue 0.30 2)) | |
230 | (cyan-1fg . ,(solarized-color-blend brightest-base cyan 0.30 2)) | |
231 | (green-1fg . ,(solarized-color-blend brightest-base green 0.30 2)) | |
232 | ||
233 | (yellow-2bg . ,(solarized-color-blend darkest-base yellow 0.60 2)) | |
234 | (orange-2bg . ,(solarized-color-blend darkest-base orange 0.60 2)) | |
235 | (red-2bg . ,(solarized-color-blend darkest-base red 0.60 2)) | |
236 | (magenta-2bg . ,(solarized-color-blend darkest-base magenta 0.60 2)) | |
237 | (violet-2bg . ,(solarized-color-blend darkest-base violet 0.60 2)) | |
238 | (blue-2bg . ,(solarized-color-blend darkest-base blue 0.60 2)) | |
239 | (cyan-2bg . ,(solarized-color-blend darkest-base cyan 0.60 2)) | |
240 | (green-2bg . ,(solarized-color-blend darkest-base green 0.60 2)) | |
241 | ||
242 | (yellow-2fg . ,(solarized-color-blend brightest-base yellow 0.45 2)) | |
243 | (orange-2fg . ,(solarized-color-blend brightest-base orange 0.45 2)) | |
244 | (red-2fg . ,(solarized-color-blend brightest-base red 0.45 2)) | |
245 | (magenta-2fg . ,(solarized-color-blend brightest-base magenta 0.45 2)) | |
246 | (violet-2fg . ,(solarized-color-blend brightest-base violet 0.45 2)) | |
247 | (blue-2fg . ,(solarized-color-blend brightest-base blue 0.45 2)) | |
248 | (cyan-2fg . ,(solarized-color-blend brightest-base cyan 0.45 2)) | |
249 | (green-2fg . ,(solarized-color-blend brightest-base green 0.45 2))))) | |
250 | ||
251 | ;;; Setup Start | |
252 | (defmacro solarized-with-color-variables (variant theme-name color-palette &optional childtheme-sexp) | |
253 | "Eval `solarized-definition' in solarized COLOR-PALETTE for THEME-NAME. | |
254 | VARIANT is \\='dark or \\='light. | |
255 | When optional argument CHILDTHEME-SEXP sexp is supplied it\\='s invoked to further | |
256 | customize the resulting theme." | |
257 | (declare (indent defun)) | |
258 | (let ((color-palette* (eval color-palette))) | |
259 | `(let* ((class '((class color) (min-colors 89))) | |
260 | (light-class (append '((background light)) class)) | |
261 | (dark-class (append '((background dark)) class)) | |
262 | (theme-name ,theme-name) | |
263 | (variant ,variant) | |
264 | ,@(mapcar (lambda (elm) `(,(car elm) ,(cdr elm))) color-palette*) | |
265 | ||
266 | (s-base03 base03) | |
267 | (s-base02 base02) | |
268 | (s-base01 base01) | |
269 | (s-base00 base00) | |
270 | (s-base3 base3) | |
271 | (s-base2 base2) | |
272 | (s-base1 base1) | |
273 | (s-base0 base0) | |
274 | ||
275 | ;; Solarized palette names, use these instead of -fg -bg... | |
276 | (base03 (if (eq variant 'light) s-base3 s-base03)) | |
277 | (base02 (if (eq variant 'light) s-base2 s-base02)) | |
278 | (base01 (if (eq variant 'light) s-base1 s-base01)) | |
279 | (base00 (if (eq variant 'light) s-base0 s-base00)) | |
280 | (base0 (if (eq variant 'light) s-base00 s-base0)) | |
281 | (base1 (if (eq variant 'light) s-base01 s-base1)) | |
282 | (base2 (if (eq variant 'light) s-base02 s-base2)) | |
283 | (base3 (if (eq variant 'light) s-base03 s-base3)) | |
284 | ||
285 | ;; Line drawing color | |
286 | ;; | |
287 | ;; NOTE only use this for very thin lines that are hard to see using base02, in low | |
288 | ;; color displayes base02 might be used instead | |
289 | (s-line (if (eq variant 'light) "#cccec4" "#284b54")) | |
290 | ||
291 | ;; Light/Dark adaptive higher/lower contrast accented colors | |
292 | ;; | |
293 | ;; NOTE Only use these in exceptional cirmumstances! | |
294 | (yellow-hc (if (eq variant 'light) yellow-d yellow-l)) | |
295 | (yellow-lc (if (eq variant 'light) yellow-l yellow-d)) | |
296 | (orange-hc (if (eq variant 'light) orange-d orange-l)) | |
297 | (orange-lc (if (eq variant 'light) orange-l orange-d)) | |
298 | (red-hc (if (eq variant 'light) red-d red-l)) | |
299 | (red-lc (if (eq variant 'light) red-l red-d)) | |
300 | (magenta-hc (if (eq variant 'light) magenta-d magenta-l)) | |
301 | (magenta-lc (if (eq variant 'light) magenta-l magenta-d)) | |
302 | (violet-hc (if (eq variant 'light) violet-d violet-l)) | |
303 | (violet-lc (if (eq variant 'light) violet-l violet-d)) | |
304 | (blue-hc (if (eq variant 'light) blue-d blue-l)) | |
305 | (blue-lc (if (eq variant 'light) blue-l blue-d)) | |
306 | (cyan-hc (if (eq variant 'light) cyan-d cyan-l)) | |
307 | (cyan-lc (if (eq variant 'light) cyan-l cyan-d)) | |
308 | (green-hc (if (eq variant 'light) green-d green-l)) | |
309 | (green-lc (if (eq variant 'light) green-l green-d)) | |
310 | ||
311 | ;; customize based face properties | |
312 | (s-maybe-bold (if solarized-use-less-bold | |
313 | 'unspecified 'bold)) | |
314 | (s-maybe-italic (if solarized-use-more-italic | |
315 | 'italic 'normal)) | |
316 | (s-variable-pitch (if solarized-use-variable-pitch | |
317 | 'variable-pitch 'default)) | |
318 | (s-fringe-bg (if solarized-distinct-fringe-background | |
319 | base02 base03)) | |
320 | (s-fringe-fg base01) | |
321 | ||
322 | (s-header-line-fg (if solarized-high-contrast-mode-line | |
323 | base1 base0)) | |
324 | (s-header-line-bg (if solarized-high-contrast-mode-line | |
325 | base02 base03)) | |
326 | (s-header-line-underline (if solarized-high-contrast-mode-line | |
327 | nil base02)) | |
328 | ||
329 | (s-mode-line-fg (if solarized-high-contrast-mode-line | |
330 | base03 base0)) | |
331 | (s-mode-line-bg (if solarized-high-contrast-mode-line | |
332 | base0 base02)) | |
333 | (s-mode-line-underline (if solarized-high-contrast-mode-line | |
334 | nil s-line)) | |
335 | ||
336 | (s-mode-line-buffer-id-fg (if solarized-high-contrast-mode-line | |
337 | 'unspecified base1)) | |
338 | (s-mode-line-inactive-fg (if solarized-high-contrast-mode-line | |
339 | base0 base01)) | |
340 | (s-mode-line-inactive-bg (if solarized-high-contrast-mode-line | |
341 | base02 base03)) | |
342 | (s-mode-line-inactive-bc (if solarized-high-contrast-mode-line | |
343 | base02 base02)) | |
344 | ||
345 | ;; diff colors | |
346 | (s-diff-A-bg red-1bg) | |
347 | (s-diff-A-fg red-1fg) | |
348 | (s-diff-fine-A-bg red-2bg) | |
349 | (s-diff-fine-A-fg red-2fg) | |
350 | ||
351 | (s-diff-B-bg green-1bg) | |
352 | (s-diff-B-fg green-1fg) | |
353 | (s-diff-fine-B-bg green-2bg) | |
354 | (s-diff-fine-B-fg green-2fg) | |
355 | ||
356 | (s-diff-Ancestor-bg yellow-1bg) | |
357 | (s-diff-Ancestor-fg yellow-1fg) | |
358 | (s-diff-fine-Ancestor-bg yellow-2bg) | |
359 | (s-diff-fine-Ancestor-fg yellow-2fg) | |
360 | ||
361 | (s-diff-C-bg blue-1bg) | |
362 | (s-diff-C-fg blue-1fg) | |
363 | (s-diff-fine-C-bg blue-2bg) | |
364 | (s-diff-fine-C-fg blue-2fg) | |
365 | (s-diff-context-fg base0) | |
366 | (s-diff-heading-bg base02) | |
367 | ||
368 | (s-diffstat-added-fg green) | |
369 | (s-diffstat-changed-fg blue) | |
370 | (s-diffstat-removed-fg red)) | |
371 | ||
372 | ;; NOTE: `custom--inhibit-theme-enable' turn-off needed | |
373 | ;; childtheme works well disscussed in #352 | |
374 | (let ((custom--inhibit-theme-enable nil)) | |
375 | ,@solarized-definition | |
376 | ,@(eval childtheme-sexp))))) | |
377 | ||
378 | (defmacro solarized-with-color-variables-with-palette (variant theme-name core-palette &optional childtheme-sexp) | |
379 | "Create a VARIANT of the theme named THEME-NAME with CORE-PALETTE. | |
380 | ||
381 | When optional argument CHILDTHEME-SEXP sexp is supplied it's invoked to further | |
382 | customize the resulting theme. | |
383 | ||
384 | CORE-PALETTE is core color-palette." | |
385 | (declare (indent 2)) | |
386 | (let ((color-palette (solarized-create-color-palette (eval core-palette)))) | |
387 | `(solarized-with-color-variables ,variant ,theme-name ',color-palette ,childtheme-sexp))) | |
388 | ||
389 | (defun solarized-create-theme-file (variant theme-name color-palette &optional childtheme-sexp overwrite) | |
390 | "Create a VARIANT of the theme named THEME-NAME with COLOR-PALETTE. | |
391 | ||
392 | When optional argument CHILDTHEME-SEXP sexp is supplied it's invoked to further | |
393 | customize the resulting theme. | |
394 | ||
395 | CORE-PALETTE is core color-palette. | |
396 | If OVERWRITE is non-nil, overwrite theme file if exist." | |
397 | (declare (indent 2)) | |
398 | (add-to-list 'custom-theme-load-path solarized-theme-dir) | |
399 | (let ((path (expand-file-name (format "%s.el" theme-name) | |
400 | solarized-theme-dir))) | |
401 | (unless (file-directory-p solarized-theme-dir) | |
402 | (make-directory solarized-theme-dir)) | |
403 | (when (or overwrite (not (file-readable-p path))) | |
404 | (with-temp-file (expand-file-name (format "%s-theme.el" theme-name) | |
405 | solarized-theme-dir) | |
406 | (mapc (lambda (elm) | |
407 | (insert (pp-to-string elm))) | |
408 | `((require 'solarized) | |
409 | (deftheme ,theme-name | |
410 | ,(format "The %s colour theme of Solarized colour theme flavor." theme-name)) | |
411 | (solarized-with-color-variables ',variant ',theme-name ',color-palette ',childtheme-sexp) | |
412 | (provide-theme ',theme-name) | |
413 | (provide ',(intern (format "%s-theme" theme-name))))))) | |
414 | path)) | |
415 | ||
416 | (defun solarized-create-theme-file-with-palette (variant theme-name core-palette &optional childtheme-sexp overwrite) | |
417 | "Create a VARIANT of the theme named THEME-NAME with CORE-PALETTE. | |
418 | ||
419 | When optional argument CHILDTHEME-SEXP sexp is supplied it's invoked to further | |
420 | customize the resulting theme. | |
421 | ||
422 | CORE-PALETTE is core color-palette. | |
423 | If OVERWRITE is non-nil, overwrite theme file if exist." | |
424 | (declare (indent 2)) | |
425 | (let ((color-palette (solarized-create-color-palette core-palette))) | |
426 | (apply #'solarized-create-theme-file (list variant theme-name color-palette childtheme-sexp overwrite)))) | |
427 | ||
428 | (define-obsolete-function-alias 'create-solarized-theme-file 'solarized-create-theme-file "1.3.0") | |
429 | ||
430 | ;;; Footer | |
431 | ||
432 | ;;;###autoload | |
433 | (when (and (boundp 'custom-theme-load-path) load-file-name) | |
434 | (add-to-list 'custom-theme-load-path | |
435 | (file-name-as-directory (file-name-directory load-file-name)))) | |
436 | ||
437 | (provide 'solarized) | |
438 | ||
439 | ;; Local Variables: | |
440 | ;; indent-tabs-mode: nil | |
441 | ;; End: | |
442 | ||
443 | ;;; solarized.el ends here |