Compare commits

...
2 Commits
Author SHA1 Message Date
jasonhilder c43ff55d32 Emacs clean up. 2026-10-27 07:59:41 +02:00
jasonhilder 62e4feba61 Custom theme 2026-10-26 09:34:18 +02:00
5 changed files with 387 additions and 324 deletions
+1 -12
View File
@@ -1,8 +1,6 @@
;;; early-init.el --- Pre-init: GC ceiling and frame chrome -*- lexical-binding: t; -*-
;;; Commentary:
;; Runs before package.el initialises and before the first frame is drawn, so
;; it is the only place two things can take effect:
;; Runs before package.el initialises and first frame is drawn, the only place these take effect:
;; 1. Raising the GC ceiling, so the whole startup (package load + init.el)
;; runs without garbage-collection pauses.
;; 2. Removing the menu/tool/scroll bars via `default-frame-alist', so they
@@ -10,15 +8,6 @@
;; them and then removes them, a visible flicker on launch.
;;
;; Nothing here may depend on a package: none are loaded yet.
;;
;; IMPORTANT: the GC bump below is only half the pair. Restore a working value
;; once startup is done by adding this to init.el:
;;
;; (add-hook 'emacs-startup-hook
;; (lambda () (setq gc-cons-threshold (* 16 1024 1024))))
;;
;; Without it, GC never runs again and Emacs slowly eats memory.
;;; Code:
(startup-redirect-eln-cache (expand-file-name "var/eln-cache/" user-emacs-directory))
+14 -28
View File
@@ -3,12 +3,18 @@
;; C-h works too, except in normal/motion state where it moves to the window on the left.
;;; Code:
;;;; 1. Emac setup, files, packages and paths
;;;; 1. Emac setup, gc, files, packages
(add-hook 'emacs-startup-hook
(lambda () (setq gc-cons-threshold (* 16 1024 1024))))
(dolist (bin (list (expand-file-name "~/.local/bin")
(expand-file-name "~/.go/bin")))
(add-to-list 'exec-path bin)
(setenv "PATH" (concat bin path-separator (getenv "PATH"))))
;; Add the themes directory to the load path
(add-to-list 'custom-theme-load-path (expand-file-name "themes" user-emacs-directory))
;; all the emacs runtime files live in var/.
;; early-init.el redirects eln-cache and elpa.
(defvar my/var (locate-user-emacs-file "var/"))
@@ -59,20 +65,8 @@
(electric-pair-mode 1)
(which-key-mode 1)
(add-to-list 'warning-suppress-types '(files))
(use-package doom-themes :ensure t)
(load-theme 'doom-tomorrow-night t)
(doom-themes-set-faces 'user
'(default :background "#131313")
'(fringe :background "#131313")
'(line-number :background "#131313")
'(line-number-current-line :background "#131313")
'(mode-line :background "#1a1a1a")
'(mode-line-inactive :background "#131313"))
(use-package doom-modeline
:ensure t
:init (doom-modeline-mode 1))
;; Load the compline theme
(load-theme 'minimal t)
;; set mode line at the top of each window
(setq-default header-line-format mode-line-format mode-line-format nil)
@@ -143,7 +137,7 @@
(kbd "TAB") #'my/insert-tab
(kbd "C-SPC") #'completion-at-point)
;; C-p, C-f and C-b are assigned to Consult below.
;; C-p and C-f are assigned to Consult below, C-m to ibuffer.
(evil-define-key '(normal motion) 'global
(kbd "C-e") #'dired-jump))
@@ -153,7 +147,7 @@
;; Don't add its global [b ]b [e ]e ... bindings.
(evil-collection-want-unimpaired-p nil)
:config
(evil-collection-init '(info)))
(evil-collection-init '(info ibuffer)))
;; Minibuffer. Vertico
(with-eval-after-load 'vertico
@@ -192,22 +186,16 @@
;; Searches start at the project root when there is one, else the current directory.
(use-package consult
:config
;; Hide noise from the buffer picker.
(dolist (re '("\\`\\*scratch\\*\\'"
"\\`\\*Messages\\*\\'"
"\\`\\*Warnings\\*\\'"
"\\`\\*xref\\*\\'"))
(add-to-list 'consult-buffer-filter re))
;; Don't re-run the preview on every keystroke while typing a search.
(consult-customize consult-ripgrep
:preview-key '(:debounce 0.4 any)))
;; Bind immediately, without waiting for consult to load.
;; C-m opens the full ibuffer list (evil-collection provides its navigation).
(evil-define-key '(normal motion) 'global
(kbd "C-p") #'consult-fd
(kbd "C-f") #'consult-ripgrep
(kbd "C-m") #'consult-buffer)
(kbd "C-m") #'ibuffer)
;;;; 7. Dired
(setq dired-dwim-target t
@@ -231,12 +219,10 @@
;;;; Core config ends here.
;;;; -----------------------------------------------------------------
;;;; 8. Modules - additional functionality outside of the core init.el
;; Setup for orgmode
(load (locate-user-emacs-file "modules/org.el") nil 'nomessage)
;; Setup for rss feed
(load (locate-user-emacs-file "modules/rss.el") nil 'nomessage)
;; Magit and the :git command live in modules/git.el.
(load (locate-user-emacs-file "modules/git.el") nil 'nomessage)
+12 -6
View File
@@ -2,16 +2,17 @@
;;; Commentary:
;; Loaded from init.el after Evil.
;;
;; :build Run ./build.sh from the project root.
;; :build Run ./build.sh from the nearest ancestor dir containing it.
;; :build ARGS Run ./build.sh ARGS, e.g. :build release -v
;;
;; If no build.sh is found (or it isn't executable), report it and do nothing.
;;
;; The compilation buffer opens at the bottom (45% height, full width) and
;; takes focus when the build starts. ANSI colours are rendered.
;; Kill a running build with M-x kill-compilation.
;;; Code:
(setq compile-command "./build.sh"
compilation-read-command nil ; run without prompting
(setq compilation-read-command nil ; run without prompting
compilation-ask-about-save nil
compilation-scroll-output t)
@@ -31,10 +32,15 @@
;; :build runs ./build.sh; :build ARGS appends ARGS.
(evil-define-command my/ex-build (args)
"Run `./build.sh ARGS' from the project root."
"Run `./build.sh ARGS' from the nearest directory containing build.sh."
(interactive "<a>")
(let ((compile-command (concat "./build.sh " args))) ; nil args -> ""
(project-compile)))
(let ((root (locate-dominating-file default-directory "build.sh")))
(unless root
(user-error "No build.sh found"))
(let ((default-directory root))
(unless (file-executable-p "build.sh")
(user-error "build.sh is not executable"))
(compile (string-trim (concat "./build.sh " args)))))) ; nil args -> ""
(evil-ex-define-cmd "build" #'my/ex-build)
-278
View File
@@ -1,278 +0,0 @@
;;; rss.el --- Elfeed for YouTube feeds, played in mpv -*- lexical-binding: t; -*-
;;; Commentary:
;; Elfeed with a little glue for Evil. Needs the `elfeed' package (MELPA).
;;
;; :rss / :rss get open elfeed / also fetch all feeds now
;;
;; Search buffer RET show the entry
;; o play in mpv and mark read
;; r/u mark read / unread
;; A mark everything listed as read
;; c pick a channel/feed by name and show only it
;; s change the filter; TAB completes +tags
;; (type "+seb" TAB -> "+Sebastian_Lague")
;; gr fetch all feeds
;; q quit
;; Entry buffer o play in mpv
;; q close
;;
;; Every feed is tagged with its category (+youtube, +news) and with its
;; own channel tag: its name with spaces replaced by "_". So
;; "gingerBill" is +gingerBill and "Sebastian Lague" is +Sebastian_Lague.
;; Tags match exactly, but in the `s' prompt TAB completes them, ignoring
;; case. Give a feed a short tag of your own with a third argument:
;; (my/rss-yt "Jonathan Blow highlights" "UC..." 'blow).
;;
;; Everything else is your normal Evil keys. Nothing is fetched
;; automatically; fetching is always manual (:rss get / gr). Fetch errors
;; are logged in the *elfeed-log* buffer.
;;
;; Feeds live in `my/rss-categories' below, grouped by tag. Edit the list
;; and restart Emacs.
;;; Code:
(use-package elfeed
:ensure t
:defer t
:custom
(elfeed-search-filter "@1-month-ago +unread")
;; Be gentle with YouTube: few simultaneous connections.
(elfeed-curl-max-connections 4)
:config
;; Not in :custom: `my/rss-feeds' is defined below, and :custom runs
;; immediately, while :config waits until elfeed loads.
(setq elfeed-feeds (my/rss-feeds))
(my/rss-apply-titles)
(my/rss-retag))
(defun my/rss-yt (name channel-id &optional tag)
"Feed entry for a YouTube channel, uploads only (no Shorts).
TAG, a symbol, overrides the channel tag made from NAME."
(let ((url (concat "https://www.youtube.com/feeds/videos.xml?playlist_id=UULF"
(substring channel-id 2))))
(if tag (list name url tag) (list name url))))
(defvar my/rss-categories
(list
(list 'youtube
(my/rss-yt "Awesome" "UCXzw-OdotBUcNA9yhuYQBwA")
(my/rss-yt "Coding with Sphere" "UCpwl7jNE9PJc-lBTShNs5TQ")
(my/rss-yt "Computerphile" "UC9-y-6csu5WGm29I7JiwpnA")
(my/rss-yt "gingerBill" "UCUSck1dOH7VKmG4lRW7tZXg")
(my/rss-yt "Jonathan Blow highlights" "UCavhLwXoB9tkqd-KsXpovOQ")
(my/rss-yt "Karl Zylinski" "UC5YnADU2rChK7598A9gKygQ")
(my/rss-yt "Nic Barker" "UCz-yrxeZYIYdpEZgHGvIydA")
(my/rss-yt "Nir Lichtman" "UCAMu6Dso0ENoNm3sKpQsy0g")
(my/rss-yt "Ryan Fleury" "UCCsdwE2z_kRL3vfVsd5OGyA")
(my/rss-yt "Tariq10x" "UCXyisNI9ezbv7fvGMoSaFKg")
(my/rss-yt "The Coding Gopher" "UC-mTIBh__DzAqW495JHXy5A")
(my/rss-yt "Tsoding Daily" "UCrqM0Ym_NbK1fqeQG2VIohg")
(my/rss-yt "zyapguy" "UCc4IizbM0q_JySK3XUY0Drw")
(my/rss-yt "Dylan Falconer" "UCZzs3Umh6sRiYS_IQIQDThw")
(my/rss-yt "Gamefromscratch" "UCr-5TdGkKszdbboXXsFZJTQ")
(my/rss-yt "Jonas Tyroller" "UC_p_9arduPuxM8DHTGIuSOg")
(my/rss-yt "Miziziziz" "UCaoqVlqPTH78_xjTjTOMcmQ")
(my/rss-yt "Penusbmic" "UCjU-rielI7RsX1hqsCQdfhw")
(my/rss-yt "randy" "UCUmLRMERmJrmUtgnbFfknAg")
(my/rss-yt "randy uncut" "UCgXdyySqz7qH-lDiVG-7KwA")
(my/rss-yt "raylib" "UC8WIBkhYb5sBNqXO1mZ7WSQ")
(my/rss-yt "Sebastian Lague" "UCmtyQOKKmrMVaKuRXz02jbQ")
(my/rss-yt "Tantan" "UChl_NKOs1qqh_x7yJfaDpDw")
(my/rss-yt "ThinMatrix" "UCUkRj4qoT1bsWpE_C8lZYoQ")
(my/rss-yt "Brodie Robertson" "UCld68syR8Wi-GY_n4CaoJGA")
(my/rss-yt "ETA PRIME" "UC_0CVCfC_3iuHqmyClu59Uw")
(my/rss-yt "Benny Surge" "UCkih_7PNYICxAZi1omr2_Og")
(my/rss-yt "bizlychannel" "UCMPGiQ8gwDXFYpwQhX6kK9A")
(my/rss-yt "Daz Games" "UCDBCCMlFD-hArPbWv38FINA")
(my/rss-yt "Deep Dive Dev" "UC1yGsLABIDAqLVtPnoHbpEA")
(my/rss-yt "Flo Woelki" "UC18qytfIhR9cNEjUcgGLl3A")
(my/rss-yt "Gohjoe" "UCac9YlOpTLy_wToRb5Bo-DQ")
(my/rss-yt "Herbcode" "UC79nyXj9gujAj5CySiy2FAQ")
(my/rss-yt "hoff._world" "UCaezB99bVg9xlMS6Jn_ka0A")
(my/rss-yt "Inbound Shovel" "UCdYwjLVP-98bptdlQFO_5zQ")
(my/rss-yt "Jimmy Oakes" "UChp08hcL-qAJD4LK51ZZZvw")
(my/rss-yt "Juby Philosophy" "UCLrpO7U1lnmbRtVxji843-Q")
(my/rss-yt "Lance Hedrick" "UCR2_8uHyWcTSV6iIw6BN4rg")
(my/rss-yt "Mental Moshpit" "UC5a4hb7i2UAT6DxmGz72hdg")
(my/rss-yt "NIGHTRIDE" "UCuYLDxZWv-aal88czKkFvKA")
(my/rss-yt "Rockers Games" "UCeq6focWSVKJy5DR1JxDGyw")
(my/rss-yt "Slax" "UCc0V8-3xYIT6aNOAreAjRcw")
(my/rss-yt "StayAtHomeDev" "UCDshKIMtFjYreCzApleuV8w")
(my/rss-yt "Turkey Tom" "UCDKJdFer1phQI95UinPZehw")
(my/rss-yt "Zei" "UCywwEsnSmADUyhtSaq5dKNg")
(my/rss-yt "Zip Tie Tech" "UCUpt_5O1vYpWAGg77iNMQXA"))
(list 'news
'("Hacker News" "https://hnrss.org/frontpage?points=100")))
"Feeds by tag: each entry is (TAG FEED...), a feed is (NAME URL [CHANNEL-TAG]).
The tag is what you filter on in elfeed, e.g. \"+youtube\". Each feed
also gets its own channel tag, see `my/rss-channel-tag'.")
(defun my/rss-slug (name)
"Tag symbol made from NAME, with spaces replaced by \"_\"."
(intern (replace-regexp-in-string " +" "_" (string-trim name) t t)))
(defun my/rss-channel-tag (feed)
"Channel tag for FEED, (NAME URL [TAG]): TAG if given, else NAME slugged."
(or (nth 2 feed) (my/rss-slug (car feed))))
(defun my/rss-feeds ()
"Elfeed feed list, (URL CATEGORY CHANNEL-TAG), from `my/rss-categories'."
(mapcan (lambda (cat)
(mapcar (lambda (feed)
(list (cadr feed) (car cat) (my/rss-channel-tag feed)))
(cdr cat)))
my/rss-categories))
(defun my/rss-all-feeds ()
"Every (NAME URL) in `my/rss-categories', across all tags."
(mapcan (lambda (cat) (copy-sequence (cdr cat))) my/rss-categories))
(defun my/rss-apply-titles ()
"Give each feed the name from `my/rss-categories' as its display title.
YouTube playlist feeds all call themselves \"Videos\"; this overrides
that, so the list shows the channel and \"=Name\" filters work. The
title is stored as feed metadata, which fetching never overwrites."
(dolist (feed (my/rss-all-feeds))
(setf (elfeed-meta (elfeed-db-get-feed (cadr feed)) :title)
(car feed))))
(defun my/rss-retag ()
"Give already-fetched entries their feed's tags from `elfeed-feeds'.
Elfeed tags entries only as they arrive, so this catches up entries
fetched before a feed's tags changed. Safe to run any time."
(interactive)
(elfeed-db-ensure)
(let ((tags-by-url (make-hash-table :test #'equal))
(n 0))
(dolist (f elfeed-feeds)
(puthash (car f) (cdr f) tags-by-url))
(maphash
(lambda (_id entry)
(let* ((tags (gethash (elfeed-entry-feed-id entry) tags-by-url))
(missing (cl-set-difference tags (elfeed-entry-tags entry))))
(when missing
(apply #'elfeed-tag entry missing)
(cl-incf n))))
elfeed-db-entries)
(when (or (> n 0) (called-interactively-p 'any))
(message "rss: retagged %d entries" n))))
;;;; Playing videos
(defun my/rss-play (url &rest _)
"Play URL in mpv. Its output goes to the *mpv* buffer."
(message "mpv: starting %s (can take a few seconds)..." url)
(set-process-sentinel
(start-process "mpv" "*mpv*" "mpv" url)
(lambda (proc _event)
(when (and (eq (process-status proc) 'exit)
(/= (process-exit-status proc) 0))
(message "mpv failed (exit %d), see the *mpv* buffer"
(process-exit-status proc))
(display-buffer "*mpv*")))))
;; YouTube links go to mpv, everywhere in Emacs.
(with-eval-after-load 'browse-url
(add-to-list 'browse-url-handlers
'("\\`https?://\\(?:www\\.\\|m\\.\\)?\\(?:youtube\\.com\\|youtu\\.be\\)/"
. my/rss-play)))
;;;; Elfeed
(defvar my/rss-stagger 4
"Seconds between feed fetches. YouTube answers with 404/500 when hit fast.")
(defun my/rss-fetch ()
"Fetch every feed, one at a time, `my/rss-stagger' seconds apart.
Run it again to fill in feeds that failed; entries are not duplicated."
(interactive)
(seq-do-indexed
(lambda (feed i)
(run-with-timer (* my/rss-stagger i) nil #'elfeed-update-feed (car feed)))
elfeed-feeds)
(message "rss: fetching %d feeds, about %ds"
(length elfeed-feeds) (* my/rss-stagger (length elfeed-feeds))))
(defun my/rss-all-tags ()
"Every tag name: the ones in `elfeed-feeds' plus any in the database."
(delete-dups
(mapcar #'symbol-name
(append (mapcan (lambda (f) (copy-sequence (cdr f))) elfeed-feeds)
(elfeed-db-get-all-tags)))))
(defun my/rss-filter-capf ()
"Complete the +tag or -tag at point in the filter prompt."
(when (looking-back "\\(?:^\\| \\)[+-]\\([^ ]*\\)" (line-beginning-position))
(list (match-beginning 1) (match-end 1)
(completion-table-case-fold (my/rss-all-tags))
:exclusive 'no)))
(defvar my/rss-filter-map
(let ((map (make-sparse-keymap)))
(define-key map (kbd "TAB") #'completion-at-point)
map)
"Extra keys for the filter prompt.")
(defun my/rss-filter ()
"Elfeed's live filter, with TAB completing +tags and -tags."
(interactive)
(minibuffer-with-setup-hook
(lambda ()
(add-hook 'completion-at-point-functions #'my/rss-filter-capf nil t)
(use-local-map (make-composed-keymap my/rss-filter-map
(current-local-map))))
(elfeed-search-live-filter)))
(defun my/rss-mark-all-read ()
"Mark every entry the current filter lists as read.
Works on elfeed's list directly, so it doesn't depend on the region or
on Evil's visual state. Clear the filter first to mark everything."
(interactive)
(let ((n (length elfeed-search-entries)))
(elfeed-untag elfeed-search-entries 'unread)
(elfeed-search-update :force)
(message "rss: marked %d entries read" n)))
(defun my/rss-channel ()
"Pick a feed by name and show only its entries (read and unread).
Filters on the feed URL, so it works whatever the feed calls itself.
Press `s' and clear the filter to go back."
(interactive)
(let* ((feeds (my/rss-all-feeds))
(name (completing-read "Channel: " feeds nil t))
(url (cadr (assoc name feeds))))
(elfeed-search-set-filter
(concat "@6-months-ago =" (regexp-quote url)))))
;; Elfeed's buffers start in motion state: Evil movement, no editing keys.
(evil-set-initial-state 'elfeed-search-mode 'motion)
(evil-set-initial-state 'elfeed-show-mode 'motion)
(with-eval-after-load 'elfeed-search
(evil-define-key 'motion elfeed-search-mode-map
(kbd "RET") #'elfeed-search-show-entry
"o" #'elfeed-search-browse-url ; plays via `browse-url-handlers', marks read
"r" #'elfeed-search-untag-all-unread
"u" #'elfeed-search-tag-all-unread
"A" #'my/rss-mark-all-read
"c" #'my/rss-channel
"s" #'my/rss-filter
"gr" #'my/rss-fetch
"q" #'elfeed-search-quit-window))
(with-eval-after-load 'elfeed-show
(evil-define-key 'motion elfeed-show-mode-map
"o" #'elfeed-show-visit
"q" #'elfeed-kill-buffer))
;; :rss opens elfeed; :rss get also fetches every feed now.
(evil-define-command my/rss (args)
"Open elfeed, or fetch all feeds too with `:rss get'."
(interactive "<a>")
(elfeed)
(when (equal (string-trim (or args "")) "get")
(my/rss-fetch)))
(evil-ex-define-cmd "rss" #'my/rss)
;;; rss.el ends here
+360
View File
@@ -0,0 +1,360 @@
;;; minimal-theme.el --- Minimal high-functionality Ujelly port -*- lexical-binding: t; -*-
;;
;; Built on the compline-theme face structure, updated with the color palette
;; from Ujelly (color-theme-ujelly by marktran).
;;
;;; Code:
(deftheme minimal
"Created 2026-10-26.")
(custom-theme-set-faces
'minimal
;;;; Core
'(default ((t (:inherit nil :extend nil :stipple nil :background "#151515" :foreground "#e8e8d3" :inverse-video nil :box nil :strike-through nil :overline nil :underline nil :slant normal :weight regular :height 143 :width normal))))
'(cursor ((t (:background "#8fbfdc"))))
'(fixed-pitch ((t (:height 140))))
'(variable-pitch ((t (:height 140))))
'(escape-glyph ((t (:foreground "#8fbfdc"))))
'(homoglyph ((t (:foreground "#8fbfdc"))))
'(minibuffer-prompt ((t (:foreground "#8fbfdc"))))
'(highlight ((t (:foreground "#e8e8d3" :background "#303030" :weight bold))))
'(hl-line ((t (:extend t :background "#1b1b1b"))))
'(region ((t (:extend t :background "#404040"))))
'(shadow ((t (:foreground "#7f7f7f"))))
'(secondary-selection ((t (:extend t :background "#404040"))))
'(trailing-whitespace ((t (:background "#cf6a4c"))))
'(vertical-border ((t (:foreground "#262626"))))
'(error ((t (:foreground "#cf6a4c"))))
'(warning ((t (:foreground "#fad07a"))))
'(success ((t (:foreground "#99ad6a"))))
;;;; Line numbers
'(line-number ((t (:foreground "#404040"))))
'(line-number-current-line ((t (:foreground "#e8e8d3"))))
;;;; Font lock
'(font-lock-bracket-face ((t (:inherit (font-lock-punctuation-face)))))
'(font-lock-builtin-face ((t (:foreground "#8fbfdc"))))
'(font-lock-comment-delimiter-face ((default (:inherit (font-lock-comment-face)))))
'(font-lock-comment-face ((t (:foreground "#767676"))))
'(font-lock-constant-face ((t (:foreground "#c6b5ed"))))
'(font-lock-delimiter-face ((t (:inherit (font-lock-punctuation-face)))))
'(font-lock-doc-face ((t (:foreground "#767676" :inherit (font-lock-comment-face)))))
'(font-lock-doc-markup-face ((t (:inherit (font-lock-constant-face)))))
'(font-lock-escape-face ((t (:inherit (font-lock-regexp-grouping-backslash)))))
'(font-lock-function-call-face ((t (:slant italic :foreground "#8fbfdc" :inherit (font-lock-function-name-face)))))
'(font-lock-function-name-face ((t (:foreground "#8fbfdc"))))
'(font-lock-keyword-face ((t (:foreground "#fad07a"))))
'(font-lock-negation-char-face ((t (:foreground "#cf6a4c" :inherit (bold)))))
'(font-lock-number-face ((t (:foreground "#cf6a4c"))))
'(font-lock-misc-punctuation-face ((t (:inherit (font-lock-punctuation-face)))))
'(font-lock-operator-face ((t (:foreground "#a0a8b0"))))
'(font-lock-preprocessor-face ((t (:foreground "#fad07a" :inherit (bold)))))
'(font-lock-property-name-face ((t (:weight bold :foreground "#8fbfdc"))))
'(font-lock-property-use-face ((t (:weight regular :inherit (font-lock-property-name-face)))))
'(font-lock-punctuation-face ((t (:foreground "#a0a8b0"))))
'(font-lock-regexp-grouping-backslash ((t (:foreground "#fad07a" :inherit (bold)))))
'(font-lock-regexp-grouping-construct ((t (:foreground "#fad07a" :inherit (bold)))))
'(font-lock-string-face ((t (:foreground "#99ad6a"))))
'(font-lock-type-face ((t (:foreground "#ffb17a"))))
'(font-lock-variable-name-face ((t (:foreground "#e8e8d3"))))
'(font-lock-variable-use-face ((t (:foreground "#e8e8d3" :inherit (font-lock-variable-name-face)))))
'(font-lock-warning-face ((t (:inherit (warning)))))
;;;; Links, buttons, tooltips
'(button ((t (:inherit (link)))))
'(link ((t (:weight bold :underline (:color foreground-color :style line :position nil) :foreground "#8fbfdc"))))
'(link-visited ((t (:inherit link :foreground "#c6b5ed"))))
'(fringe ((t (:foreground "#404040" :inherit (default)))))
'(tooltip ((t (:foreground "#e8e8d3" :background "#1b1b1b"))))
;;;; Mode line
'(header-line ((t (:inherit (mode-line)))))
'(mode-line ((t (:background "#1c1c1c" :foreground unspecified))))
'(mode-line-buffer-id ((t (:weight bold))))
'(mode-line-emphasis ((t (:foreground "#fad07a"))))
'(mode-line-highlight ((t (:inherit (highlight)))))
'(mode-line-inactive ((t (:foreground "#767676" :background "#121212"))))
;;;; Tab bar
'(tab-bar ((t (:inherit default :background "#151515" :foreground "#767676"))))
'(tab-bar-tab ((t (:inherit tab-bar :background "#262626" :foreground "#e8e8d3" :weight bold :box nil))))
'(tab-bar-tab-inactive ((t (:inherit tab-bar :background "#151515" :foreground "#999999" :weight normal :box nil))))
;;;; Search & Completions
'(isearch ((t (:weight bold :inherit (lazy-highlight)))))
'(isearch-fail ((t (:weight bold :foreground "#151515" :background "#cf6a4c"))))
'(lazy-highlight ((t (:weight bold :foreground "#e8e8d3" :background "#303030"))))
'(match ((t (:weight bold :foreground "#99ad6a" :background "#151515"))))
'(next-error ((t (:inherit (region)))))
'(query-replace ((t (:inherit (isearch)))))
;;;; VC gutter: added = green, deleted = red, modified = sand/yellow
'(diff-hl-insert ((t (:foreground "#99ad6a" :background "#99ad6a"))))
'(diff-hl-delete ((t (:foreground "#cf6a4c" :background "#cf6a4c"))))
'(diff-hl-change ((t (:foreground "#fad07a" :background "#fad07a"))))
'(git-gutter:added ((t (:foreground "#99ad6a" :background "#99ad6a"))))
'(git-gutter:deleted ((t (:foreground "#cf6a4c" :background "#cf6a4c"))))
'(git-gutter:modified ((t (:foreground "#fad07a" :background "#fad07a"))))
'(git-gutter-fr:added ((t (:foreground "#99ad6a"))))
'(git-gutter-fr:deleted ((t (:foreground "#cf6a4c"))))
'(git-gutter-fr:modified ((t (:foreground "#fad07a"))))
;;;; gnus: group buffer
'(gnus-group-news-1 ((t (:foreground "#e8e8d3" :weight bold))))
'(gnus-group-news-1-empty ((t (:foreground "#e8e8d3" :weight normal))))
'(gnus-group-news-2 ((t (:foreground "#8fbfdc" :weight bold))))
'(gnus-group-news-2-empty ((t (:foreground "#8fbfdc" :weight normal))))
'(gnus-group-news-3 ((t (:foreground "#fad07a" :weight bold))))
'(gnus-group-news-3-empty ((t (:foreground "#fad07a" :weight normal))))
'(gnus-group-news-low ((t (:foreground "#767676" :weight bold))))
'(gnus-group-news-low-empty ((t (:foreground "#404040" :weight normal))))
'(gnus-group-mail-1 ((t (:foreground "#99ad6a" :weight bold))))
'(gnus-group-mail-1-empty ((t (:foreground "#99ad6a" :weight normal))))
'(gnus-group-mail-2 ((t (:foreground "#c6b5ed" :weight bold))))
'(gnus-group-mail-2-empty ((t (:foreground "#c6b5ed" :weight normal))))
'(gnus-group-mail-3 ((t (:foreground "#ffb17a" :weight bold))))
'(gnus-group-mail-3-empty ((t (:foreground "#ffb17a" :weight normal))))
'(gnus-group-mail-low ((t (:foreground "#767676" :weight bold))))
'(gnus-group-mail-low-empty ((t (:foreground "#404040" :weight normal))))
;;;; gnus: summary buffer
'(gnus-summary-normal-unread ((t (:foreground "#e8e8d3" :weight bold))))
'(gnus-summary-normal-read ((t (:foreground "#767676" :weight normal))))
'(gnus-summary-normal-ticked ((t (:foreground "#cf6a4c" :weight bold))))
'(gnus-summary-normal-ancient ((t (:foreground "#404040" :weight normal))))
'(gnus-summary-normal-undownloaded ((t (:foreground "#8fbfdc" :slant italic))))
'(gnus-summary-high-unread ((t (:foreground "#fad07a" :weight bold))))
'(gnus-summary-high-read ((t (:foreground "#99ad6a" :weight normal))))
'(gnus-summary-high-ticked ((t (:foreground "#cf6a4c" :weight bold))))
'(gnus-summary-high-ancient ((t (:foreground "#767676" :weight normal))))
'(gnus-summary-low-unread ((t (:foreground "#8fbfdc" :slant italic :weight bold))))
'(gnus-summary-low-read ((t (:foreground "#404040" :slant italic :weight normal))))
'(gnus-summary-low-ticked ((t (:foreground "#cf6a4c" :slant italic))))
'(gnus-summary-low-ancient ((t (:foreground "#404040" :slant italic))))
'(gnus-summary-selected ((t (:background "#404040" :foreground "#e8e8d3" :weight bold))))
'(gnus-summary-cancelled ((t (:foreground "#cf6a4c" :strike-through t))))
;;;; gnus: article headers, citations, misc
'(gnus-header-name ((t (:foreground "#8fbfdc" :weight bold))))
'(gnus-header-content ((t (:foreground "#fad07a" :slant italic))))
'(gnus-header-from ((t (:foreground "#e8e8d3" :weight bold))))
'(gnus-header-subject ((t (:foreground "#ffb17a"))))
'(gnus-header-newsgroups ((t (:foreground "#fad07a" :slant italic))))
'(gnus-cite-1 ((t (:foreground "#8fbfdc"))))
'(gnus-cite-2 ((t (:foreground "#99ad6a"))))
'(gnus-cite-3 ((t (:foreground "#fad07a"))))
'(gnus-cite-4 ((t (:foreground "#cf6a4c"))))
'(gnus-cite-5 ((t (:foreground "#c6b5ed"))))
'(gnus-cite-6 ((t (:foreground "#ffb17a"))))
'(gnus-cite-7 ((t (:foreground "#8fbfdc"))))
'(gnus-cite-8 ((t (:foreground "#99ad6a"))))
'(gnus-cite-9 ((t (:foreground "#fad07a"))))
'(gnus-cite-10 ((t (:foreground "#767676"))))
'(gnus-cite-11 ((t (:foreground "#404040"))))
'(gnus-signature ((t (:foreground "#767676" :slant italic))))
'(gnus-button ((t (:inherit link))))
'(gnus-splash ((t (:foreground "#767676"))))
'(gnus-emphasis-bold ((t (:weight bold))))
'(gnus-emphasis-italic ((t (:slant italic))))
'(gnus-emphasis-underline ((t (:underline t))))
'(gnus-emphasis-bold-italic ((t (:weight bold :slant italic))))
'(gnus-server-opened ((t (:foreground "#99ad6a" :weight bold))))
'(gnus-server-closed ((t (:foreground "#767676" :slant italic))))
'(gnus-server-denied ((t (:foreground "#cf6a4c" :weight bold))))
'(gnus-server-offline ((t (:foreground "#fad07a" :weight bold))))
'(gnus-server-agent ((t (:foreground "#8fbfdc" :weight bold))))
;;;; message (gnus composition buffers)
'(message-header-name ((t (:foreground "#8fbfdc" :weight bold))))
'(message-header-to ((t (:foreground "#e8e8d3" :weight bold))))
'(message-header-cc ((t (:foreground "#ffb17a"))))
'(message-header-subject ((t (:foreground "#e8e8d3" :weight bold))))
'(message-header-newsgroups ((t (:foreground "#fad07a" :slant italic))))
'(message-header-other ((t (:foreground "#fad07a"))))
'(message-header-xheader ((t (:foreground "#767676"))))
'(message-separator ((t (:foreground "#404040"))))
'(message-mml ((t (:foreground "#99ad6a"))))
'(message-cited-text-1 ((t (:foreground "#8fbfdc"))))
'(message-cited-text-2 ((t (:foreground "#99ad6a"))))
'(message-cited-text-3 ((t (:foreground "#fad07a"))))
'(message-cited-text-4 ((t (:foreground "#cf6a4c"))))
;;;; magit: sections
'(magit-section-heading ((t (:foreground "#fad07a" :weight bold :extend t))))
'(magit-section-secondary-heading ((t (:foreground "#c6b5ed" :weight bold :extend t))))
'(magit-section-heading-selection ((t (:foreground "#99ad6a" :weight bold :extend t))))
'(magit-section-highlight ((t (:background "#1b1b1b" :extend t))))
'(magit-section-child-count ((t (:foreground "#767676"))))
;;;; magit: refs, hashes, log
'(magit-branch-local ((t (:foreground "#8fbfdc"))))
'(magit-branch-remote ((t (:foreground "#99ad6a"))))
'(magit-branch-current ((t (:foreground "#8fbfdc" :weight bold :box (:line-width -1 :color "#767676")))))
'(magit-branch-remote-head ((t (:foreground "#99ad6a" :weight bold :box (:line-width -1 :color "#767676")))))
'(magit-branch-upstream ((t (:slant italic))))
'(magit-tag ((t (:foreground "#fad07a"))))
'(magit-hash ((t (:foreground "#767676"))))
'(magit-dimmed ((t (:foreground "#404040"))))
'(magit-filename ((t (:foreground "#e8e8d3"))))
'(magit-refname ((t (:foreground "#767676"))))
'(magit-refname-stash ((t (:foreground "#767676"))))
'(magit-refname-wip ((t (:foreground "#767676"))))
'(magit-log-author ((t (:foreground "#fad07a"))))
'(magit-log-date ((t (:foreground "#767676"))))
'(magit-log-graph ((t (:foreground "#404040"))))
'(magit-keyword ((t (:foreground "#fad07a"))))
'(magit-keyword-squash ((t (:foreground "#fad07a"))))
'(magit-cherry-equivalent ((t (:foreground "#e8e8d3"))))
'(magit-cherry-unmatched ((t (:foreground "#8fbfdc"))))
;;;; magit: diffs
'(magit-diff-file-heading ((t (:foreground "#e8e8d3" :weight bold :extend t))))
'(magit-diff-file-heading-highlight ((t (:inherit magit-diff-file-heading :background "#1b1b1b"))))
'(magit-diff-file-heading-selection ((t (:inherit magit-diff-file-heading :foreground "#fad07a" :background "#404040"))))
'(magit-diff-hunk-heading ((t (:foreground "#c6b5ed" :background "#222222" :extend t))))
'(magit-diff-hunk-heading-highlight ((t (:foreground "#e8e8d3" :background "#404040" :extend t))))
'(magit-diff-hunk-heading-selection ((t (:foreground "#fad07a" :background "#404040" :extend t))))
'(magit-diff-lines-heading ((t (:foreground "#151515" :background "#fad07a" :extend t))))
'(magit-diff-context ((t (:foreground "#767676" :extend t))))
'(magit-diff-context-highlight ((t (:foreground "#c6b5ed" :background "#1b1b1b" :extend t))))
'(magit-diff-added ((t (:foreground "#99ad6a" :background "#1a261a" :extend t))))
'(magit-diff-added-highlight ((t (:foreground "#99ad6a" :background "#223322" :extend t))))
'(magit-diff-removed ((t (:foreground "#cf6a4c" :background "#261a1a" :extend t))))
'(magit-diff-removed-highlight ((t (:foreground "#cf6a4c" :background "#332222" :extend t))))
'(magit-diffstat-added ((t (:foreground "#99ad6a"))))
'(magit-diffstat-removed ((t (:foreground "#cf6a4c"))))
'(magit-diff-whitespace-warning ((t (:background "#cf6a4c"))))
;;;; magit: process, signatures, sequences, blame, header line
'(magit-process-ok ((t (:foreground "#99ad6a" :weight bold))))
'(magit-process-ng ((t (:foreground "#cf6a4c" :weight bold))))
'(magit-mode-line-process ((t (:foreground "#fad07a"))))
'(magit-mode-line-process-error ((t (:foreground "#cf6a4c"))))
'(magit-signature-good ((t (:foreground "#99ad6a"))))
'(magit-signature-bad ((t (:foreground "#cf6a4c" :weight bold))))
'(magit-signature-untrusted ((t (:foreground "#8fbfdc"))))
'(magit-signature-expired ((t (:foreground "#fad07a"))))
'(magit-signature-expired-key ((t (:foreground "#fad07a"))))
'(magit-signature-revoked ((t (:foreground "#cf6a4c"))))
'(magit-signature-error ((t (:foreground "#cf6a4c"))))
'(magit-sequence-head ((t (:foreground "#8fbfdc"))))
'(magit-sequence-stop ((t (:foreground "#99ad6a"))))
'(magit-sequence-part ((t (:foreground "#fad07a"))))
'(magit-sequence-done ((t (:foreground "#767676"))))
'(magit-sequence-onto ((t (:foreground "#767676"))))
'(magit-bisect-good ((t (:foreground "#99ad6a"))))
'(magit-bisect-skip ((t (:foreground "#fad07a"))))
'(magit-bisect-bad ((t (:foreground "#cf6a4c"))))
'(magit-blame-heading ((t (:foreground "#c6b5ed" :background "#222222" :extend t))))
'(magit-header-line ((t (:foreground "#fad07a" :weight bold))))
'(magit-header-line-key ((t (:foreground "#fad07a"))))
'(magit-header-line-log-select ((t (:foreground "#e8e8d3" :weight bold))))
;;;; transient (magit popups)
'(transient-heading ((t (:foreground "#fad07a" :weight bold))))
'(transient-key ((t (:foreground "#fad07a" :weight bold))))
'(transient-key-exit ((t (:foreground "#cf6a4c" :weight bold))))
'(transient-key-return ((t (:foreground "#fad07a" :weight bold))))
'(transient-key-stay ((t (:foreground "#99ad6a" :weight bold))))
'(transient-argument ((t (:foreground "#99ad6a" :weight bold))))
'(transient-value ((t (:foreground "#99ad6a"))))
'(transient-inactive-argument ((t (:foreground "#767676"))))
'(transient-inactive-value ((t (:foreground "#767676"))))
'(transient-unreachable ((t (:foreground "#404040"))))
'(transient-unreachable-key ((t (:foreground "#404040"))))
'(transient-disabled-suffix ((t (:foreground "#151515" :background "#cf6a4c" :weight bold))))
'(transient-enabled-suffix ((t (:foreground "#151515" :background "#99ad6a" :weight bold))))
'(transient-delimiter ((t (:foreground "#767676"))))
'(transient-separator ((t (:background "#1c1c1c"))))
'(transient-active-infix ((t (:foreground "#e8e8d3" :background "#404040"))))
'(transient-mismatched-key ((t (:underline t))))
'(transient-nonstandard-key ((t (:underline t))))
;;;; git-commit (magit commit message buffer)
'(git-commit-summary ((t (:foreground "#e8e8d3" :weight bold))))
'(git-commit-overlong-summary ((t (:foreground "#cf6a4c" :weight bold))))
'(git-commit-nonempty-second-line ((t (:foreground "#cf6a4c"))))
'(git-commit-keyword ((t (:foreground "#8fbfdc"))))
'(git-commit-comment-heading ((t (:foreground "#fad07a" :weight bold))))
'(git-commit-comment-branch-local ((t (:foreground "#8fbfdc"))))
'(git-commit-comment-branch-remote ((t (:foreground "#99ad6a"))))
'(git-commit-comment-detached ((t (:foreground "#fad07a"))))
'(git-commit-comment-file ((t (:foreground "#fad07a"))))
'(git-commit-comment-action ((t (:foreground "#99ad6a"))))
;;;; erc: buffer text
'(erc-default-face ((t (:foreground "#e8e8d3"))))
'(erc-input-face ((t (:foreground "#99ad6a"))))
'(erc-my-nick-face ((t (:foreground "#99ad6a" :weight bold))))
'(erc-my-nick-prefix-face ((t (:foreground "#99ad6a" :weight bold))))
'(erc-nick-default-face ((t (:foreground "#e8e8d3" :weight bold))))
'(erc-nick-prefix-face ((t (:foreground "#fad07a"))))
'(erc-notice-face ((t (:foreground "#767676" :weight normal))))
'(erc-information ((t (:foreground "#c6b5ed"))))
'(erc-timestamp-face ((t (:foreground "#404040" :weight normal))))
'(erc-action-face ((t (:foreground "#ffb17a" :weight bold))))
'(erc-prompt-face ((t (:foreground "#fad07a" :weight bold))))
'(erc-command-indicator-face ((t (:foreground "#c6b5ed" :weight bold))))
'(erc-error-face ((t (:foreground "#cf6a4c"))))
'(erc-button ((t (:inherit link :foreground "#e8e8d3"))))
'(erc-button-nick-default-face ((t (:foreground "#e8e8d3" :weight bold))))
'(erc-bold-face ((t (:weight bold))))
'(erc-italic-face ((t (:slant italic))))
'(erc-underline-face ((t (:underline t))))
'(erc-inverse-face ((t (:foreground "#151515" :background "#e8e8d3"))))
'(erc-keep-place-indicator-line ((t (:underline (:color "#404040" :style line)))))
'(erc-keep-place-indicator-arrow ((t (:foreground "#cf6a4c"))))
'(erc-header-line ((t (:foreground "#c6b5ed" :background "#1c1c1c"))))
'(erc-header-line-disconnected ((t (:foreground "#cf6a4c" :background "#1c1c1c"))))
;;;; erc: highlighting rules
'(erc-current-nick-face ((t (:foreground "#fad07a" :weight bold))))
'(erc-keyword-face ((t (:foreground "#fad07a" :weight bold))))
'(erc-nick-msg-face ((t (:foreground "#fad07a" :weight bold))))
'(erc-direct-msg-face ((t (:foreground "#cf6a4c"))))
'(erc-pal-face ((t (:foreground "#99ad6a" :weight bold))))
'(erc-fool-face ((t (:foreground "#404040"))))
'(erc-dangerous-host-face ((t (:foreground "#cf6a4c"))))
;;;; css-mode / scss-mode
'(css-proprietary-property ((t (:foreground "#fad07a"))))
'(css-property ((t (:foreground "#e8e8d3"))))
'(css-selector ((t (:foreground "#cf6a4c"))))
;;;; markdown-mode
'(markdown-markup-face ((t (:foreground "#404040"))))
'(markdown-header-face ((t (:inherit bold :foreground "#cf6a4c"))))
'(markdown-code-face ((t (:background "#1c1c1c"))))
;;;; outline
'(outline-1 ((t (:foreground "#e8e8d3" :weight ultra-bold))))
'(outline-2 ((t (:foreground "#8fbfdc"))))
'(outline-3 ((t (:foreground "#99ad6a"))))
'(outline-4 ((t (:foreground "#c6b5ed"))))
'(outline-5 ((t (:foreground "#ffb17a"))))
'(outline-6 ((t (:foreground "#fad07a"))))
'(outline-7 ((t (:foreground "#cf6a4c"))))
'(outline-8 ((t (:foreground "#e8e8d3"))))
;;;; org
'(org-block ((t (:background "#1b1b1b"))))
'(org-block-begin-line ((t (:foreground "#404040" :slant italic :background "#121212"))))
'(org-ellipsis ((t (:underline nil :background "#151515" :foreground "#cf6a4c"))))
'(org-quote ((t (:background "#1c1c1c"))))
'(org-hide ((t (:foreground "#151515"))))
;;;; solaire-mode
'(solaire-mode-line-face ((t (:inherit mode-line :background "#1c1c1c"))))
'(solaire-mode-line-inactive-face ((t (:inherit mode-line-inactive :background "#1c1c1c")))))
;;;###autoload
(when load-file-name
(add-to-list 'custom-theme-load-path
(file-name-as-directory (file-name-directory load-file-name))))
(provide-theme 'minimal)
;;; minimal-theme.el ends here