| 1 | ;;; darkmatter-theme.el --- Darkmatter on base16 -*- lexical-binding: t; -*- |
| 2 | |
| 3 | ;; https://darkmattertheme.com |
| 4 | ;; Palette + a few overrides on top of `base16-theme' (package base16-theme). |
| 5 | ;; The 16 slots are mapped to match the old doom-darkmatter roles. |
| 6 | |
| 7 | (require 'cl-lib) |
| 8 | (require 'base16-theme) |
| 9 | |
| 10 | ;;; Palette -- edit these and everything below follows |
| 11 | |
| 12 | (defun darkmatter--blend (a b alpha) |
| 13 | "Mix hex colors A and B; ALPHA is the share of B (0..1)." |
| 14 | (cl-flet ((rgb (c) (mapcar (lambda (i) (string-to-number (substring c i (+ i 2)) 16)) |
| 15 | '(1 3 5)))) |
| 16 | (apply #'format "#%02x%02x%02x" |
| 17 | (cl-mapcar (lambda (x y) (round (+ (* x (- 1 alpha)) (* y alpha)))) |
| 18 | (rgb a) (rgb b))))) |
| 19 | |
| 20 | (defvar darkmatter-palette |
| 21 | '((base00 . "#121113") ; background |
| 22 | (base01 . "#121212") ; lighter background |
| 23 | (base02 . "#222222") ; selection |
| 24 | (base03 . "#333333") ; comments |
| 25 | (base04 . "#999999") ; dark foreground, doc strings |
| 26 | (base05 . "#c1c1c1") ; foreground |
| 27 | (base06 . "#999999") ; light foreground |
| 28 | (base07 . "#c1c1c1") ; lightest |
| 29 | (base08 . "#5f8787") ; variables, errors |
| 30 | (base09 . "#aaaaaa") ; constants, numbers |
| 31 | (base0A . "#e78a53") ; types, accent, warnings |
| 32 | (base0B . "#fbcb97") ; strings, added |
| 33 | (base0C . "#aaaaaa") ; builtins, support |
| 34 | (base0D . "#888888") ; functions |
| 35 | (base0E . "#999999") ; keywords |
| 36 | (base0F . "#444444") ; deprecated |
| 37 | (red . "#aa6c6c")) ; extra: removed lines, ERC errors (not a base16 slot) |
| 38 | "Darkmatter colors. Base16 slots plus `red'. Everything else is derived.") |
| 39 | |
| 40 | (deftheme darkmatter "Darkmatter, based on Black Metal Bathory.") |
| 41 | |
| 42 | (let* ((base00 (alist-get 'base00 darkmatter-palette)) |
| 43 | (base01 (alist-get 'base01 darkmatter-palette)) |
| 44 | (base02 (alist-get 'base02 darkmatter-palette)) |
| 45 | (base03 (alist-get 'base03 darkmatter-palette)) |
| 46 | (base04 (alist-get 'base04 darkmatter-palette)) |
| 47 | (base05 (alist-get 'base05 darkmatter-palette)) |
| 48 | (base06 (alist-get 'base06 darkmatter-palette)) |
| 49 | (base07 (alist-get 'base07 darkmatter-palette)) |
| 50 | (base08 (alist-get 'base08 darkmatter-palette)) |
| 51 | (base09 (alist-get 'base09 darkmatter-palette)) |
| 52 | (base0A (alist-get 'base0A darkmatter-palette)) |
| 53 | (base0B (alist-get 'base0B darkmatter-palette)) |
| 54 | (base0C (alist-get 'base0C darkmatter-palette)) |
| 55 | (base0D (alist-get 'base0D darkmatter-palette)) |
| 56 | (base0E (alist-get 'base0E darkmatter-palette)) |
| 57 | (base0F (alist-get 'base0F darkmatter-palette)) |
| 58 | (red (alist-get 'red darkmatter-palette)) |
| 59 | ;; roles used by the face overrides below |
| 60 | (bg base00) |
| 61 | (bg-alt base01) |
| 62 | (sel base02) |
| 63 | (comment base03) |
| 64 | (dim base04) |
| 65 | (fg base05) |
| 66 | (fg-hi base06) |
| 67 | (fg-max base07) |
| 68 | (teal base08) |
| 69 | (const base09) |
| 70 | (orange base0A) |
| 71 | (string base0B) |
| 72 | (func base0D) |
| 73 | (kw base0E) |
| 74 | (dep base0F) |
| 75 | ;; derived |
| 76 | (base0 (darkmatter--blend bg "#000000" 0.4)) |
| 77 | (faint (darkmatter--blend bg-alt kw 0.2)) |
| 78 | (muted (darkmatter--blend bg dim 0.45)) |
| 79 | (bg-tint (darkmatter--blend bg const 0.15)) |
| 80 | (added-fg (darkmatter--blend string "#000000" 0.2)) |
| 81 | (added-bg (darkmatter--blend bg string 0.1)) |
| 82 | (added-bg-hi (darkmatter--blend bg string 0.2)) |
| 83 | (removed-bg (darkmatter--blend sel red 0.1)) |
| 84 | (removed-bg-hi (darkmatter--blend sel red 0.2)) |
| 85 | (changed-bg (darkmatter--blend bg orange 0.1)) |
| 86 | (changed-bg-hi (darkmatter--blend bg orange 0.2)) |
| 87 | (red-dark (darkmatter--blend red "#000000" 0.2)) |
| 88 | (orange-dark (darkmatter--blend orange "#000000" 0.2))) |
| 89 | |
| 90 | ;; Fringe/line numbers share the main background, like doom-darkmatter |
| 91 | (setq base16-theme-distinct-fringe-background nil) |
| 92 | ;; In a tty base16 defaults to the terminal's ANSI palette by name |
| 93 | ;; (base02 -> brightyellow, i.e. orange in ghostty), so map our hex |
| 94 | ;; colors to the nearest 256-color instead. |
| 95 | (setq base16-theme-256-color-source 'colors) |
| 96 | |
| 97 | (base16-theme-define |
| 98 | 'darkmatter |
| 99 | (list :base00 base00 :base01 base01 :base02 base02 :base03 base03 |
| 100 | :base04 base04 :base05 base05 :base06 base06 :base07 base07 |
| 101 | :base08 base08 :base09 base09 :base0A base0A :base0B base0B |
| 102 | :base0C base0C :base0D base0D :base0E base0E :base0F base0F)) |
| 103 | |
| 104 | ;; Where doom-darkmatter differs from stock base16 role assignments, |
| 105 | ;; plus packages base16 has no faces for |
| 106 | (custom-theme-set-faces |
| 107 | 'darkmatter |
| 108 | `(cursor ((t (:background ,orange)))) |
| 109 | `(font-lock-variable-name-face ((t (:foreground ,teal)))) |
| 110 | `(font-lock-builtin-face ((t (:foreground ,kw)))) |
| 111 | `(font-lock-constant-face ((t (:foreground ,const)))) |
| 112 | `(font-lock-number-face ((t (:foreground ,const)))) |
| 113 | `(font-lock-warning-face ((t (:foreground ,orange)))) |
| 114 | `(mode-line ((t (:foreground ,fg :background ,bg :overline ,sel :box nil)))) |
| 115 | `(mode-line-inactive ((t (:foreground ,dim :background ,bg :overline ,sel :box nil)))) |
| 116 | `(mode-line-buffer-id ((t (:foreground ,fg :weight bold)))) |
| 117 | `(line-number ((t (:foreground ,faint :background ,bg)))) |
| 118 | `(line-number-current-line ((t (:foreground ,orange :background ,bg)))) |
| 119 | `(vertical-border ((t (:foreground ,sel)))) |
| 120 | `(erc-prompt-face ((t (:foreground ,orange :weight bold)))) |
| 121 | ;; base16 uses base01 for highlight, which is ~identical to bg here |
| 122 | `(highlight ((t (:background ,sel)))) |
| 123 | `(icomplete-selected-match ((t (:foreground ,orange :background ,sel :weight bold :extend t)))) |
| 124 | `(completions-highlight ((t (:inherit icomplete-selected-match)))) |
| 125 | ;; base16 makes this inherit gnus-group-news-6, whose default spec |
| 126 | ;; inherits this face back -> cycle error in enable-theme |
| 127 | `(gnus-group-news-6-empty ((t (:foreground ,base04 :inherit outline-2)))) |
| 128 | ;; base16 only themes the normal 8; bright ones (used by ghostel etc.) |
| 129 | ;; fall back to Emacs defaults. Match the darkmatter ghostty palette. |
| 130 | `(ansi-color-bright-black ((t (:foreground ,base03 :background ,base03)))) |
| 131 | `(ansi-color-bright-red ((t (:foreground ,base08 :background ,base08)))) |
| 132 | `(ansi-color-bright-green ((t (:foreground ,base0B :background ,base0B)))) |
| 133 | `(ansi-color-bright-yellow ((t (:foreground ,base0A :background ,base0A)))) |
| 134 | `(ansi-color-bright-blue ((t (:foreground ,base0D :background ,base0D)))) |
| 135 | `(ansi-color-bright-magenta ((t (:foreground ,base0E :background ,base0E)))) |
| 136 | `(ansi-color-bright-cyan ((t (:foreground ,base0C :background ,base0C)))) |
| 137 | `(ansi-color-bright-white ((t (:foreground ,base07 :background ,base07)))) |
| 138 | |
| 139 | ;; Packages base16 has no faces for |
| 140 | `(elfeed-search-date-face ((t (:foreground ,const)))) |
| 141 | `(elfeed-search-feed-face ((t (:foreground ,func)))) |
| 142 | `(elfeed-search-tag-face ((t (:foreground ,comment)))) |
| 143 | `(elfeed-search-title-face ((t (:foreground ,comment)))) |
| 144 | `(elfeed-search-unread-title-face ((t (:foreground ,fg :weight bold)))) |
| 145 | `(elfeed-search-unread-count-face ((t (:foreground ,orange)))) |
| 146 | `(elfeed-search-filter-face ((t (:foreground ,const)))) |
| 147 | `(elfeed-log-debug-level-face ((t (:foreground ,comment)))) |
| 148 | `(elfeed-log-error-level-face ((t (:inherit error)))) |
| 149 | `(elfeed-log-info-level-face ((t (:inherit success)))) |
| 150 | `(elfeed-log-warn-level-face ((t (:inherit warning)))) |
| 151 | `(which-key-key-face ((t (:foreground ,orange)))) |
| 152 | `(which-key-group-description-face ((t (:foreground ,kw)))) |
| 153 | `(which-key-command-description-face ((t (:foreground ,fg))))) |
| 154 | |
| 155 | ;; Magit/diff/org/vc faces, flattened from doom-darkmatter |
| 156 | (custom-theme-set-faces |
| 157 | 'darkmatter |
| 158 | `(diff-hl-change ((t (:foreground "#e78a53" :background "#e78a53")))) |
| 159 | `(diff-hl-delete ((t (:foreground "#aa6c6c" :background "#aa6c6c")))) |
| 160 | `(diff-hl-insert ((t (:foreground "#fbcb97" :background "#fbcb97")))) |
| 161 | `(diff-added ((t (:inherit hl-line :foreground ,string)))) |
| 162 | `(diff-changed ((t (:foreground ,const)))) |
| 163 | `(diff-context ((t (:foreground ,const)))) |
| 164 | `(diff-removed ((t (:foreground ,red :background ,sel)))) |
| 165 | `(diff-header ((t (:foreground ,const)))) |
| 166 | `(diff-file-header ((t (:foreground ,func)))) |
| 167 | `(diff-hunk-header ((t (:foreground ,const)))) |
| 168 | `(diff-indicator-added ((t (:foreground ,string)))) |
| 169 | `(diff-indicator-changed ((t (:foreground ,orange)))) |
| 170 | `(diff-indicator-removed ((t (:foreground ,red)))) |
| 171 | `(diff-refine-added ((t (:inherit diff-added :inverse-video t)))) |
| 172 | `(diff-refine-changed ((t (:inherit diff-changed :inverse-video t)))) |
| 173 | `(diff-refine-removed ((t (:inherit diff-removed :inverse-video t)))) |
| 174 | `(ediff-fine-diff-A ((t (:inherit diff-refine-removed)))) |
| 175 | `(ediff-fine-diff-B ((t (:inherit diff-refine-added)))) |
| 176 | `(ediff-fine-diff-C ((t (:inherit ediff-fine-diff-A)))) |
| 177 | `(ediff-current-diff-A ((t (:foreground ,red :background ,removed-bg-hi :extend t)))) |
| 178 | `(ediff-current-diff-B ((t (:foreground ,string :background ,added-bg-hi :extend t)))) |
| 179 | `(ediff-current-diff-C ((t (:inherit ediff-current-diff-A)))) |
| 180 | `(ediff-even-diff-A ((t (:inherit hl-line)))) |
| 181 | `(ediff-even-diff-B ((t (:inherit ediff-even-diff-A)))) |
| 182 | `(ediff-even-diff-C ((t (:inherit ediff-even-diff-A)))) |
| 183 | `(ediff-odd-diff-A ((t (:inherit ediff-even-diff-A)))) |
| 184 | `(ediff-odd-diff-B ((t (:inherit ediff-odd-diff-A)))) |
| 185 | `(ediff-odd-diff-C ((t (:inherit ediff-odd-diff-A)))) |
| 186 | `(git-commit-summary ((t (:foreground ,string)))) |
| 187 | `(git-commit-overlong-summary ((t (:inherit error :background ,base0 :slant italic :weight bold)))) |
| 188 | `(git-commit-nonempty-second-line ((t (:inherit git-commit-overlong-summary)))) |
| 189 | `(git-commit-keyword ((t (:foreground ,const :slant italic)))) |
| 190 | `(git-commit-pseudo-header ((t (:foreground ,dim :slant italic)))) |
| 191 | `(git-commit-known-pseudo-header ((t (:foreground ,dim :weight bold :slant italic)))) |
| 192 | `(git-commit-comment-branch-local ((t (:foreground ,kw)))) |
| 193 | `(git-commit-comment-branch-remote ((t (:foreground ,string)))) |
| 194 | `(git-commit-comment-detached ((t (:foreground ,orange)))) |
| 195 | `(git-commit-comment-heading ((t (:foreground ,kw)))) |
| 196 | `(git-commit-comment-file ((t (:foreground ,const)))) |
| 197 | `(git-commit-comment-action ((t nil))) |
| 198 | `(hl-line ((t (:background ,bg :extend t)))) |
| 199 | `(magit-bisect-bad ((t (:foreground ,red)))) |
| 200 | `(magit-bisect-good ((t (:foreground ,string)))) |
| 201 | `(magit-bisect-skip ((t (:foreground ,orange)))) |
| 202 | `(magit-blame-hash ((t (:foreground ,const)))) |
| 203 | `(magit-blame-date ((t (:foreground ,red)))) |
| 204 | `(magit-blame-heading ((t (:foreground ,orange :background ,sel :extend t)))) |
| 205 | `(magit-branch-current ((t (:foreground ,func)))) |
| 206 | `(magit-branch-local ((t (:foreground ,const)))) |
| 207 | `(magit-branch-remote ((t (:foreground ,string)))) |
| 208 | `(magit-cherry-equivalent ((t (:foreground ,const)))) |
| 209 | `(magit-cherry-unmatched ((t (:foreground ,const)))) |
| 210 | `(magit-diff-added ((t (:foreground ,added-fg :background ,added-bg :extend t)))) |
| 211 | `(magit-diff-added-highlight ((t (:foreground ,string :background ,added-bg-hi :weight bold :extend t)))) |
| 212 | `(magit-diff-base ((t (:foreground ,orange-dark :background ,changed-bg :extend t)))) |
| 213 | `(magit-diff-base-highlight ((t (:foreground ,orange :background ,changed-bg-hi :weight bold :extend t)))) |
| 214 | `(magit-diff-context ((t (:foreground ,dim :background ,bg :extend t)))) |
| 215 | `(magit-diff-context-highlight ((t (:foreground ,fg :background ,bg :extend t)))) |
| 216 | `(magit-diff-file-heading ((t (:foreground ,fg :weight bold :extend t)))) |
| 217 | `(magit-diff-file-heading-selection ((t (:foreground ,kw :background ,dim :weight bold :extend t)))) |
| 218 | `(magit-diff-hunk-heading ((t (:foreground ,bg :background ,muted :extend t)))) |
| 219 | `(magit-diff-hunk-heading-highlight ((t (:foreground ,bg :background ,const :weight bold :extend t)))) |
| 220 | `(magit-diff-lines-heading ((t (:foreground ,orange :background ,red :extend t :extend t)))) |
| 221 | `(magit-diff-removed ((t (:foreground ,red-dark :background ,removed-bg :extend t)))) |
| 222 | `(magit-diff-removed-highlight ((t (:foreground ,red :background ,removed-bg-hi :weight bold :extend t)))) |
| 223 | `(magit-diffstat-added ((t (:foreground ,string)))) |
| 224 | `(magit-diffstat-removed ((t (:foreground ,red)))) |
| 225 | `(magit-dimmed ((t (:foreground ,kw)))) |
| 226 | `(magit-hash ((t (:foreground ,comment)))) |
| 227 | `(magit-header-line ((t (:background ,dim :foreground ,fg :weight bold :box (:line-width 3 :color ,dim))))) |
| 228 | `(magit-filename ((t (:foreground ,const)))) |
| 229 | `(magit-log-author ((t (:foreground ,orange)))) |
| 230 | `(magit-log-date ((t (:foreground ,func)))) |
| 231 | `(magit-log-graph ((t (:foreground ,comment)))) |
| 232 | `(magit-process-ng ((t (:inherit error)))) |
| 233 | `(magit-process-ok ((t (:inherit success)))) |
| 234 | `(magit-reflog-amend ((t (:foreground ,kw)))) |
| 235 | `(magit-reflog-checkout ((t (:foreground ,func)))) |
| 236 | `(magit-reflog-cherry-pick ((t (:foreground ,string)))) |
| 237 | `(magit-reflog-commit ((t (:foreground ,string)))) |
| 238 | `(magit-reflog-merge ((t (:foreground ,string)))) |
| 239 | `(magit-reflog-other ((t (:foreground ,const)))) |
| 240 | `(magit-reflog-rebase ((t (:foreground ,kw)))) |
| 241 | `(magit-reflog-remote ((t (:foreground ,const)))) |
| 242 | `(magit-reflog-reset ((t (:inherit error)))) |
| 243 | `(magit-refname ((t (:foreground ,comment)))) |
| 244 | `(magit-section-heading ((t (:foreground ,func :weight bold :extend t)))) |
| 245 | `(magit-section-heading-selection ((t (:foreground ,orange :weight bold :extend t)))) |
| 246 | `(magit-section-highlight ((t (:inherit hl-line)))) |
| 247 | `(magit-section-secondary-heading ((t (:foreground ,const :weight bold :extend t)))) |
| 248 | `(magit-sequence-drop ((t (:foreground ,red)))) |
| 249 | `(magit-sequence-head ((t (:foreground ,func)))) |
| 250 | `(magit-sequence-part ((t (:foreground ,orange)))) |
| 251 | `(magit-sequence-stop ((t (:foreground ,string)))) |
| 252 | `(magit-signature-bad ((t (:inherit error)))) |
| 253 | `(magit-signature-error ((t (:inherit error)))) |
| 254 | `(magit-signature-expired ((t (:foreground ,orange)))) |
| 255 | `(magit-signature-good ((t (:inherit success)))) |
| 256 | `(magit-signature-revoked ((t (:foreground ,kw)))) |
| 257 | `(magit-signature-untrusted ((t (:foreground ,orange)))) |
| 258 | `(magit-tag ((t (:foreground ,orange)))) |
| 259 | `(org-block ((t (:background ,sel :extend t)))) |
| 260 | `(org-block-background ((t (:background ,sel :extend t)))) |
| 261 | `(org-block-begin-line ((t (:inherit org-block :foreground ,comment)))) |
| 262 | `(org-block-end-line ((t (:inherit org-block-begin-line)))) |
| 263 | `(org-checkbox ((t (:inherit org-todo)))) |
| 264 | `(org-checkbox-statistics-done ((t (:inherit org-done)))) |
| 265 | `(org-checkbox-statistics-todo ((t (:inherit org-todo)))) |
| 266 | `(org-code ((t (:inherit org-block :foreground ,orange)))) |
| 267 | `(org-date ((t (:foreground ,orange)))) |
| 268 | `(org-document-info ((t (:foreground ,kw)))) |
| 269 | `(org-document-title ((t (:foreground ,kw :weight bold)))) |
| 270 | `(org-done ((t (:inherit org-headline-done :strike-through unspecified :weight bold)))) |
| 271 | `(org-link ((t (:inherit link :foreground ,orange)))) |
| 272 | `(org-meta-line ((t (:foreground ,dim)))) |
| 273 | `(org-table ((t (:foreground ,const)))) |
| 274 | `(org-tag ((t (:foreground ,dim :weight normal)))) |
| 275 | `(org-todo ((t (:foreground ,string :bold inherit)))) |
| 276 | `(org-verbatim ((t (:foreground ,string)))) |
| 277 | `(outline-1 ((t (:foreground ,func :weight bold :extend t)))) |
| 278 | `(outline-2 ((t (:foreground ,kw :weight bold :extend t)))) |
| 279 | `(outline-3 ((t (:foreground ,const :weight bold :extend t)))) |
| 280 | `(outline-4 ((t (:foreground ,const :weight bold :extend t)))) |
| 281 | `(outline-5 ((t (:foreground ,const :weight bold :extend t)))) |
| 282 | `(outline-6 ((t (:foreground ,fg :weight bold :extend t)))) |
| 283 | `(outline-7 ((t (:foreground ,fg-hi :weight bold :extend t)))) |
| 284 | `(outline-8 ((t (:foreground ,fg-max :weight bold :extend t)))) |
| 285 | `(smerge-lower ((t (:background ,added-bg-hi)))) |
| 286 | `(smerge-upper ((t (:background ,removed-bg-hi)))) |
| 287 | `(smerge-base ((t (:background ,bg-tint)))) |
| 288 | `(smerge-markers ((t (:background ,comment :foreground ,bg :distant-foreground ,fg :weight bold)))) |
| 289 | `(smerge-refined-added ((t (:inherit diff-added :inverse-video t)))) |
| 290 | `(smerge-refined-removed ((t (:inherit diff-removed :inverse-video t)))) |
| 291 | `(smerge-mine ((t (:background ,removed-bg-hi)))) |
| 292 | `(smerge-other ((t (:background ,added-bg-hi)))))) |
| 293 | |
| 294 | (provide-theme 'darkmatter) |
| 295 | |
| 296 | ;;; darkmatter-theme.el ends here |