├── discobolus.png ├── .editorconfig ├── LICENSE ├── themes ├── myron-grayscale-theme.el ├── myron-theme-template.el ├── myron-storm-theme.el ├── myron-test-theme.el ├── myron-mcfay-theme.el ├── myron-kobo-theme.el ├── myron-whisper-theme.el ├── myron-dogman-theme.el ├── myron-struan-theme.el └── myron-room-theme.el ├── readme.org ├── myron-themes-cache.el └── myron-themes.el /discobolus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neeasade/myron-themes/HEAD/discobolus.png -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | 7 | [*.el] 8 | indent_size = 2 9 | indent_style = space 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 neeasade 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /themes/myron-grayscale-theme.el: -------------------------------------------------------------------------------- 1 | ;; -*- lexical-binding: t; -*- 2 | ;; inspo: base16-grayscale 3 | 4 | (require 'myron-themes) 5 | 6 | (defun myron-grayscale-colors (background) 7 | "Get the grayscale foreground colors against a specific BACKGROUND." 8 | (->> '(:background 0 9 | :foreground 6 10 | :faded 3 11 | :primary 4 12 | :assumed 5 13 | :alt 3 14 | :strings 4) 15 | (-partition 2) 16 | (-mapcat (-lambda ((label contrast)) 17 | (list label (ct-contrast-min background background contrast)))) 18 | (ht<-plist))) 19 | 20 | (defun myron-grayscale-create () 21 | "Create the colors for the grayscale theme." 22 | (-let* 23 | ((background 24 | ;; "#e9e9e9" 25 | "#f3f3f3" 26 | ;; "#f7f7f7" 27 | ;; "#e0e0e0" 28 | )) 29 | (->> '(:focused 3 30 | :weak 4 31 | :strong 7) 32 | (-partition 2) 33 | (-map (-lambda ((label distance)) 34 | (list label (ct-change background distance 'ct-edit-lab-l-dec)))) 35 | (append `((:normal ,background))) 36 | (-mapcat (-lambda ((label bg)) (list label (myron-grayscale-colors bg)))) 37 | (ht<-plist)))) 38 | 39 | (deftheme myron-grayscale) 40 | (myron-themes--define 'myron-grayscale) 41 | 42 | (provide-theme 'myron-grayscale) 43 | (provide 'myron-grayscale-theme) 44 | ;;; myron-grayscale-theme.el ends here 45 | -------------------------------------------------------------------------------- /themes/myron-theme-template.el: -------------------------------------------------------------------------------- 1 | ;; -*- lexical-binding: t; -*- 2 | ;; template the foobar theme 3 | 4 | (require 'myron-themes) 5 | 6 | (defun myron-foobar-colors (background) 7 | "Get the foobar foreground colors against a specific BACKGROUND." 8 | (let* ((colors (->> (ct-make-hsl 240 80 43.596) 9 | (ct-rotation-hsv 5) 10 | (--map (ct-contrast-clamp it background 4.1))))) 11 | (ht<-plist 12 | `(:background ,background 13 | :foreground ,(ct-contrast-min background background 6.0) 14 | :assumed ,(-> (nth 1 colors) 15 | (ct-edit-lch-c 90) 16 | (ct-contrast-max background 2.6)) 17 | 18 | ,@(-interleave 19 | '(:primary :faded :alt :strings) 20 | (-select-by-indices '(0 4 3 3) colors)))))) 21 | 22 | (defun myron-foobar-create () 23 | "Create the colors for the foobar theme." 24 | (-let* ((background (ct-make-hsluv 180 100 94)) 25 | (background+ (-> (myron-foobar-colors background) 26 | (ht-get :primary) 27 | (ct-edit-lch-c 80) 28 | (ct-steal 'hsluv-l background>)))) 29 | 30 | (ht<-plist 31 | (list 32 | :focused (myron-foobar-colors background+) 33 | :normal (myron-foobar-colors background) 34 | :weak (myron-foobar-colors background>) 35 | :strong (myron-foobar-colors background>>))))) 36 | 37 | (deftheme myron-foobar) 38 | (myron-themes--define 'myron-foobar) 39 | 40 | (myron-themes-evil-cursor-color (myron-themes-get :assumed)) 41 | 42 | (provide-theme 'myron-foobar) 43 | (provide 'myron-foobar-theme) 44 | ;;; myron-foobar-theme.el ends here 45 | -------------------------------------------------------------------------------- /themes/myron-storm-theme.el: -------------------------------------------------------------------------------- 1 | ;; -*- lexical-binding: t; -*- 2 | ;; authored during a storm 3 | ;; lower contrast 4 | 5 | (require 'myron-themes) 6 | 7 | (defun myron-storm-colors (bg) 8 | "Get the storm foreground colors against a specific BG." 9 | (let ((fg-ratio 4) 10 | (return (ht))) 11 | 12 | (ht-set return :background bg) 13 | (ht-set return :foreground (ct-contrast-min bg bg fg-ratio)) 14 | (ht-set return :faded (ct-contrast-min bg bg (- fg-ratio 1))) 15 | 16 | (->> (ct-rotation-hsluv 6 bg) 17 | (-map (lambda (c) 18 | (ct-iterate c 19 | (-compose 'ct-edit-hsluv-l-dec 'ct-edit-hsluv-s-inc) 20 | (lambda (step) (> (ct-contrast-ratio step bg) fg-ratio))))) 21 | ;; todo: revisit assumed color 22 | (-select-by-indices '(2 1 0 4)) 23 | (-interleave '(:primary :assumed :strings :alt)) 24 | (-partition 2) 25 | (-map (-lambda ((k v)) (ht-set return k v)))) 26 | 27 | return)) 28 | 29 | (defun myron-storm-create () 30 | "Create the colors for the storm theme." 31 | (-let* 32 | ((background (ct-make-lab 94 -5 0)) 33 | (background> (ct-change background 5 'ct-edit-hsluv-l-dec)) 34 | (background>> (ct-change background 7 'ct-edit-hsluv-l-dec)) 35 | (normal-parts (myron-storm-colors background)) 36 | ((&hash :alt :assumed :primary :faded :foreground) normal-parts) 37 | 38 | (background+ (ct-edit-hsluv-l primary (ct-get-hsluv-l background>)))) 39 | 40 | (ht 41 | (:normal normal-parts) 42 | (:weak (myron-storm-colors background>)) 43 | (:strong (myron-storm-colors background>>)) 44 | (:focused (myron-storm-colors background+))))) 45 | 46 | (deftheme myron-storm) 47 | (myron-themes--define 'myron-storm) 48 | 49 | (provide-theme 'myron-storm) 50 | (provide 'myron-storm-theme) 51 | ;;; myron-storm-theme.el ends here 52 | -------------------------------------------------------------------------------- /themes/myron-test-theme.el: -------------------------------------------------------------------------------- 1 | ;; -*- lexical-binding: t; -*- 2 | ;; placeholder for themes being developed 3 | 4 | (require 'myron-themes) 5 | 6 | (defun myron-test-colors (background) 7 | "get the foreground colors against a specific background" 8 | (let* ((colors (--> 9 | (ct-make-hsl 240 80 43.596) 10 | 11 | (ct-rotation-hsv it 72) 12 | 13 | (--map (ct-contrast-clamp it background 4.1) it)))) 14 | 15 | (ht<-plist 16 | `(:background ,background 17 | :foreground ,(ct-contrast-min background background 6.0) 18 | 19 | :assumed ,(-> (nth 1 colors) 20 | (ct-edit-lch-c 90) 21 | (ct-contrast-max background 2.6)) 22 | 23 | ,@(-interleave 24 | '(:primary :faded :alt :strings) 25 | ;; (-select-by-indices '(0 4 3 2) colors) 26 | ;; what if strings and types were the same color 27 | (-select-by-indices '(0 4 3 3) colors)))))) 28 | 29 | (defun myron-test-create () 30 | (-let* 31 | ( 32 | (background (ct-make-hsluv 180 100 94)) 33 | ;; (background (ct-make-hsluv 180 100 90)) 34 | (normal-parts (myron-test-colors background)) 35 | ((&hash :alt :assumed :primary :faded :foreground) normal-parts) 36 | (background> background) 37 | (background>> background) 38 | 39 | (background+ 40 | (-> primary 41 | (ct-edit-lch-c 20) 42 | (ct-edit-hsluv-l 43 | (ct-get-hsluv-l background>>))))) 44 | 45 | (ht<-plist 46 | (list 47 | :focused (myron-test-colors background+) 48 | :normal normal-parts 49 | :weak (myron-test-colors background>) 50 | :strong (myron-test-colors background>>))))) 51 | 52 | (deftheme myron-test) 53 | (plist-put myron--cache 'myron-test (myron-test-create)) 54 | 55 | (myron-theme-define 'myron-test) 56 | 57 | ;; (myron-evil-cursor-color (myron-get :assumed)) 58 | 59 | (provide-theme 'myron-test) 60 | (provide 'myron-test-theme) 61 | ;;; myron-test-theme.el ends here 62 | -------------------------------------------------------------------------------- /themes/myron-mcfay-theme.el: -------------------------------------------------------------------------------- 1 | ;; -*- lexical-binding: t; -*- 2 | ;; namesake: Jamie McFay, from the James Clavell novel Gai-Jin 3 | 4 | (require 'myron-themes) 5 | 6 | (defun myron-mcfay-colors (background) 7 | "Get the mcfay foreground colors against a specific BACKGROUND." 8 | (let* ((colors (->> (ct-make-hsluv 270 75 43.596) 9 | (ct-rotation-lch -8) 10 | (-select-by-indices '(7 1 2 4)) 11 | (-map (lambda (c) (ct-edit-hsluv-l c 43.596))) 12 | (-map (lambda (c) (ct-contrast-min c background 4.3)))))) 13 | 14 | (ht 15 | (:background background) 16 | (:foreground (ct-contrast-min background background 7.7)) 17 | (:faded (ct-contrast-min background background 4.3)) 18 | (:primary (nth 0 colors)) 19 | (:assumed (nth 1 colors)) 20 | (:alt (nth 2 colors)) 21 | (:strings (ct-edit-lch-c (nth 3 colors) 100))))) 22 | 23 | (defun myron-mcfay-create () 24 | "Create the colors for the mcfay theme." 25 | (-let* 26 | ( 27 | ;; /slightly/ cool 28 | (background (ct-make-lab 93 -0.5 -1)) 29 | (normal-parts (myron-mcfay-colors background)) 30 | ((&hash :alt :assumed :primary :faded :foreground) normal-parts) 31 | 32 | (background> (-> background 33 | (ct-change 4 'ct-edit-lab-l-dec) 34 | (ct-steal 'hsluv-h alt))) 35 | 36 | (background>> (-> background 37 | (ct-change 7 'ct-edit-lab-l-dec) 38 | (ct-steal 'hsluv-h primary))) 39 | 40 | (background+ (-> alt 41 | (ct-edit-lch-c 20) 42 | (ct-steal 'hsluv-l background>>)))) 43 | 44 | (ht 45 | (:focused (myron-mcfay-colors background+)) 46 | (:normal normal-parts) 47 | (:weak (myron-mcfay-colors background>)) 48 | (:strong (myron-mcfay-colors background>>))))) 49 | 50 | (deftheme myron-mcfay) 51 | (myron-themes--define 'myron-mcfay 52 | '((cursor :background alt))) 53 | 54 | (provide-theme 'myron-mcfay) 55 | (provide 'myron-mcfay-theme) 56 | ;;; myron-mcfay-theme.el ends here 57 | -------------------------------------------------------------------------------- /themes/myron-kobo-theme.el: -------------------------------------------------------------------------------- 1 | ;; -*- lexical-binding: t; -*- 2 | ;; bg and fg inspired by my kobo reader running plato 3 | ;; the hue is to add a tint of spice 4 | 5 | (require 'myron-themes) 6 | 7 | (defun myron-kobo-colors (background hue) 8 | "Get the kobo foreground colors against a specific BACKGROUND." 9 | (->> '(:background 0 10 | :foreground 5.5 11 | :assumed 5.5 12 | :strings 3 13 | :alt 3 14 | :faded 4 15 | :primary 4) 16 | (-partition 2) 17 | (-mapcat (-lambda ((label contrast)) 18 | (let ((color (ct-contrast-min background background contrast))) 19 | (if (-contains-p '(:primary :alt :strings) label) 20 | (list label (ct-aedit-hsluv color (list hue 100 l))) 21 | (list label color))))) 22 | (ht<-plist))) 23 | 24 | (defun myron-kobo-create () 25 | "Create the colors for the kobo theme." 26 | ;; to get this bg I took a pic of my kobo with my phone camera 27 | (-let* ((background "#d7d2cf" 28 | ;; bg fg from camshot of kobo on phone 29 | ;; (ct-contrast-ratio "#d7d2cf" "#4c4d5a") 30 | ;; 5.566905771576383 31 | ) 32 | (hue 90)) 33 | (->> (list 34 | :normal background 35 | 36 | ;; the unique thing about this theme - a *lighter* weak bg 37 | :weak (ct-change background 1.5 'ct-edit-lab-l-inc) 38 | 39 | ;; torn on whether or not to give focus bg a flare 40 | ;; syncing strong+focused works b/c in practice, focus selection on a strong bg is not used 41 | :strong (ct-change background 3 'ct-edit-lab-l-dec) 42 | :focused (ct-change background 2.5 'ct-edit-lab-l-dec) 43 | 44 | ;; (-> background 45 | ;; (ct-edit-hsluv-h hue) 46 | ;; (ct-edit-hsluv-s 10) 47 | ;; (ct-change 1.5 'ct-edit-lab-l-dec)) 48 | ) 49 | (-partition 2) 50 | (-mapcat (-lambda ((label bg)) (list label (myron-kobo-colors bg hue)))) 51 | (ht<-plist)))) 52 | 53 | (deftheme myron-kobo) 54 | 55 | (myron-themes--define 'myron-kobo 56 | '((font-lock-type-face :foreground foreground) 57 | (cursor :background faded))) 58 | 59 | (provide-theme 'myron-kobo) 60 | (provide 'myron-kobo-theme) 61 | ;;; myron-kobo-theme.el ends here 62 | -------------------------------------------------------------------------------- /themes/myron-whisper-theme.el: -------------------------------------------------------------------------------- 1 | ;; -*- lexical-binding: t; -*- 2 | ;; a soft warm theme 3 | 4 | (require 'myron-themes) 5 | 6 | (defun myron-whisper-colors (background hue) 7 | "Get the whisper foreground colors against a specific BACKGROUND." 8 | (->> '( 9 | ;; :background 0 10 | ;; :foreground 5.5 11 | ;; :assumed 5.5 12 | :foreground 3 13 | :assumed 3 14 | :strings 3 15 | :alt 3 16 | :faded 4 17 | :primary 4 18 | ) 19 | (-partition 2) 20 | (-mapcat (-lambda ((label contrast)) 21 | (let ((color (ct-contrast-min background background 4.6))) 22 | (if (-contains-p '(:primary :alt :strings) label) 23 | (list label (ct-aedit-lch color (list l 100 hue))) 24 | ;; (list label (ct-aedit-hsluv color (list hue 100 l))) 25 | (list label color))))) 26 | (ht<-plist) 27 | (ht-merge (-ht :background background)))) 28 | 29 | (defun myron-whisper-create () 30 | "Create the colors for the whisper theme." 31 | ;; to get this bg I took a pic of my whisper with my phone camera 32 | (-let* ( 33 | (bg-hue 0) 34 | 35 | (background (ct-make-hsv bg-hue 12 100)) 36 | 37 | (hue (mod (+ bg-hue 180) 360)) 38 | (hue 200) 39 | (hue 190) 40 | ) 41 | (->> (list 42 | :normal background 43 | 44 | :weak (ct-change background 1.5 'ct-edit-lab-l-dec) 45 | :strong (ct-change background 3 'ct-edit-lab-l-dec) 46 | 47 | :focused 48 | (-> 49 | (ct-change background 3 'ct-edit-lab-l-dec) 50 | (ct-edit-hsluv-s 100) 51 | ;; (ct-edit-lch-h-inc bg-hue) 52 | ) 53 | 54 | ;; (-> background 55 | ;; ;; (ct-edit-hsluv-h hue) 56 | ;; (ct-edit-hsluv-s-inc 10) 57 | ;; (ct-change 1.5 'ct-edit-lab-l-dec)) 58 | ) 59 | (-partition 2) 60 | (-mapcat (-lambda ((label bg)) (list label (myron-whisper-colors bg hue)))) 61 | (ht<-plist)))) 62 | 63 | (deftheme myron-whisper) 64 | 65 | (myron-themes--define 'myron-whisper 66 | '((font-lock-type-face :foreground foreground) 67 | (cursor :background faded))) 68 | 69 | (provide-theme 'myron-whisper) 70 | (provide 'myron-whisper-theme) 71 | ;;; myron-whisper-theme.el ends here 72 | -------------------------------------------------------------------------------- /themes/myron-dogman-theme.el: -------------------------------------------------------------------------------- 1 | ;; -*- lexical-binding: t; -*- 2 | ;; named for dogman of the first law series 3 | ;; the main colors of this theme came so naturally, late at night, in an escape 4 | ;; the backgrounds (weak/strong/focused) took more time 5 | 6 | (require 'myron-themes) 7 | 8 | (defun myron-dogman-colors (background) 9 | "Get the dogman foreground colors against a specific BACKGROUND." 10 | (let* ((colors (->> (ct-make-hsl 240 80 43.596) 11 | (ct-rotation-hsv 5) 12 | (--map (ct-contrast-clamp it background 4.1))))) 13 | (ht<-plist 14 | `(:background ,background 15 | :foreground ,(ct-contrast-min background background 6.0) 16 | :assumed ,(-> (nth 1 colors) 17 | (ct-edit-lch-c 90) 18 | (ct-contrast-max background 2.6)) 19 | 20 | ,@(-interleave 21 | '(:primary :faded :alt :strings) 22 | ;; (-select-by-indices '(0 4 3 2) colors) 23 | ;; what if strings and types were the same color 24 | (-select-by-indices '(0 4 3 3) colors)))))) 25 | 26 | (defun myron-dogman-create () 27 | "Create the colors for the dogman theme." 28 | (-let* ((background (ct-make-hsluv 180 100 94)) 29 | ;; (background "#fdf6e3") 30 | ;; (background (ct-make-hsluv 180 100 90)) 31 | 32 | (background> (ct-change background 4 33 | (-compose 34 | 'ct-edit-hsv-v-dec 35 | 'ct-edit-hsv-v-dec 36 | 'ct-edit-lab-a-inc))) 37 | 38 | (background>> (ct-change background> 6 39 | (-compose 40 | 'ct-edit-lab-a-inc 41 | 'ct-edit-lab-b-inc))) 42 | 43 | (background+ (-> (myron-dogman-colors background) 44 | (ht-get :primary) 45 | (ct-edit-lch-c 80) 46 | (ct-steal 'hsluv-l background>)))) 47 | 48 | (ht<-plist 49 | (list 50 | :focused (myron-dogman-colors background+) 51 | :normal (myron-dogman-colors background) 52 | :weak (myron-dogman-colors background>) 53 | :strong (myron-dogman-colors background>>))))) 54 | 55 | (deftheme myron-dogman) 56 | (myron-themes--define 'myron-dogman 57 | '((cursor :background assumed))) 58 | 59 | (provide-theme 'myron-dogman) 60 | (provide 'myron-dogman-theme) 61 | ;;; myron-dogman-theme.el ends here 62 | -------------------------------------------------------------------------------- /themes/myron-struan-theme.el: -------------------------------------------------------------------------------- 1 | ;; -*- lexical-binding: t; -*- 2 | ;; namesake: the Struan family, from James Clavell's Asian Saga series 3 | 4 | (require 'myron-themes) 5 | 6 | (defun myron-struan-colors (background) 7 | "Get the struan foreground colors against a specific BACKGROUND." 8 | (let* ((colors (->> (ct-make-hsluv 265 60 40) 9 | (ct-rotation-hsluv 6) 10 | (-select-by-indices '(1 5 2 3)) 11 | (-map (lambda (c) (ct-edit-hsluv-l c 80))) 12 | (-map (lambda (c) (ct-contrast-min c background 4.3))))) 13 | 14 | (foreground (ct-contrast-min background background 7)) 15 | (faded (ct-contrast-min (ct-aedit-hsl 16 | ;; (nth 2 colors) 17 | (ct-contrast-min background background 5.5) 18 | (list h 80 70)) 19 | background 4.3))) 20 | 21 | (ht<-plist (list :background background 22 | :foreground foreground 23 | :faded faded 24 | :primary (nth 0 colors) 25 | :assumed (nth 1 colors) 26 | :alt (nth 2 colors) 27 | :strings (-> (nth 3 colors) 28 | (ct-aedit-lch (list (+ l 10) 100 h)) 29 | (ct-contrast-min background 4.3)))))) 30 | 31 | (defun myron-struan-create () 32 | "Create the colors for the struan theme." 33 | (-let* 34 | ((background (ct-make-lab 93 2 4)) 35 | (normal-parts (myron-struan-colors background)) 36 | ((&hash :alt :assumed :primary :faded :foreground) normal-parts) 37 | 38 | (background> 39 | (-> background 40 | (ct-change 4 'ct-edit-lab-l-dec) 41 | (ct-steal 'hsluv-h alt))) 42 | 43 | (background>> 44 | (-> background 45 | (ct-change 7 'ct-edit-lab-l-dec) 46 | (ct-steal 'hsluv-h primary))) 47 | 48 | (background+ 49 | (-> alt 50 | (ct-edit-lch-c 25) 51 | (ct-steal 'hsluv-l background>>)))) 52 | 53 | (ht 54 | (:normal normal-parts) 55 | (:weak (myron-struan-colors background>)) 56 | (:strong (myron-struan-colors background>>)) 57 | (:focused (ht-merge normal-parts (ht (:background background+))))))) 58 | 59 | 60 | (deftheme myron-struan) 61 | (myron-themes--define 'myron-struan) 62 | 63 | (provide-theme 'myron-struan) 64 | (provide 'myron-struan-theme) 65 | ;;; myron-struan-theme.el ends here 66 | -------------------------------------------------------------------------------- /themes/myron-room-theme.el: -------------------------------------------------------------------------------- 1 | ;; -*- lexical-binding: t; -*- 2 | ;; it's warm outside, it's cool in here 3 | ;; I'm not feeling very well 4 | 5 | (require 'myron-themes) 6 | 7 | (defun myron-room-colors (background hue) 8 | "Get the room foreground colors against a specific BACKGROUND." 9 | (->> '(:background 0 10 | :foreground 6 11 | :faded 3 12 | :primary 4 13 | ;; todo: something with assumed color 14 | :assumed 6 15 | :alt 3 16 | :strings 4) 17 | (-partition 2) 18 | (-mapcat (-lambda ((label contrast)) 19 | (list label 20 | (cond 21 | ((eq :strings label) 22 | (-> (ct-contrast-min background background contrast) 23 | (ct-edit-hsluv-h hue) 24 | (ct-edit-lch-c 100) 25 | (ct-complement))) 26 | ((-contains-p '(:primary :alt) label) 27 | (-> (ct-contrast-min background background contrast) 28 | (ct-edit-hsluv-h hue) 29 | ;; (ct-edit-hsluv-s 100) 30 | (ct-edit-lch-c 100))) 31 | (t (ct-contrast-min background background contrast)))))) 32 | ;; (-mapcat (-lambda ((label contrast)) 33 | ;; (list label (ct-contrast-min background background contrast)))) 34 | (ht<-plist))) 35 | 36 | (defun myron-room-create () 37 | "Create the colors for the room theme." 38 | (-let* 39 | (;; maybe a darker bg 40 | (background "#f0f0f0") 41 | 42 | (hue (ct-get-hsluv-h "#ebe5f4")) 43 | 44 | ((background> background>>) (->> '(:weak 4 45 | :strong 7) 46 | (-partition 2) 47 | (-map (-lambda ((label distance)) 48 | (ct-change background distance 'ct-edit-lab-l-dec))))) 49 | (background+ (-> (ht-get (myron-room-colors background hue) :alt) 50 | ;; (ct-edit-lch-h 40) 51 | (ct-complement) 52 | (ct-edit-lch-c 100) 53 | (ct-steal 'hsluv-l background>)))) 54 | (ht<-plist 55 | (list 56 | :focused (myron-room-colors background+ hue) 57 | :normal (myron-room-colors background hue) 58 | :weak (myron-room-colors background> hue) 59 | :strong (myron-room-colors background>> hue))))) 60 | 61 | (deftheme myron-room) 62 | (myron-themes--define 'myron-room 63 | '((cursor :background alt))) 64 | 65 | (provide-theme 'myron-room) 66 | (provide 'myron-room-theme) 67 | ;;; myron-room-theme.el ends here 68 | -------------------------------------------------------------------------------- /readme.org: -------------------------------------------------------------------------------- 1 | #+html:

2 | 3 | * ~Myron Themes~ 🟠 🔴 🟡 🟤 🟢 🟣 🔵 4 | 5 | Yet more *artisanal* light themes for [[https://emacs.sexy/][emacs]]. 6 | 7 | - Bootstraps [[https://github.com/base16-project/base16-emacs][base16-emacs]] for wide emacs package coverage 8 | - Constant contrast across different [[#Emphasis][emphasis]] contexts 9 | - Conformity of markup texts to look like org mode (markdown, rst, adoc) 10 | - Built with [[https://github.com/neeasade/ct.el][ct.el]] (macro technology!!) 11 | 12 | ** Screenshots 13 | 14 | See [[https://notes.neeasade.net/tarps.html][here]] for a code preview of all themes. Some flagship themes below: 15 | 16 | | *mcfay* [[https://i.imgur.com/Fk4VBkP.png]] | 17 | | *struan* [[https://i.imgur.com/xxCuyoT.png]] | 18 | | *dogman* [[https://i.imgur.com/RlpnKZe.png]] | 19 | 20 | ** Installation 21 | 22 | Install with [[https://github.com/raxod502/straight.el][straight.el]]: 23 | 24 | #+begin_src emacs-lisp 25 | (straight-use-package '(myron-themes :host github :repo "neeasade/myron-themes" :files ("*.el" "themes/*.el"))) 26 | #+end_src 27 | 28 | ** Colors 29 | 30 | Myron colorschemes come flavored against different backgrounds, for different levels of emphasis. This can be used to ensure the same contrast level across different contexts. The schemes are stored in a nested hash table, with a helper to access them -- EG ~(myron-get :primary :strong)~ to get the primary foreground color meant to be used against the strong background (which you could get with ~(myron-get :background :strong)~). The available background keys are: ~:normal :weak :strong :focused~. For each of those, the following foregrounds are available: 31 | 32 | | label | meaning (foreground) | example | 33 | |-------------+------------------------+----------------------------------------------| 34 | | :foreground | default | | 35 | | :faded | faded | comments | 36 | | :primary | identity | functions, variables | 37 | | :assumed | assumptions/core stuff | builtins, key words | 38 | | :alt | accent | types, matching string within search results | 39 | | :strings | strings | strings | 40 | 41 | Some thoughts on my general theme opinions: 42 | 43 | - Strings are important enough to get their own color for emphasis because they often represent the edges or barriers at which things communicate 44 | - Identity between functions and variables can be blended (lisp-1 type of feel) 45 | - The focused background is important/should be used to show what's highlighted or where interactive focus is 46 | - It appears I hate the color red generally (in thin lines it looks the same as black to me), except magenta/pinkish tones for the identity foreground 47 | - I generally lean higher contrast 48 | - note: I'm colorblind 49 | 50 | ** Contrast dumping 51 | 52 | Calling ~myron-show-contrasts~ will show the contrast ratios of all the foregrounds against all the backgrounds. 53 | 54 | ** Terminal usage 55 | 56 | Use these themes in a terminal supporting truecolors, and set the following before loading the themes: 57 | 58 | #+begin_src emacs-lisp 59 | (setq base16-theme-256-color-source 'colors) 60 | #+end_src 61 | 62 | ** Thanks/Previous inspo 63 | 64 | - [[https://github.com/MetroWind/lab-theme][lab-theme]] 65 | - [[https://github.com/waymondo/apropospriate-theme][aproprospriate]] 66 | - [[https://github.com/belak/base16-emacs][base16-emacs]] 67 | -------------------------------------------------------------------------------- /myron-themes-cache.el: -------------------------------------------------------------------------------- 1 | ;; -*- lexical-binding: t; -*- 2 | (defvar myron-themes-cache 3 | '(myron-dogman 4 | #s(hash-table test equal data 5 | (:strong 6 | #s(hash-table test equal data 7 | (:strings "#026d00" :alt "#026d00" :faded "#006b47" :primary "#6d34e3" 8 | :assumed "#d144a7" :foreground "#064d51" :background "#92d9dd")) 9 | :weak 10 | #s(hash-table test equal data 11 | (:strings "#0e7900" :alt "#0e7900" :faded "#007753" :primary "#7940ef" 12 | :assumed "#e14db9" :foreground "#005953" :background "#92ede7")) 13 | :normal 14 | #s(hash-table test equal data 15 | (:strings "#1a8500" :alt "#1a8500" :faded "#00825e" :primary "#854cfb" 16 | :assumed "#f256c9" :foreground "#036458" :background "#9efff3")) 17 | :focused 18 | #s(hash-table test equal data 19 | (:strings "#0e7900" :alt "#0e7900" :faded "#007753" :primary "#7940ef" 20 | :assumed "#e14db9" :foreground "#524b6a" :background "#e0d9f8")) 21 | :meta 22 | #s(hash-table test equal data 23 | (:diff-remove-highlight "#f2c7ce" :diff-add-highlight "#9ef57d" :diff-remove 24 | "#f5d6db" :diff-add "#c7f9b7")))) 25 | myron-grayscale 26 | #s(hash-table test equal data 27 | (:strong 28 | #s(hash-table test equal data 29 | (:strings "#636363" :alt "#767676" :assumed "#545454" :primary "#636363" 30 | :faded "#767676" :foreground "#494949" :background "#d3d3d3")) 31 | :weak 32 | #s(hash-table test equal data 33 | (:strings "#6b6b6b" :alt "#7f7f7f" :assumed "#5c5c5c" :primary "#6b6b6b" 34 | :faded "#7f7f7f" :foreground "#515151" :background "#e0e0e0")) 35 | :focused 36 | #s(hash-table test equal data 37 | (:strings "#6e6e6e" :alt "#828282" :assumed "#5f5f5f" :primary "#6e6e6e" 38 | :faded "#828282" :foreground "#535353" :background "#e4e4e4")) 39 | :normal 40 | #s(hash-table test equal data 41 | (:strings "#777777" :alt "#8c8c8c" :assumed "#686868" :primary "#777777" 42 | :faded "#8c8c8c" :foreground "#5c5c5c" :background "#f3f3f3")) 43 | :meta 44 | #s(hash-table test equal data 45 | (:diff-remove-highlight "#f2cbd1" :diff-add-highlight "#abf68d" :diff-remove 46 | "#f6dce0" :diff-add "#d8face")))) 47 | myron-kobo 48 | #s(hash-table test equal data 49 | (:focused 50 | #s(hash-table test equal data 51 | (:primary "#5a5f00" :faded "#5f5a57" :alt "#6e7400" :strings "#6e7400" 52 | :assumed "#4b4643" :foreground "#4b4643" :background "#ccc7c4")) 53 | :strong 54 | #s(hash-table test equal data 55 | (:primary "#595e00" :faded "#5e5956" :alt "#6c7100" :strings "#6c7100" 56 | :assumed "#4a4542" :foreground "#4a4542" :background "#cac5c2")) 57 | :weak 58 | #s(hash-table test equal data 59 | (:primary "#666b00" :faded "#6b6663" :alt "#7a8000" :strings "#7a8000" 60 | :assumed "#57524f" :foreground "#57524f" :background "#ded9d6")) 61 | :normal 62 | #s(hash-table test equal data 63 | (:primary "#626700" :faded "#67625f" :alt "#757b00" :strings "#757b00" 64 | :assumed "#524d4a" :foreground "#524d4a" :background "#d7d2cf")) 65 | :meta 66 | #s(hash-table test equal data 67 | (:diff-remove-highlight "#efbac3" :diff-add-highlight "#95ea74" :diff-remove 68 | "#eeb4be" :diff-add "#92e572")))) 69 | myron-mcfay 70 | #s(hash-table test equal data 71 | (:focused 72 | #s(hash-table test equal data 73 | (:background "#a6d0ed" :foreground "#0c3653" :faded "#335d7a" :primary 74 | "#ad0066" :assumed "#0055b8" :alt "#005f87" :strings "#006c00")) 75 | :normal 76 | #s(hash-table test equal data 77 | (:background "#e8ebec" :foreground "#444748" :faded "#6a6d6e" :primary 78 | "#c6007f" :assumed "#0065c8" :alt "#006e96" :strings "#007c00")) 79 | :weak 80 | #s(hash-table test equal data 81 | (:background "#d6d7d8" :foreground "#3a3b3c" :faded "#606162" :primary 82 | "#bb0074" :assumed "#005ec1" :alt "#006890" :strings "#007500")) 83 | :strong 84 | #s(hash-table test equal data 85 | (:background "#cdcacb" :foreground "#353233" :faded "#5b5859" :primary 86 | "#ae0067" :assumed "#0055b8" :alt "#005f87" :strings "#006d00")) 87 | :meta 88 | #s(hash-table test equal data 89 | (:diff-remove-highlight "#f0c0c8" :diff-add-highlight "#9bef7b" :diff-remove 90 | "#f4d2d7" :diff-add "#bbf8a7")))) 91 | myron-room 92 | #s(hash-table test equal data 93 | (:strong 94 | #s(hash-table test equal data 95 | (:strings "#a66300" :alt "#0094ab" :assumed "#474747" :primary "#007e97" 96 | :faded "#747474" :foreground "#474747" :background "#d0d0d0")) 97 | :weak 98 | #s(hash-table test equal data 99 | (:strings "#b56800" :alt "#009eb5" :assumed "#4f4f4f" :primary "#00879f" 100 | :faded "#7d7d7d" :foreground "#4f4f4f" :background "#dddddd")) 101 | :normal 102 | #s(hash-table test equal data 103 | (:strings "#cb7000" :alt "#00acc3" :assumed "#5a5a5a" :primary "#0095ac" 104 | :faded "#8a8a8a" :foreground "#5a5a5a" :background "#f0f0f0")) 105 | :focused 106 | #s(hash-table test equal data 107 | (:strings "#626d1e" :alt "#9454ff" :assumed "#6e4338" :primary "#803bea" 108 | :faded "#9e7368" :foreground "#6e4338" :background "#fed3c8")) 109 | :meta 110 | #s(hash-table test equal data 111 | (:diff-remove-highlight "#f1c8ce" :diff-add-highlight "#a3f483" :diff-remove 112 | "#f5d9dd" :diff-add "#cff9c2")))) 113 | myron-storm 114 | #s(hash-table test equal data 115 | (:normal 116 | #s(hash-table test equal data 117 | (:background "#e3f0ed" :foreground "#697673" :faded "#7e8b88" :primary 118 | "#a356a4" :assumed "#108082" :strings "#0e8618" :alt "#a95e5b")) 119 | :weak 120 | #s(hash-table test equal data 121 | (:background "#ccd9d6" :foreground "#5b6865" :faded "#6e7b78" :primary 122 | "#924894" :assumed "#067074" :strings "#05760f" :alt "#984f49")) 123 | :strong 124 | #s(hash-table test equal data 125 | (:background "#c3d0cd" :foreground "#55625f" :faded "#687572" :primary 126 | "#8b418d" :assumed "#026a6f" :strings "#006f0a" :alt "#924942")) 127 | :focused 128 | #s(hash-table test equal data 129 | (:background "#ecccec" :foreground "#7a5a7a" :faded "#8e6e8e" :primary 130 | "#a74908" :assumed "#a74446" :strings "#a138a1" :alt "#00716d")) 131 | :meta 132 | #s(hash-table test equal data 133 | (:diff-remove-highlight "#efc0c8" :diff-add-highlight "#99f078" :diff-remove 134 | "#f4d5da" :diff-add "#c5f9b5")))) 135 | myron-struan 136 | #s(hash-table test equal data 137 | (:normal 138 | #s(hash-table test equal data 139 | (:strings "#677400" :alt "#916156" :assumed "#2a7783" :primary "#8f5d7f" 140 | :faded "#a35a29" :foreground "#544b45" :background "#f2e9e3")) 141 | :weak 142 | #s(hash-table test equal data 143 | (:strings "#5b6700" :alt "#845449" :assumed "#1d6a76" :primary "#825072" 144 | :faded "#a93b2f" :foreground "#483f3e" :background "#ded5d4")) 145 | :strong 146 | #s(hash-table test equal data 147 | (:strings "#535f00" :alt "#7d4d42" :assumed "#15626e" :primary "#7b496b" 148 | :faded "#a1276b" :foreground "#40373c" :background "#d2c9ce")) 149 | :focused 150 | #s(hash-table test equal data 151 | (:strings "#677400" :alt "#916156" :assumed "#2a7783" :primary "#8f5d7f" 152 | :faded "#a35a29" :foreground "#544b45" :background "#e1c5c0")) 153 | :meta 154 | #s(hash-table test equal data 155 | (:diff-remove-highlight "#f0c0c8" :diff-add-highlight "#9aef7b" :diff-remove 156 | "#f4d2d7" :diff-add "#bbf8a9"))))) 157 | "Cache value for the themes. Internal use only.") 158 | (provide 'myron-themes-cache) -------------------------------------------------------------------------------- /myron-themes.el: -------------------------------------------------------------------------------- 1 | ;;; myron-themes.el --- A collection of light color themes -*- coding: utf-8; lexical-binding: t -*- 2 | ;; Copyright (C) 2025 neeasade 3 | ;; SPDX-License-Identifier: MIT 4 | ;; Author: neeasade 5 | ;; URL: https://github.com/neeasade/myron-themes 6 | ;; Package-Requires: ((emacs "25.1") (ct "0.3") (helpful "0.19") (ht "2.3") (base16-theme "3.0")) 7 | ;; Version: 0.1 8 | 9 | ;;; Commentary: 10 | ;; A set of color themes built on top of the base16-themes. 11 | 12 | ;;; Code: 13 | 14 | (require 'base16-theme) 15 | (require 'ct) 16 | (require 'helpful) 17 | (require 'ht) 18 | (require 'myron-themes-cache) 19 | 20 | (defvar myron-themes-colors nil "The color values for the loaded myron theme.") 21 | 22 | (defgroup myron-themes nil 23 | "Myron color themes for EMACS." 24 | :group 'myron-themes 25 | :prefix "myron-themes") 26 | 27 | (defcustom myron-themes-use-cache t 28 | "A toggle to use the colors as authored. 29 | 30 | To compute the colors on your machine, set to nil." 31 | :type 'boolean 32 | :group 'myron) 33 | 34 | (defun myron-themes-get (label &optional background-emphasis) 35 | "Get the color value of LABEL on some BACKGROUND-EMPHASIS." 36 | (or (ht-get* myron-themes-colors (or background-emphasis :normal) label) 37 | (when (not background-emphasis) (ht-get* myron-themes-colors :meta label)))) 38 | 39 | (defun myron-themes--show-contrast-against (bg-level) 40 | "Show contrast levels of fg colors in myron-themes-colors against BG-LEVEL." 41 | (-map (lambda (fg-label) 42 | (-let* ((foreground (myron-themes-get fg-label bg-level)) 43 | (background (myron-themes-get :background bg-level)) 44 | (contrast-ratio (ct-contrast-ratio foreground background))) 45 | (format "%s %.1f %s" foreground contrast-ratio fg-label))) 46 | '(:foreground :faded :primary :assumed :alt :strings))) 47 | 48 | (defun myron-themes-show-contrasts () 49 | "Message the contrast ratios of colors of different background emphasis levels." 50 | (interactive) 51 | (->> '(:focused :strong :weak :normal) 52 | (-map (-juxt 'identity (-partial 'myron-themes-get :background))) 53 | (-mapcat 54 | (-lambda ((bg-level bg-color)) 55 | `(,(format "Against background %s %s" bg-level bg-color) 56 | ,@(myron-themes--show-contrast-against bg-level) 57 | "------"))) 58 | (--map (concat it "\n")) 59 | (apply 'concat) 60 | (message))) 61 | 62 | (defun myron-themes-to-base16 (&optional emphasis) 63 | "Return `myron-themes-colors' colors as a base16 plist using EMPHASIS." 64 | (-let* ((emphasis (or emphasis :normal)) 65 | (background-f (myron-themes-get :background :focused)) 66 | ((&hash :alt :strings :assumed :primary :faded :foreground :background) (ht-get myron-themes-colors emphasis))) 67 | ;; The comments on the sections here are from the base16 styling guidelines, not necessarily 68 | ;; what the emacs base16 theme package follows (observations commented following ":"). 69 | ;; guidelines location: http://chriskempson.com/projects/base16/ 70 | (list 71 | :base00 background ;; Default Background 72 | :base01 background-f ;; search match, Lighter Background (Used for status bars) : search bg 73 | :base02 background-f ;; Selection Background 74 | :base03 faded ;; Comments, Invisibles, Line Highlighting 75 | :base04 faded ;; Dark Foreground (Used for status bars) : paren-face 76 | :base05 foreground ;; Default Foreground, Caret, Delimiters, Operators 77 | :base06 faded ;; Light Foreground (Not often used) 78 | :base07 background ;; Light Background (Not often used) : nb. unused 79 | :base08 alt ;; Variables, XML Tags, Markup Link Text, Markup Lists, Diff Deleted : org-todo 80 | :base09 foreground ;; Integers, Boolean, Constants, XML Attributes, Markup Link Url 81 | :base0A alt ;; Types, Classes, Markup Bold, Search Text Background 82 | :base0B strings ;; Strings, Inherited Class, Markup Code, Diff Inserted 83 | :base0C assumed ;; Support, Regular Expressions, Escape Characters, Markup Quotes 84 | :base0D primary ;; Functions, Methods, Attribute IDs, Headings : search fg, prompt 85 | :base0E assumed ;; Keywords, Storage, Selector, Markup Italic, Diff Changed : org-date, keyword 86 | :base0F faded ;; Deprecated, Opening/Closing Embedded Language Tags, e.g. : used as fg in various smol places 87 | ))) 88 | 89 | (defun myron-themes--get-function-sexp (sym) 90 | "Get SYM as a quoted list, using helpful.el." 91 | (read (seq-let (buffer point _) (helpful--definition sym t) 92 | (helpful--source sym t buffer point)))) 93 | 94 | (defun myron-themes--markup-map () 95 | "List of org faces to markup-faces for non-org modes." 96 | '( 97 | ;; HEADINGS 98 | org-level-1 (adoc-title-0-face markdown-header-face-1 rst-level-1) 99 | org-level-2 (adoc-title-1-face markdown-header-face-2 rst-level-2) 100 | org-level-3 (adoc-title-2-face markdown-header-face-3 rst-level-3) 101 | org-level-4 (adoc-title-3-face markdown-header-face-4 rst-level-4) 102 | org-level-5 (adoc-title-4-face markdown-header-face-5 rst-level-5) 103 | 104 | ;; the leading #'s of the headings in markdown 105 | ;; using org-level-4 so it's not thicc on nested markdown headings 106 | org-level-4 (markdown-header-delimiter-face) 107 | 108 | ;; INLINE CODE 109 | ;; nb: rst-literal applies for both inline-code and blocks of code 110 | org-code (adoc-typewriter-face markdown-inline-code-face) 111 | 112 | ;; BLOCKS OF CODE 113 | org-block (adoc-verbatim-face adoc-native-code-face adoc-code-face markdown-code-face rst-literal) 114 | 115 | ;; BUILTINS/META 116 | bold (adoc-bold-face markdown-bold-face rst-emphasis2) 117 | italic (adoc-emphasis-face rst-emphasis1) 118 | 119 | org-meta-line (adoc-complex-replacement-face 120 | adoc-meta-hide-face 121 | markdown-markup-face 122 | adoc-markup-face ; maybe? 123 | adoc-meta-face 124 | rst-directive 125 | rst-adornment) 126 | 127 | ;; non-org modes make the distinction between labels and destinations 128 | ;; org mode when showing link markup treats url/dest as default face, so I'm choosing to match that 129 | default (adoc-internal-reference-face markdown-url-face) 130 | org-link (adoc-reference-face 131 | markdown-link-face 132 | rst-reference 133 | rst-external 134 | lui-button-face 135 | button) 136 | 137 | ;; org list elements have no face 138 | default (markdown-list-face adoc-list-face rst-block) 139 | 140 | org-checkbox markdown-gfm-checkbox-face)) 141 | 142 | (defun myron-themes--make-faces (&optional theme-overrides) 143 | "Make the face->color map for the current theme. 144 | 145 | Optionally transform colors with a THEME-OVERRIDES function." 146 | (let* 147 | ( 148 | ;; steal the list that's hardcoded in base16-theme-define 149 | ;; cf https://github.com/belak/base16-emacs/blob/93b1513a9994355492314e809cdbfb0d21f1e30d/base16-theme.el#L186 150 | (original-theme (->> (myron-themes--get-function-sexp 'base16-theme-define) 151 | (nth 4) 152 | (nth 3) 153 | (-second-item))) 154 | 155 | ;; todo: consider it might be more natural to create normal_faded, 156 | ;; strong_background aliases instead of calling myron-themes-get througout 157 | ;; this section (eg consistency with theme-overrides) 158 | 159 | ;; note individual changes 160 | (theme-changes 161 | `( 162 | (cursor :background primary) 163 | (fringe :background unspecified) 164 | 165 | (font-lock-comment-delimiter-face :foreground faded) 166 | (font-lock-comment-face :background unspecified) 167 | 168 | ((window-divider vertical-border) :foreground faded) 169 | 170 | ;; identity 171 | (font-lock-function-name-face :foreground primary) 172 | (font-lock-variable-name-face :foreground primary) 173 | 174 | ((outline-1 outline-2 outline-3 outline-4 outline-5) :foreground foreground) 175 | ((whitespace-space whitespace-tab) :background unspecified) 176 | ((org-date flycheck-warning flycheck-info) :underline unspecified) 177 | 178 | (secondary-selection :background ,(myron-themes-get :background :strong)) 179 | 180 | (parenthesis :foreground faded) 181 | 182 | (prescient-primary-highlight :foreground alt) 183 | ;; maybe this should be assumed or primary 184 | (prescient-secondary-highlight :foreground strings) 185 | 186 | ((orderless-match-face-0 orderless-match-face-1 orderless-match-face-2 orderless-match-face-3) 187 | :foreground alt) 188 | 189 | (completions-common-part :foreground ,(myron-themes-get :alt :weak)) ; weak for corfu popup 190 | 191 | (magit-diff-context-highlight :background ,(myron-themes-get :background :weak)) 192 | 193 | ;; todo: this appears to not be doing anything 194 | ;; (magit-diff-file-heading :extend t) 195 | (corfu-bar :background faded) 196 | (company-tooltip-scrollbar-thumb :background faded) 197 | (company-tooltip-scrollbar-track :background ,(myron-themes-get :background :weak)) 198 | 199 | (completions-annotations :foreground faded) 200 | 201 | ((magit-diff-hunk-heading magit-diff-hunk-heading-highlight) :extend unspecified) 202 | 203 | (magit-diff-hunk-heading :background ,(myron-themes-get :background :strong)) 204 | (magit-diff-hunk-heading-highlight :background ,(myron-themes-get :background :focused)) 205 | (magit-diff-added :background ,(myron-themes-get :diff-add)) 206 | (magit-diff-removed :background ,(myron-themes-get :diff-remove)) 207 | (magit-diff-added-highlight :background ,(myron-themes-get :diff-add-highlight)) 208 | (magit-diff-removed-highlight :background ,(myron-themes-get :diff-remove-highlight)) 209 | 210 | ,@(-map 211 | (-lambda ((face back-label fore-label)) 212 | (->> `(,face :inverse-video nil 213 | :background ,(myron-themes-get :background back-label) 214 | :foreground ,(myron-themes-get (or fore-label :foreground) back-label)))) 215 | `( 216 | ;; (avy-lead-face :strong :primary) 217 | ;; (avy-lead-face-0 :strong :assumed) 218 | ;; (avy-lead-face-1 :strong :alt) 219 | ;; (avy-lead-face-2 :strong :strings) 220 | 221 | ;; maybe button? a button-active notion? 222 | (avy-lead-face :strong :assumed) 223 | (avy-lead-face-0 :strong :assumed) 224 | (avy-lead-face-1 :strong :assumed) 225 | (avy-lead-face-2 :strong :assumed) 226 | 227 | (eros-result-overlay-face :strong) 228 | (cider-result-overlay-face :strong) 229 | 230 | (comint-highlight-prompt :normal :assumed) 231 | 232 | (tooltip :weak) 233 | 234 | (lsp-ui-sideline-global :weak :alt) 235 | (lsp-ui-sideline-current-symbol :weak :alt) 236 | 237 | (magit-blame-heading :weak) 238 | 239 | ;; focus bois 240 | ,@(--map (list it :focused) 241 | '(show-paren-match show-paren-match-expression 242 | line-number-current-line 243 | corfu-current ivy-current-match isearch)) 244 | 245 | ;; all the org builtin stuff: 246 | ;; this assumes sort of a soft alt, 247 | ;; faded might be more appropriate, 248 | ;; but then intent gets mixed with commenting 249 | (org-drawer :normal :alt) 250 | (org-meta-line :normal :alt) 251 | (org-document-info-keyword :normal :alt) 252 | 253 | (org-todo :strong :strings) 254 | (org-headline-todo :normal) 255 | 256 | (org-done :weak :faded) 257 | (org-headline-done :normal :faded) 258 | 259 | (mode-line-inactive :weak) 260 | (mode-line :strong) 261 | 262 | (lazy-highlight :strong) 263 | 264 | (org-link :weak :alt) 265 | (org-code :weak) 266 | 267 | (org-block :normal) 268 | (org-block-begin-line :normal) 269 | (org-block-end-line :normal) 270 | 271 | ;; todo: only want this if we can get (:extend t) to work above 272 | ;; (magit-diff-file-heading :strong) 273 | 274 | (diff-header :strong) 275 | (diff-hunk-header :strong) 276 | (diff-function :strong) 277 | (diff-file-header :weak) 278 | 279 | (line-number :weak :faded))) 280 | 281 | ;; inheritors 282 | ,@(-mapcat 283 | (-lambda ((parent children)) 284 | (--map (apply 'list it :inherit parent 285 | (--mapcat (list it 'unspecified) 286 | '(:foreground :background :underline :box :height))) 287 | (-list children))) 288 | (-partition 2 289 | `( 290 | ,@(myron-themes--markup-map) 291 | 292 | tooltip (corfu-default) 293 | 294 | ;; diff consistency: 295 | default smerge-markers 296 | 297 | magit-diff-added (diff-added smerge-upper) 298 | magit-diff-removed (diff-removed smerge-lower) 299 | 300 | magit-diff-added-highlight (diff-refine-added smerge-refined-added) 301 | magit-diff-removed-highlight (diff-refine-removed smerge-refined-removed) 302 | 303 | ;; abuse diff colors in other contexts for consistency: 304 | 305 | ;; success: 306 | magit-diff-added cider-test-success-face 307 | 308 | ;; failure: 309 | magit-diff-removed (whitespace-line) 310 | magit-diff-removed-highlight (cider-error-overlay-face 311 | cider-test-error-face 312 | cider-test-failure-face 313 | error 314 | show-paren-mismatch)))) 315 | 316 | ,@theme-overrides)) 317 | 318 | ;; allow multi-face, multi-attr conf 319 | (theme-changes 320 | (->> theme-changes 321 | (-mapcat (-lambda ((faces . kvs)) 322 | (-map (lambda (face) `(,face ,@kvs)) 323 | (-list faces)))) 324 | (-mapcat (-lambda ((face . kvs)) 325 | (-map (lambda (kv) `(,face ,@kv)) 326 | (-partition 2 kvs)))))) 327 | 328 | (new-theme 329 | ;; apply our individual changes to the original theme 330 | (-reduce-from 331 | (-lambda (state (face key value)) 332 | (if (-contains-p (-map #'-first-item state) face) 333 | (-map (lambda (entry) 334 | (if (eq (-first-item entry) face) 335 | `(,face ,@(plist-put (cdr entry) key value)) 336 | entry)) 337 | state) 338 | (cons (list face key value) state))) 339 | original-theme 340 | theme-changes))) 341 | 342 | ;; original-theme 343 | new-theme)) 344 | 345 | 346 | 347 | (defun myron-themes-termcolors () 348 | "Export current myron theme to a list of terminal colors." 349 | ;; stealing default base16 export order for now 350 | (--map (plist-get (myron-themes-to-base16) it) 351 | '(:base00 :base08 :base0B :base0A :base0D :base0E :base0C :base05 352 | :base03 :base09 :base01 :base02 :base04 :base06 :base0F :base07))) 353 | 354 | (defun myron-themes--create-meta-colors (colors) 355 | "Add the meta color table to COLORS." 356 | 357 | (ht-set! colors 358 | :meta 359 | (-let* (((bg bg-weak _) (--map (ht-get* colors it :background) '(:normal :weak :strong))) 360 | ;; (color-strings (ht-get* colors :normal :strings)) 361 | ;; (strings-hue (ct-get-hsluv-h (ht-get* colors :normal :strings))) 362 | (green (ct-make-hsluv 120 70 (ct-get-hsluv-l bg))) 363 | ;; a little oomf 364 | (red (ct-make-hsluv 0 70 (- (ct-get-hsluv-l bg) 5))) 365 | (light-delta (apply '- (-map 'ct-get-hsluv-l (list bg bg-weak)))) 366 | (light-delta (* 0.7 light-delta)) 367 | (dark-green (ct-edit-hsluv-l-dec green light-delta)) 368 | (dark-red (ct-edit-hsluv-l-dec red light-delta)) 369 | ((green red dark-green dark-red) (--map (ct-edit-hsluv-l-dec it 0.5) 370 | (list green red dark-green dark-red)))) 371 | (ht<-plist 372 | `(:diff-add ,green 373 | :diff-remove ,red 374 | :diff-add-highlight ,dark-green 375 | :diff-remove-highlight ,dark-red 376 | ;; :interactive-background ,(ct-aedit-hsluv bg-weak (list strings-hue 5 l)) 377 | ;; :interactive-background-highlight ,(ct-aedit-hsluv bg-strong (list strings-hue 5 l)) 378 | 379 | ;; todo: instead of percent, perhaps this should be based on a distance of some sort 380 | :subtle ,(ct-lessen (ht-get* colors :normal :background) 3))))) 381 | colors) 382 | 383 | (defun myron-themes--define (theme-name &optional theme-overrides) 384 | "Define theme THEME-NAME, optionally change faces with function THEME-OVERRIDES." 385 | (setq myron-themes-colors (if myron-themes-use-cache 386 | (plist-get myron-themes-cache theme-name) 387 | (myron-themes--create-meta-colors 388 | (funcall (intern (format "%s-create" theme-name)))))) 389 | 390 | (base16-theme-set-faces theme-name 391 | (append (myron-themes-to-base16) (ht-to-plist (ht-get myron-themes-colors :normal))) 392 | (myron-themes--make-faces theme-overrides)) 393 | 394 | (custom-theme-set-variables theme-name 395 | `(ansi-color-names-vector ,(apply 'vector (-take 8 (myron-themes-termcolors)))))) 396 | 397 | ;;;###autoload 398 | (when (and (boundp 'custom-theme-load-path) load-file-name) 399 | (let* ((base (file-name-directory load-file-name)) 400 | (dir (expand-file-name "themes/" base))) 401 | (add-to-list 'custom-theme-load-path 402 | (or (and (file-directory-p dir) dir) 403 | base)))) 404 | 405 | (provide 'myron-themes) 406 | ;;; myron-themes.el ends here 407 | --------------------------------------------------------------------------------