Commit Diff


commit - 2ed57a1dd15ad101eef0224de2012b8b18076582
commit + e0df63515ebe429a3d299df6a6dd0cd880ce7410
blob - 84e9f0d6d6dc4df013f09f0b1bdd0962f9545b82
blob + 6954f20103079d379610484984cb6d26fe47e37a
--- Makefile
+++ Makefile
@@ -12,9 +12,9 @@ checkdoc:
 lint: checkdoc
 	@tmp=$$(mktemp -d); trap 'rm -rf "$$tmp"' EXIT; \
 	  out=$$tmp/lint.log; \
-	  $(EMACS) -Q --batch -L lisp \
+	  $(EMACS) --batch -L lisp \
+	  -l init.el \
 	  --eval '(setq byte-compile-dest-file-function (lambda (f) (expand-file-name (concat (file-name-base f) ".elc") temporary-file-directory)))' \
-	  --eval '(require (quote use-package))' \
 	  --eval '(dolist (f $(MODULES)) (byte-compile-file f))' \
 	  --eval '(byte-compile-file "early-init.el")' \
 	  --eval '(byte-compile-file "init.el")' >"$$out" 2>&1; \
blob - e48a1d171ec3e1f17046554dfbba6e86c5e856e2
blob + a3874f1395c124a08ecc525dd78034004c041c72
--- early-init.el
+++ early-init.el
@@ -2,7 +2,7 @@
 
 ;;; Commentary:
 
-;; Performance and frame defaults applied before `init.el' loads.
+;; Performance and frame defaults applied before 'init.el' loads.
 ;; Keep this file dependency free: no third-party packages here.
 
 ;;; Code:
@@ -10,19 +10,22 @@
 (setq package-enable-at-startup nil)
 
 (defvar mine--initial-file-name-handler-alist file-name-handler-alist
-  "Value of `file-name-handler-alist' before start-up tuning.")
+  "Value of 'file-name-handler-alist' before start-up tuning.")
 
 (setq-default indent-tabs-mode nil)
 
 (setq gc-cons-threshold most-positive-fixnum
       gc-cons-percentage 0.6
+      byte-compile-load t
       file-name-handler-alist nil)
 
 (defun mine--restore-startup-defaults ()
-  "Restore GC and `file-name-handler-alist' for normal use."
+  "Restore GC and 'file-name-handler-alist' for normal use."
   (setq gc-cons-threshold (* 128 1024 1024)
         gc-cons-percentage 0.1
-        file-name-handler-alist mine--initial-file-name-handler-alist))
+        file-name-handler-alist mine--initial-file-name-handler-alist)
+  (unless (eq system-type 'darwin)
+    (setopt byte-compile-load t)))
 
 (add-hook 'emacs-startup-hook #'mine--restore-startup-defaults)
 
blob - ec146775082d6a9b8b275b18eb95710f198b02c1
blob + fc497fdabe3cf8dbff77f4e954e571e9cf027e3d
--- init.el
+++ init.el
@@ -2,20 +2,11 @@
 
 ;;; Commentary:
 
-;; Bootstrap Elpaca, enable its `use-package' support, then load the
-;; configuration modules in `lisp/'.
+;; Bootstrap Elpaca, enable its use-package support, then load the
+;; configuration modules in 'lisp/'.
 
 ;;; Code:
 
-(declare-function elpaca "elpaca" (order &rest body))
-(declare-function elpaca-wait "elpaca" ())
-(declare-function elpaca-process-queues "elpaca" (&optional arg))
-(declare-function elpaca-generate-autoloads "elpaca" (package dir))
-(declare-function elpaca-use-package-mode "elpaca-use-package" (&optional arg))
-(defvar elpaca-use-package)
-(declare-function compile-angel-on-load-mode "compile-angel" (&optional arg))
-(defvar compile-angel-excluded-path-suffixes)
-
 (defvar elpaca-installer-version 0.12)
 (defvar elpaca-directory (expand-file-name "elpaca/" user-emacs-directory))
 (defvar elpaca-builds-directory (expand-file-name "builds/" elpaca-directory))
@@ -24,7 +15,7 @@
                               :ref nil :depth 1 :inherit ignore
                               :files (:defaults "elpaca-test.el" (:exclude "extensions"))
                               :build (:not elpaca-activate)))
-(let* ((repo (expand-file-name "elpaca/" elpaca-sources-directory))
+(let* ((repo  (expand-file-name "elpaca/" elpaca-sources-directory))
        (build (expand-file-name "elpaca/" elpaca-builds-directory))
        (order (cdr elpaca-order))
        (default-directory repo))
@@ -55,9 +46,10 @@
 (add-hook 'after-init-hook #'elpaca-process-queues)
 (elpaca `(,@elpaca-order))
 
-(elpaca elpaca-use-package
+;; Install use-package support. :wait splits queue so mode is active
+;; before subsequent use-package forms.
+(elpaca (elpaca-use-package :wait t)
         (elpaca-use-package-mode))
-(elpaca-wait)
 
 (setopt use-package-always-ensure t
         use-package-expand-minimally t
@@ -68,19 +60,11 @@
 
 (add-to-list 'load-path (expand-file-name "lisp" user-emacs-directory))
 
-(use-package compile-angel
-  :if (not (eq system-type 'darwin))
-  :custom (compile-angel-verbose nil)
-  :config
-  (add-to-list 'compile-angel-excluded-path-suffixes "/init.el")
-  (add-to-list 'compile-angel-excluded-path-suffixes "/early-init.el")
-  (compile-angel-on-load-mode 1))
-
 ;; Load configuration modules.
 (mapc #'require '(setup-core setup-ui setup-evil setup-cmp setup-search
                              setup-treesitter setup-prog setup-eglot setup-git
-                             setup-term-sessions setup-tramp-rpc setup-notes
-                             setup-remind setup-gptel setup-pilish setup-popper
+                             setup-term-sessions setup-shell setup-tramp-rpc setup-notes
+                             setup-remind setup-pilish setup-popper
                              setup-keys))
 
 (defvar mine-cache-directory)
blob - 578f6e2caf6d8ef3e5d036306eab628768c34277
blob + c3849dcbcf533fc6cc0fcde1f38ecff6275a8c33
--- lisp/setup-cmp.el
+++ lisp/setup-cmp.el
@@ -1,4 +1,4 @@
-;;; setup-cmp.el --- Completion, search and jumping  -*- lexical-binding: t; -*-
+;;; setup-cmp.el --- Completion, search and jumping  -*- lexical-binding: t -*-
 
 ;;; Commentary:
 
@@ -67,7 +67,7 @@
 (declare-function dabbrev-capf "dabbrev")
 
 (defun mine-dabbrev-setup-capf ()
-  "Add `dabbrev-capf' as a local fallback completion source."
+  "Add 'dabbrev-capf' as a local fallback completion source."
   (add-hook 'completion-at-point-functions #'dabbrev-capf 90 'local))
 
 (add-hook 'prog-mode-hook #'mine-dabbrev-setup-capf)
@@ -76,7 +76,7 @@
 (declare-function tempel-expand "tempel" (&optional interactive))
 
 (defun mine-tempel-setup-capf ()
-  "Add `tempel-expand' to `completion-at-point-functions' locally."
+  "Add 'tempel-expand' to 'completion-at-point-functions' locally."
   (add-hook 'completion-at-point-functions #'tempel-expand -1 'local))
 
 (use-package tempel
@@ -114,7 +114,7 @@
 (defvar avy-dispatch-alist)
 
 (defun mine-avy-action-embark (pt)
-  "Run `embark-act' at PT, then restore the window avy jumped from."
+  "Run 'embark-act' at PT, then restore the window avy jumped from."
   (unwind-protect
       (save-excursion
         (goto-char pt)
blob - f87bcee1a8abab7df6bdd35448a7eb6d8c57ac1b
blob + 81295e71a23f6528a9899691d798b4eaa715f8fa
--- lisp/setup-core.el
+++ lisp/setup-core.el
@@ -1,4 +1,4 @@
-;;; setup-core.el --- Paths, files, state, undo, clipboard, server  -*- lexical-binding: t; -*-
+;;; setup-core.el --- Paths, files, state, undo, clipboard, server  -*- lexical-binding: t -*-
 
 ;;; Commentary:
 
@@ -27,11 +27,11 @@
   :group 'mine)
 
 (defun mine-cache-file (name)
-  "Return NAME as a file below `mine-cache-directory'."
+  "Return NAME as a file below 'mine-cache-directory'."
   (expand-file-name name mine-cache-directory))
 
 (defun mine-cache-subdir (name)
-  "Return NAME as a directory name below `mine-cache-directory'.
+  "Return NAME as a directory name below 'mine-cache-directory'.
 The directory is created if it does not exist."
   (let ((dir (file-name-as-directory (mine-cache-file name))))
     (make-directory dir t)
@@ -47,8 +47,8 @@ The directory is created if it does not exist."
   "Directory holding file lock files.")
 
 (defun mine-backup-file-name (filename)
-  "Return a backup path mirroring FILENAME under `mine-backup-directory'.
-The leading separator is dropped so that `expand-file-name' treats the
+  "Return a backup path mirroring FILENAME under 'mine-backup-directory'.
+The leading separator is dropped so that 'expand-file-name' treats the
 mirrored path as relative; its parent directories are created."
   (let ((backup (expand-file-name
                  (string-remove-prefix
blob - 7eb3d7c01939fe24f0715ed07b7ca74d67155043
blob + 91abb9af067a0b28b9157eb9faf0738c5a22c744
--- lisp/setup-eglot.el
+++ lisp/setup-eglot.el
@@ -1,4 +1,4 @@
-;;; setup-eglot.el --- Language servers  -*- lexical-binding: t; -*-
+;;; setup-eglot.el --- Language servers  -*- lexical-binding: t -*-
 
 ;;; Commentary:
 
blob - d9c629809ae8756f3cbecd19f19e61c9de5b248b
blob + da7fba590e85f7ce1660ed8a3889f3bf9b813b37
--- lisp/setup-evil.el
+++ lisp/setup-evil.el
@@ -1,4 +1,4 @@
-;;; setup-evil.el --- Modal editing  -*- lexical-binding: t; -*-
+;;; setup-evil.el --- Modal editing  -*- lexical-binding: t -*-
 
 ;;; Commentary:
 
@@ -41,7 +41,7 @@
               ("C-g" . evil-normal-state))
   :config
   (evil-mode 1)
-  (add-hook 'git-commit-setup-hook #'evil-insert-state)
+  (add-hook 'git-commit-setup-hook 'evil-insert-state)
   (evil-set-initial-state 'term-mode 'emacs)
   (evil-set-initial-state 'vterm-mode 'emacs)
 
@@ -55,7 +55,7 @@
   :config
   (defun mine-avy-char-jump (char beg end &optional post)
     "Jump to CHAR between BEG and END, then move by POST."
-    (let* ((regex (if (= char 13) "\n" (regexp-quote (string char))))
+    (let* ((regex (if (= char 13) "\\n" (regexp-quote (string char))))
            (cands (avy--regex-candidates regex beg end))
            (pt (point)))
       (cond
blob - 33fdef5c8837e21736639b2987f0d41f3d47ca70
blob + 2a04c45fa6c5c189d1ab6836fc0a9a390432deca
--- lisp/setup-git.el
+++ lisp/setup-git.el
@@ -1,4 +1,4 @@
-;;; setup-git.el --- Version control  -*- lexical-binding: t; -*-
+;;; setup-git.el --- Version control  -*- lexical-binding: t -*-
 
 ;;; Commentary:
 
blob - f559654f0e61751ef9ef1e9a91a90869efa63153 (mode 644)
blob + /dev/null
--- lisp/setup-gptel.el
+++ /dev/null
@@ -1,473 +0,0 @@
-;;; setup-gptel.el --- Large language models  -*- lexical-binding: t; -*-
-
-;;; Commentary:
-
-;; Configure Gptel backends, transcript persistence, and local tools.
-
-;;; Code:
-
-(require 'auth-source)
-(require 'json)
-(require 'subr-x)  ; string-empty-p
-(require 'project)
-(require 'url)
-
-(defvar mine-notes-directory)
-
-(declare-function denote
-                  "denote"
-                  (title &optional keywords file-type subdirectory date template signature))
-(declare-function denote-date-org-timestamp "denote" (date))
-(declare-function denote-format-keywords-for-org-front-matter "denote" (keywords))
-(declare-function denote-format-file-name "denote")
-(declare-function mine-cache-subdir "setup-core" (name))
-(declare-function gptel-make-openai-oauth "gptel-openai-oauth" (name &rest args))
-(defvar denote-org-front-matter)
-(defvar denote-get-identifier-function)
-(defvar gptel-tools)
-(defvar gptel-mode-map)
-(defvar gptel--openai-oauth-token-file)
-
-(declare-function evil-insert-state "evil" ())
-(declare-function gptel-mode "gptel" (&optional arg))
-(declare-function gptel-make-openai "gptel-openai" (name &rest args))
-(declare-function gptel-make-preset "gptel" (name &rest keys))
-(declare-function gptel-get-backend "gptel-request" (name))
-(declare-function gptel-get-tool "gptel-request" (path))
-(declare-function gptel-make-tool "gptel-request" (&rest slots))
-(declare-function gptel-prompt-prefix-string "gptel-request" ())
-
-(defun mine-gptel-ollama-api-key ()
-  "Return the Ollama Cloud API key stored in auth-source.
-Expects a line in `auth-sources' for host ollama.com, user apikey."
-  (or (auth-source-pick-first-password :host "ollama.com" :user "apikey")
-      (user-error "No Ollama API key in auth-source for host ollama.com")))
-
-(defun mine-gptel-openai-api-key ()
-  "Return the OpenAI API key stored in auth-source.
-Expects a line in `auth-sources' for host api.openai.com, user apikey."
-  (or (auth-source-pick-first-password :host "api.openai.com" :user "apikey")
-      (user-error "No OpenAI API key in auth-source for host api.openai.com")))
-
-(defun mine-gptel-ollama--parse-response (path)
-  "Parse the current buffer as an Ollama API response for PATH."
-  (goto-char (point-min))
-  (let ((status (and (re-search-forward "^HTTP/[0-9.]+ \\([0-9]+\\)" nil t)
-                     (string-to-number (match-string 1)))))
-    (unless (re-search-forward "\\r?\\n\\r?\\n" nil t)
-      (error "Malformed response from Ollama API"))
-    (let ((body (json-parse-buffer :object-type 'alist
-                                   :array-type 'list
-                                   :null-object nil
-                                   :false-object nil)))
-      (when (and status (>= status 400))
-        (error "Ollama API %s failed (HTTP %d): %s" path status
-               (or (alist-get 'error body) body)))
-      body)))
-
-(defun mine-gptel-ollama-post (callback path payload)
-  "Asynchronously POST PAYLOAD to Ollama API PATH, then call CALLBACK."
-  (let* ((url-request-method "POST")
-         (url-request-extra-headers
-          `(("Content-Type" . "application/json")
-            ("Authorization" . ,(concat "Bearer " (mine-gptel-ollama-api-key)))))
-         (url-request-data
-          (encode-coding-string (json-encode payload) 'utf-8)))
-    (url-retrieve
-     (concat "https://ollama.com" path)
-     (lambda (status)
-       (unwind-protect
-           (funcall callback
-                    (condition-case err
-                        (if-let* ((network-error (plist-get status :error)))
-                            (format "Ollama API request to %s failed: %s" path network-error)
-                          (mine-gptel-ollama--parse-response path))
-                      (error (format "Ollama API request to %s failed: %s" path err))))
-         (kill-buffer (current-buffer))))
-     nil t t)))
-
-(defun mine-gptel-web-search (callback query &optional max-results)
-  "Call CALLBACK with web-search results for QUERY.
-Return at most MAX-RESULTS (1-10) hits."
-  (let* ((payload `(("query" . ,query)
-                    ,@(when (and (integerp max-results) (> max-results 0))
-                        `(("max_results" . ,(min max-results 10)))))))
-    (mine-gptel-ollama-post
-     (lambda (response)
-       (if (stringp response)
-           (funcall callback response)
-         (let ((results (alist-get 'results response)))
-           (funcall callback
-                    (if (null results)
-                        "No results found."
-                      (mapconcat (lambda (r)
-                                   (format "## %s\n%s\n\n%s"
-                                           (alist-get 'title r)
-                                           (alist-get 'url r)
-                                           (alist-get 'content r)))
-                                 results "\n\n---\n\n"))))))
-     "/api/web_search" payload)))
-
-(defun mine-gptel-web-fetch (callback url)
-  "Call CALLBACK with the main text content extracted from URL."
-  (mine-gptel-ollama-post
-   (lambda (response)
-     (if (stringp response)
-         (funcall callback response)
-       (let ((content (alist-get 'content response)))
-         (funcall callback
-                  (if (and (stringp content) (not (string-empty-p content)))
-                      (format "# %s\n\n%s" (or (alist-get 'title response) url) content)
-                    "Could not extract any content from that URL.")))))
-   "/api/web_fetch" `(("url" . ,url))))
-
-(defun mine-gptel-read-buffer (buffer)
-  "Return the full contents of live BUFFER."
-  (unless (buffer-live-p (get-buffer buffer))
-    (error "Error: buffer %s is not live" buffer))
-  (with-current-buffer buffer
-    (buffer-substring-no-properties (point-min) (point-max))))
-
-(defun mine-gptel--local-path (path)
-  "Return canonical local PATH, rejecting TRAMP paths.
-PATH must name an existing local file or directory."
-  (let ((expanded (expand-file-name path)))
-    (when (file-remote-p expanded)
-      (user-error "Remote paths are not available to GPTel tools: %s" path))
-    (unless (file-exists-p expanded)
-      (user-error "Path does not exist: %s" expanded))
-    (file-truename expanded)))
-
-(defun mine-gptel--command-root ()
-  "Return the local project root for the current GPTel command request."
-  (let* ((directory (mine-gptel--local-path default-directory))
-         (project (project-current nil directory))
-         (root (if project (project-root project) directory)))
-    (file-name-as-directory (file-truename root))))
-
-(defun mine-gptel--command-directory (working-dir)
-  "Validate WORKING-DIR and return a directory beneath the project root."
-  (let* ((root (mine-gptel--command-root))
-         (directory (mine-gptel--local-path
-                     (if (and working-dir (not (string-empty-p working-dir)))
-                         (expand-file-name working-dir default-directory)
-                       default-directory))))
-    (unless (file-directory-p directory)
-      (user-error "Working directory is not a directory: %s" directory))
-    (unless (file-in-directory-p directory root)
-      (user-error "Working directory must be inside %s" root))
-    (file-name-as-directory directory)))
-
-(defun mine-gptel-read-file (path)
-  "Return the contents of local file PATH."
-  (with-temp-buffer
-    (insert-file-contents (mine-gptel--local-path path))
-    (buffer-string)))
-
-(defun mine-gptel-list-directory (directory)
-  "Return the entries of local DIRECTORY, one per line."
-  (let ((directory (mine-gptel--local-path directory)))
-    (unless (file-directory-p directory)
-      (user-error "Not a directory: %s" directory))
-    (string-join (directory-files directory nil
-                                  directory-files-no-dot-files-regexp)
-                 "\n")))
-
-(defun mine-gptel-run-command (command &optional working-dir)
-  "Run shell COMMAND inside the current project's WORKING-DIR.
-WORKING-DIR defaults to `default-directory' and must be within the
-current project, or that directory when no project is active.  Remote
-directories are never permitted.  GPTel always asks for confirmation
-before this tool runs."
-  (unless (and (stringp command) (not (string-empty-p command)))
-    (user-error "Command must be a non-empty string"))
-  (with-temp-message (format "Executing: %s" command)
-    (let ((default-directory (mine-gptel--command-directory working-dir)))
-      (with-temp-buffer
-        (let ((status (call-process shell-file-name nil (list (current-buffer) t)
-                                    nil shell-command-switch command))
-              (output (buffer-string)))
-          (if (and (integerp status) (zerop status))
-              output
-            (error "Command failed (%s): %s" status (string-trim output))))))))
-
-(defvar mine-gptel-keywords '("ai" "gptel")
-  "Denote keywords applied to gptel sessions and saved transcripts.")
-
-(defvar mine-gptel-save-directory
-  mine-notes-directory
-  "Directory where chat transcripts are saved as Denote Org notes.
-Chat transcripts are stored directly in `~/notes`, not a subdirectory.")
-
-(defun mine-gptel-denote-session ()
-  "Create a Denote note and start a gptel session in it."
-  (interactive)
-  (denote (read-string "GPTel session title: ") mine-gptel-keywords)
-  (gptel-mode))
-
-(defun mine-gptel--default-title ()
-  "Return a note title derived from the buffer name, without its earmuffs."
-  (string-trim (buffer-name) "\\*+" "\\*+"))
-
-(defun mine-gptel--front-matter (title identifier)
-  "Return Denote Org front matter for TITLE and IDENTIFIER."
-  (format denote-org-front-matter
-          title
-          (denote-date-org-timestamp (current-time))
-          (denote-format-keywords-for-org-front-matter mine-gptel-keywords)
-          identifier
-          ""))
-
-(defun mine-gptel--note-file (title identifier)
-  "Return the note file name for TITLE and IDENTIFIER, creating its directory."
-  (let ((dir (file-name-as-directory mine-gptel-save-directory)))
-    (make-directory dir t)
-    (denote-format-file-name dir identifier mine-gptel-keywords title ".org" "")))
-
-(defun mine-gptel--transcript (title identifier)
-  "Return the transcript text for a note titled TITLE with IDENTIFIER.
-An active region is returned verbatim, as is a buffer that already
-carries Org front matter.  Anything else is prefixed with Denote
-front matter."
-  (if (use-region-p)
-      (buffer-substring-no-properties (region-beginning) (region-end))
-    (let ((body (buffer-substring-no-properties (point-min) (point-max))))
-      (if (string-match-p "\\`\\s-*#\\+title:" body)
-          body
-        (concat (mine-gptel--front-matter title identifier) body)))))
-
-(defun mine-gptel-save-chat (title)
-  "Save the current buffer to `mine-gptel-save-directory' as a Denote note.
-TITLE names the note and seeds its file name.  With an active
-region, only the region is saved."
-  (interactive (list (read-string "Chat title: " (mine-gptel--default-title))))
-  (require 'denote)
-  (let* ((id (funcall denote-get-identifier-function nil nil))
-         (file (mine-gptel--note-file title id))
-         (content (mine-gptel--transcript title id)))
-    (with-temp-file file
-      (insert content))
-    (message "Saved chat transcript to %s" file)
-    file))
-
-(defun mine-gptel-auto-save (_beg _end)
-  "Save the current gptel buffer if it is a Denote note.
-Called from `gptel-post-response-functions', which passes the response
-beginning and end positions; both are ignored."
-  (when (and buffer-file-name
-             (derived-mode-p 'org-mode)
-             (string-prefix-p (file-name-as-directory mine-notes-directory)
-                              buffer-file-name))
-    (save-buffer)))
-
-(defun mine-gptel--blank-p ()
-  "Determine whether the chat has anything worth keeping.
-A buffer counts as blank when all that remains after stripping
-whitespace and gptel's prompt prefix is nothing.  `gptel' seeds every
-new chat with that prefix, so an untouched chat must not be saved."
-  (let ((text (string-trim (buffer-substring-no-properties
-                            (point-min) (point-max))))
-        (prefix (string-trim (or (gptel-prompt-prefix-string) ""))))
-    (or (string-empty-p text)
-        (and (not (string-empty-p prefix))
-             (string-empty-p (string-trim (string-remove-prefix prefix text)))))))
-
-(defun mine-gptel--adopt-note ()
-  "Give the current unsaved chat a Denote file name and save it.
-Front matter is prepended and the buffer visits the new file, so
-`gptel-mode' writes its own state through `before-save-hook' and the
-conversation can be resumed by reopening the note."
-  (let* ((title (mine-gptel--default-title))
-         (_ (require 'denote))
-         (id (funcall denote-get-identifier-function nil nil))
-         (file (mine-gptel--note-file title id)))
-    (save-excursion
-      (goto-char (point-min))
-      (insert (mine-gptel--front-matter title id)))
-    (set-visited-file-name file :no-query)
-    (save-buffer)
-    file))
-
-(defun mine-gptel-save-on-kill ()
-  "Save the current chat when its gptel buffer is killed.
-A chat already visiting a file is just saved; an unsaved one becomes a
-new Denote note.  Blank buffers are skipped, and any failure is reported
-rather than left to block `kill-buffer'."
-  (when (and (bound-and-true-p gptel-mode)
-             (not (mine-gptel--blank-p)))
-    (with-demoted-errors "Could not save gptel chat: %S"
-      (cond ((not buffer-file-name) (mine-gptel--adopt-note))
-            ((buffer-modified-p) (save-buffer))))))
-
-(defun mine-gptel-save-all-chats ()
-  "Run `mine-gptel-save-on-kill' in every live gptel buffer.
-Killing Emacs does not run `kill-buffer-hook', so this covers exiting
-with chats still open."
-  (dolist (buffer (buffer-list))
-    (with-current-buffer buffer
-      (mine-gptel-save-on-kill))))
-
-(defun mine-gptel-enable-save-on-kill ()
-  "Save non-empty gptel chats when their buffers are killed."
-  (when (bound-and-true-p gptel-mode)
-    (add-hook 'kill-buffer-hook #'mine-gptel-save-on-kill nil :local)))
-
-(add-hook 'gptel-mode-hook #'mine-gptel-enable-save-on-kill)
-
-(defun mine-gptel-enable-insert-state ()
-  "Start gptel chats in Evil insert state.
-This makes a chat buffer immediately ready for typing instead of treating
-ordinary input as Normal-state motions at the end of the buffer."
-  (when (fboundp 'evil-insert-state)
-    (evil-insert-state)))
-
-(add-hook 'gptel-mode-hook #'mine-gptel-enable-insert-state)
-
-(add-hook 'kill-emacs-hook #'mine-gptel-save-all-chats)
-
-(use-package gptel
-  :demand t
-  :bind (:map gptel-mode-map
-              ("C-c RET" . gptel-send)
-              ("C-c C-r" . gptel-rewrite)
-              ("C-c C-a" . gptel-add))
-  :custom
-  (gptel-use-curl t)
-  (gptel-stream t)
-  (gptel-default-mode 'org-mode)
-  (gptel-use-header-line t)
-  (gptel-org-ignore-elements '(property-drawer))
-  (gptel-use-tools t)
-  (gptel-confirm-tool-calls 'auto)
-  (gptel-include-tool-results 'auto)
-  (gptel-directives
-   '((default
-      . "You are a large language model living in Emacs and a helpful assistant. Respond concisely.")
-     (programming
-      . "You are a careful programmer working from inside Emacs. Provide code, with minimal surrounding prose.")
-     (chat
-      . "You are a conversation partner. Respond concisely.")))
-  :config
-  (require 'gptel-openai)
-
-  (setq gptel--openai-oauth-token-file
-        (expand-file-name "openai-oauth-token"
-                          (mine-cache-subdir "gptel-openai")))
-
-  (gptel-make-openai "OpenAI"
-                     :key #'mine-gptel-openai-api-key)
-
-  (gptel-make-openai-oauth "Codex")
-
-  (gptel-make-openai "Ollama Cloud"
-                     :host "ollama.com"
-                     :protocol "https"
-                     :endpoint "/v1/chat/completions"
-                     :stream t
-                     :key #'mine-gptel-ollama-api-key
-                     :models '(kimi-k2.6:cloud
-                               kimi-k2.7-code:cloud
-                               kimi-k3:cloud
-                               qwen3.6:cloud
-                               glm-5.2:cloud
-                               gpt-oss:120b-cloud
-                               minimax-m3:cloud))
-
-
-  (setopt gptel-backend (gptel-get-backend "Ollama Cloud")
-          gptel-model 'minimax-m3:cloud)
-
-  (add-hook 'gptel-post-stream-hook 'gptel-auto-scroll)
-  (add-hook 'gptel-post-response-functions #'mine-gptel-auto-save))
-
-(defvar mine-gptel-tools
-  `((:name "web_search"
-           :category "web"
-           :function mine-gptel-web-search
-           :async t
-           :description
-           ,(concat "Search the web and return a list of results, each with a "
-                    "title, URL and a content snippet.  Use this for current "
-                    "events or anything outside your training data, then call "
-                    "`web_fetch' on a promising URL to read it in full.")
-           :args ((:name "query" :type string
-                         :description "The search query.")
-                  (:name "max_results" :type integer :optional t
-                         :description "How many results to return (1-10, default 5).")))
-
-    (:name "web_fetch"
-           :category "web"
-           :function mine-gptel-web-fetch
-           :async t
-           :description
-           "Fetch and return the main text content of a web page, given its URL."
-           :args ((:name "url" :type string
-                         :description "The full URL of the page to fetch.")))
-
-    (:name "read_buffer"
-           :category "emacs"
-           :function mine-gptel-read-buffer
-           :confirm t
-           :description "Return the full contents of a live Emacs buffer."
-           :args ((:name "buffer" :type string
-                         :description "The name of the buffer to read.")))
-
-    (:name "read_file"
-           :category "filesystem"
-           :function mine-gptel-read-file
-           :confirm t
-           :description "Read and return the contents of a file on disk."
-           :args ((:name "filepath" :type string
-                         :description "Path to the file.  Supports relative paths and ~.")))
-
-    (:name "list_directory"
-           :category "filesystem"
-           :function mine-gptel-list-directory
-           :confirm t
-           :description "List the entries in a directory."
-           :args ((:name "directory" :type string
-                         :description "The path to the directory to list.")))
-
-    (:name "run_command"
-           :category "command"
-           :function mine-gptel-run-command
-           :confirm t
-           :include t
-           :description "Execute a shell command and return its combined output."
-           :args ((:name "command" :type string
-                         :description "The complete shell command to run.")
-                  (:name "working_dir" :type string :optional t
-                         :description "Directory to run in (default: current)."))))
-  "Declarations for the gptel tools defined in this configuration.")
-
-(with-eval-after-load 'gptel
-  (dolist (spec mine-gptel-tools)
-    (apply #'gptel-make-tool spec))
-
-  (setq gptel-tools (append (gptel-get-tool "web")
-                            (gptel-get-tool "emacs")
-                            (gptel-get-tool "filesystem")
-                            (gptel-get-tool "command")))
-
-  (gptel-make-preset 'research
-                     :description "Web research: search and fetch, then synthesise."
-                     :system
-                     (concat "You are a research assistant working inside Emacs.  Use the "
-                             "web tools to gather up-to-date information before answering: "
-                             "`web_search' to find sources and `web_fetch' to read them.  "
-                             "Always cite the URLs you used.  Be concise.")
-                     :tools '("web_search" "web_fetch")
-                     :confirm-tool-calls nil)
-
-  (gptel-make-preset 'agent
-                     :description "Coding agent: read files/buffers and run commands in Emacs."
-                     :system
-                     (concat "You are a careful coding agent operating inside Emacs.  Use "
-                             "the filesystem and buffer tools to inspect the project, and "
-                             "`run_command' to build, test or inspect the repo.  Explain "
-                             "what you will do, then act.  Prefer minimal, surgical changes.")
-                     :tools '("read_file" "read_buffer" "list_directory" "run_command")
-                     :confirm-tool-calls t))
-
-(provide 'setup-gptel)
-;;; setup-gptel.el ends here
blob - 0e89872485f1eecb49c8d20b405a8b74c25c4eca
blob + 3eb6a2a259eb9f74813b8055c6c304215a39d88b
--- lisp/setup-keys.el
+++ lisp/setup-keys.el
@@ -1,4 +1,4 @@
-;;; setup-keys.el --- Prefix maps and the evil leader  -*- lexical-binding: t; -*-
+;;; setup-keys.el --- Prefix maps and the evil leader  -*- lexical-binding: t -*-
 
 ;;; Commentary:
 
@@ -22,19 +22,9 @@
 (declare-function mine-remind-show-next "setup-remind" (&optional source))
 (declare-function mine-remind-check "setup-remind" (&optional source))
 (declare-function mine-remind-export-org-agenda "setup-remind" (&optional source))
-(declare-function mine-gptel-denote-session "setup-gptel" ())
-(declare-function mine-gptel-save-chat "setup-gptel" (&optional title))
 
 (declare-function pilish "pilish" (&optional arg))
 
-(declare-function gptel-send "gptel" (&optional arg))
-(declare-function gptel-menu "gptel" ())
-(declare-function gptel-rewrite "gptel" ())
-(declare-function gptel-add "gptel" (&optional arg))
-(declare-function gptel-add-file "gptel" (file))
-(declare-function gptel-preset "gptel" (&optional position))
-(declare-function gptel-tools "gptel" ())
-
 (keymap-global-set "C-x k" #'kill-current-buffer)
 (keymap-global-set "C-x s" #'mine-save-all-buffers)
 (keymap-global-set "C-h d" #'describe-symbol)
@@ -66,23 +56,10 @@
   "v" #'mine-remind-check
   "a" #'mine-remind-export-org-agenda)
 
-(defvar-keymap mine-gptel-prefix-map
-  :doc "Prefix map for gptel commands."
-  "s" #'gptel-send
-  "m" #'gptel-menu
-  "r" #'gptel-rewrite
-  "a" #'gptel-add
-  "A" #'gptel-add-file
-  "p" #'gptel-preset
-  "t" #'gptel-tools
-  "n" #'mine-gptel-denote-session
-  "S" #'mine-gptel-save-chat)
-
 (keymap-global-set "C-c f" mine-file-prefix-map)
 (keymap-global-set "C-c g" #'mine-consult-project-search)
 (keymap-global-set "C-c n" mine-notes-prefix-map)
 (keymap-global-set "C-c r" mine-remind-prefix-map)
-(keymap-global-set "C-c L" mine-gptel-prefix-map)
 (keymap-global-set "C-c p" #'pilish)
 
 (provide 'setup-keys)
blob - 53d9aea649bccf3742503dd5d9daa6e8dfb140b3
blob + 81852de33f413d9117f19b4a7541df63935689a7
--- lisp/setup-notes.el
+++ lisp/setup-notes.el
@@ -1,4 +1,4 @@
-;;; setup-notes.el --- Org, Babel and Denote  -*- lexical-binding: t; -*-
+;;; setup-notes.el --- Org, Babel and Denote  -*- lexical-binding: t -*-
 
 ;;; Commentary:
 
@@ -95,7 +95,7 @@
   :custom
   (denote-journal-keyword "journal")
   (denote-journal-file-type 'org)
-  ;; NIL makes journal entries share the flat `denote-directory`.
+  ;; NIL makes journal entries share the flat 'denote-directory'.
   (denote-journal-directory nil))
 
 (use-package denote-org
blob - d525da5a128ee83330ab1f1316ec858fb6eacc26
blob + 848c67a06dd2ba330a392ff379e202ed4c4fc053
--- lisp/setup-pilish.el
+++ lisp/setup-pilish.el
@@ -1,4 +1,4 @@
-;;; setup-pilish.el --- Pi coding agent frontend  -*- lexical-binding: t; -*-
+;;; setup-pilish.el --- Pi coding agent frontend  -*- lexical-binding: t -*-
 
 ;;; Commentary:
 
blob - dd0e043f8823468d774fd3aecca95b0cf04ba59c
blob + 72c1e23aa71a1db9a5a7b2723031447a1c73c501
--- lisp/setup-popper.el
+++ lisp/setup-popper.el
@@ -1,9 +1,9 @@
-;;; setup-popper.el --- Popup buffers that rotate between shells and Pilish  -*- lexical-binding: t; -*-
+;;; setup-popper.el --- Popup buffers that rotate between shells and Pilish  -*- lexical-binding: t -*-
 
 ;;; Commentary:
 
 ;; Popper keeps shell and Pilish buffers out of the way until summoned.
-;; `popper-cycle' rotates between them.
+;; 'popper-cycle' rotates between them.
 
 ;;; Code:
 
blob - fae55202b7b8a81eadf0938f240b8f8d1436357a
blob + 12cc028a84ae4cc3bf488f45f467adf669cc46b9
--- lisp/setup-prog.el
+++ lisp/setup-prog.el
@@ -1,4 +1,4 @@
-;;; setup-prog.el --- Programming  -*- lexical-binding: t; -*-
+;;; setup-prog.el --- Programming  -*- lexical-binding: t -*-
 
 ;;; Commentary:
 
@@ -52,6 +52,13 @@
 (use-package purescript-mode
   :mode "\\.purs\\'")
 
+(use-package odin-mode
+  :ensure (:host github :repo "mattt-b/odin-mode")
+  :mode "\\.odin\\'")
+
+(use-package tuareg
+  :mode ("\\.ml[iylp]?\\'" "\\.ocamlinit\\'"))
+
 (use-package clojure-mode
   :mode ("\\.clj\\'" "\\.bb\\'"))
 
@@ -60,6 +67,14 @@
   :commands (inf-clojure inf-clojure-connect inf-clojure-socket-repl)
   :hook (clojure-mode . inf-clojure-minor-mode))
 
+(use-package sly-quicklisp
+  :after sly
+  :config
+  (setq sly-quicklisp-home "/home/miro/src/proj/quicklisp/"))
+
+(use-package sly-asdf
+  :after sly)
+
 (use-package sly
   :commands (sly sly-connect)
   :custom
@@ -74,7 +89,6 @@
         (sly-setup '(sly-fancy sly-quicklisp sly-asdf))
       (error (message "sly-setup failed: %s" (error-message-string err))))))
 
-;; Chez / Scheme support via Geiser
 (dolist (entry '(("\\.ss\\'"  . scheme-mode)
                  ("\\.sls\\'" . scheme-mode)
                  ("\\.scm\\'" . scheme-mode)))
blob - e24811e62396c816265bcb12e02682cd103ba727
blob + a2fd95fed74aaf45144bc5b4f06a243bec274d52
--- lisp/setup-remind.el
+++ lisp/setup-remind.el
@@ -1,4 +1,4 @@
-;;; setup-remind.el --- Remind calendar editing and Org Agenda export -*- lexical-binding: t; -*-
+;;; setup-remind.el --- Remind calendar editing and Org Agenda export -*- lexical-binding: t -*-
 
 ;;; Commentary:
 
@@ -63,7 +63,7 @@
     (define-derived-mode remind-mode remind-conf-mode "Remind"
       "Major mode for editing Remind calendar files.
 
-This extends Remind's contributed `remind-conf-mode', including its syntax
+This extends Remind's contributed 'remind-conf-mode', including its syntax
 highlighting, indentation, and reminder/date insertion commands.")
   ;; Leave Emacs usable if the optional checkout is moved or removed.
   (define-derived-mode remind-mode text-mode "Remind"
@@ -109,12 +109,12 @@ highlighting, indentation, and reminder/date insertion
     (pop-to-buffer buffer)))
 
 (defun mine-remind-open ()
-  "Open `mine-remind-default-file'."
+  "Open 'mine-remind-default-file'."
   (interactive)
   (find-file mine-remind-default-file))
 
 (defun mine-remind-check (source)
-  "Validate SOURCE without allowing `RUN' directives or `shell()'."
+  "Validate SOURCE without allowing 'RUN' directives or 'shell()'."
   (interactive (list (mine-remind--source-file)))
   (mine-remind--call source "-n")
   (message "Remind source is valid: %s" source))
@@ -133,8 +133,8 @@ highlighting, indentation, and reminder/date insertion
 
 (defun mine-remind--org-entry (line)
   "Return an Org entry for Remind simple-calendar LINE, or nil.
-The fifth field is either `*' for all-day events or minutes after midnight.
-Requesting `-b2' makes the remaining text unambiguous and lets this function
+The fifth field is either '*' for all-day events or minutes after midnight.
+Requesting '-b2' makes the remaining text unambiguous and lets this function
 derive a locale-independent 24-hour Org timestamp."
   (when (string-match mine-remind--simple-calendar-regexp line)
     (let* ((date (replace-regexp-in-string "/" "-" (match-string 1 line)))
@@ -178,7 +178,7 @@ Other contents of OUTPUT, such as hand-written agenda 
       (save-buffer))))
 
 (defun mine-remind-export-org-agenda (source)
-  "Upsert SOURCE's simple calendar into its `agenda.org' Org Agenda file."
+  "Upsert SOURCE's simple calendar into its 'agenda.org' Org Agenda file."
   (interactive (list (mine-remind--source-file)))
   (let* ((output (expand-file-name "agenda.org"
                                    (file-name-directory source)))
blob - b2ae5236bf2102d55e4aff3066848a52930adac0
blob + 125c953b215904b3b860171d79d9cbc2e79d3d7c
--- lisp/setup-search.el
+++ lisp/setup-search.el
@@ -1,4 +1,4 @@
-;;; setup-search.el --- ugrep-backed project and grep searches  -*- lexical-binding: t; -*-
+;;; setup-search.el --- ugrep-backed project and grep searches  -*- lexical-binding: t -*-
 
 ;;; Commentary:
 
@@ -26,8 +26,8 @@ INITIAL is the initial minibuffer input."
     (consult-ripgrep dir initial)))
 
 (when (executable-find "ugrep")
-  ;; Emacs 29 and later ship the `ugrep' Xref backend.  This makes
-  ;; `project-find-regexp' use it as well as the regular grep commands.
+  ;; Emacs 29 and later ship the 'ugrep' Xref backend.  This makes
+  ;; 'project-find-regexp' use it as well as the regular grep commands.
   (setopt xref-search-program 'ugrep
           grep-template "ugrep --color=always -0Iinr -e <R>")
 
blob - ada079107721d4e09bd59a6a3fbbc35c868dc86e
blob + 327650471097f40698a3f6f5b1248e5bfa905109
--- lisp/setup-shell.el
+++ lisp/setup-shell.el
@@ -1,4 +1,4 @@
-;;; setup-shell.el --- Shells and remote hosts  -*- lexical-binding: t; -*-
+;;; setup-shell.el --- Shells and remote hosts  -*- lexical-binding: t -*-
 
 ;;; Commentary:
 
@@ -9,7 +9,7 @@
 (declare-function consult-history "consult" (&optional history-elements))
 
 (defun mine-eshell-setup ()
-  "Bind `C-r' to `consult-history' in Eshell."
+  "Set up Eshell with consult-history binding."
   (keymap-set (current-local-map) "C-r" #'consult-history))
 
 (use-package eshell
@@ -17,7 +17,7 @@
   :hook (eshell-mode . mine-eshell-setup))
 
 (use-package eat
-  :ensure (eat :repo "https://codeberg.org/akib/emacs-eat"
+  :ensure (eat :host codeberg :repo "akib/emacs-eat"
                :files ("*.el" ("term" "term/*.el") "*.texi"
                        "*.ti" ("terminfo/e" "terminfo/e/*")
                        ("terminfo/65" "terminfo/65/*")
@@ -26,6 +26,7 @@
   :commands (eat eat-project))
 
 (use-package vterm
+  :defer t
   :commands vterm)
 
 (use-package tramp
blob - 86be0e8d66338bbf57bff23465cef56c2eb8a405
blob + a98e01991f1625ad131fed6ac38b8052aa39b2a5
--- lisp/setup-term-sessions.el
+++ lisp/setup-term-sessions.el
@@ -1,4 +1,4 @@
-;;; setup-term-sessions.el --- Persistent terminal sessions  -*- lexical-binding: t; -*-
+;;; setup-term-sessions.el --- Persistent terminal sessions  -*- lexical-binding: t -*-
 
 ;;; Commentary:
 
blob - 04d426a24d0644987eeea10817e589e4797eebc0
blob + 83efc564e4db867f13f0075ec0f8004d4714237b
--- lisp/setup-tramp-rpc.el
+++ lisp/setup-tramp-rpc.el
@@ -1,8 +1,8 @@
-;;; setup-tramp-rpc.el --- High-performance TRAMP backend  -*- lexical-binding: t; -*-
+;;; setup-tramp-rpc.el --- High-performance TRAMP backend  -*- lexical-binding: t -*-
 
 ;;; Commentary:
 
-;; Configure tramp-rpc: a Rust-backed TRAMP backend accessed via the `rpc'
+;; Configure tramp-rpc: a Rust-backed TRAMP backend accessed via the 'rpc'
 ;; method (e.g. /rpc:user@host:/path/to/file).
 
 ;;; Code:
blob - 3beb932f8544b7f1352a56cfd9d7faaa7bbdd15f
blob + 9ef4c601f57f8c18b656ea1a67f6e1f2d5c83a86
--- lisp/setup-treesitter.el
+++ lisp/setup-treesitter.el
@@ -1,4 +1,4 @@
-;;; setup-treesitter.el --- Tree-sitter grammar management  -*- lexical-binding: t; -*-
+;;; setup-treesitter.el --- Tree-sitter grammar management  -*- lexical-binding: t -*-
 
 ;;; Commentary:
 
@@ -54,21 +54,21 @@ Each entry has the form:
 
   (LANGUAGE REPOSITORY BRANCH PATH)
 
-LANGUAGE is the symbol accepted by `treesit-install-language-grammar'.
+LANGUAGE is the symbol accepted by 'treesit-install-language-grammar'.
 REPOSITORY is a Git URL, BRANCH is its revision, and PATH is the grammar
 directory relative to the repository root."
   :type '(repeat (list symbol string string string))
   :group 'treesit)
 
 (defun mine-treesit-register-grammars ()
-  "Register `mine-treesit-grammar-sources' with Emacs tree-sitter."
+  "Register 'mine-treesit-grammar-sources' with Emacs tree-sitter."
   (dolist (source mine-treesit-grammar-sources)
     (pcase-let ((`(,language ,repository ,branch ,path) source))
       (setf (alist-get language treesit-language-source-alist)
             (list repository branch path)))))
 
 (defun mine-treesit-install-grammars ()
-  "Install every unavailable grammar in `mine-treesit-grammar-sources'."
+  "Install every unavailable grammar in 'mine-treesit-grammar-sources'."
   (interactive)
   (mine-treesit-register-grammars)
   (dolist (source mine-treesit-grammar-sources)
blob - 33acad841d563f3024c91301e5b9afd4bc12c5f7
blob + ccfb6b182b8bb770d21863bad7d4db4a3d70447f
--- lisp/setup-ui.el
+++ lisp/setup-ui.el
@@ -1,4 +1,4 @@
-;;; setup-ui.el --- Chrome, fonts, colours, scrolling, windows  -*- lexical-binding: t; -*-
+;;; setup-ui.el --- Chrome, fonts, colours, scrolling, windows  -*- lexical-binding: t -*-
 
 ;;; Commentary:
 
@@ -95,9 +95,8 @@
 (add-hook 'enable-theme-functions #'mine-theme--record)
 
 (unless (display-graphic-p)
-  (condition-case nil
-      (load-theme 'eziam-dark t)
-    (error (load-theme 'ef-night t))))
+  (or (ignore-errors (load-theme 'eziam-dark t))
+      (ignore-errors (load-theme 'punpun-dark t))))
 
 (use-package doric-themes
   :ensure (:host github :repo "protesilaos/doric-themes"))
@@ -113,10 +112,6 @@
                   t)
     (error (load-theme 'ef-winter t))))
 
-;; Vendored third-party snapshots, theme files already say no-byte-compile.
-(when (boundp 'compile-angel-excluded-path-suffixes)
-  (add-to-list 'compile-angel-excluded-path-suffixes "/themes/"))
-
 (setopt display-line-numbers-width 3)
 
 (add-hook 'prog-mode-hook #'display-line-numbers-mode)
@@ -147,8 +142,7 @@
 (when (boundp 'mode-line-collapse-minor-modes)
   (setopt mode-line-collapse-minor-modes
           '(evil-collection-unimpaired-mode
-            which-key-mode
-            compile-angel-on-load-mode)))
+            which-key-mode)))
 
 (provide 'setup-ui)
 ;;; setup-ui.el ends here
blob - 1109c06c392f3d1b4ad65d960a274a5a59efe367
blob + a94f5852db2f834e911e056136f7e1cd3546710e
--- themes/eziam/eziam-dark-theme.el
+++ themes/eziam/eziam-dark-theme.el
@@ -50,22 +50,22 @@
    ("color-7"                . "#eeeeee")
    ("color-8"                . "#ffffff")
    ;; Headings
-   ("ol1-fg"                 . nil)
+   ("ol1-fg"                 . unspecified)
    ("ol1-bg"                 . "#000000")
-   ("ol2-fg"                 . nil)
+   ("ol2-fg"                 . unspecified)
    ("ol2-bg"                 . "#063545")
-   ("ol3-fg"                 . nil)
+   ("ol3-fg"                 . unspecified)
    ("ol3-bg"                 . "#186b8c")
    ("ol4-fg"                 . "#222222")
    ("ol4-bg"                 . "#1e85ae")
    ("ol5-fg"                 . "#222222")
    ("ol5-bg"                 . "#96a4ab")
-   ("ol6-fg"                 . nil)
-   ("ol6-bg"                 . nil)
-   ("ol7-fg"                 . nil)
-   ("ol7-bg"                 . nil)
-   ("ol8-fg"                 . nil)
-   ("ol8-bg"                 . nil)
+   ("ol6-fg"                 . unspecified)
+   ("ol6-bg"                 . unspecified)
+   ("ol7-fg"                 . unspecified)
+   ("ol7-bg"                 . unspecified)
+   ("ol8-fg"                 . unspecified)
+   ("ol8-bg"                 . unspecified)
    ;; Misc
    ("colored-comments"       . "#ccffcc")
    ("transient-highlight"    . "#ffff00")
blob - a4b723b7e5452706c6e66eb214c0959f3ead049c
blob + 0b1667b3b77ed8fd984d51587e6a88ae4ca26dee
--- themes/eziam/eziam-dusk-theme.el
+++ themes/eziam/eziam-dusk-theme.el
@@ -50,22 +50,22 @@
    ("color-7"                . "#FFFFFF")
    ("color-8"                . "#ffffff")
    ;; Headings
-   ("ol1-fg"                 . nil)
+   ("ol1-fg"                 . unspecified)
    ("ol1-bg"                 . "#000000")
-   ("ol2-fg"                 . nil)
+   ("ol2-fg"                 . unspecified)
    ("ol2-bg"                 . "#063545")
-   ("ol3-fg"                 . nil)
+   ("ol3-fg"                 . unspecified)
    ("ol3-bg"                 . "#186b8c")
    ("ol4-fg"                 . "#222222")
    ("ol4-bg"                 . "#1e85ae")
    ("ol5-fg"                 . "#222222")
    ("ol5-bg"                 . "#96a4ab")
-   ("ol6-fg"                 . nil)
-   ("ol6-bg"                 . nil)
-   ("ol7-fg"                 . nil)
-   ("ol7-bg"                 . nil)
-   ("ol8-fg"                 . nil)
-   ("ol8-bg"                 . nil)
+   ("ol6-fg"                 . unspecified)
+   ("ol6-bg"                 . unspecified)
+   ("ol7-fg"                 . unspecified)
+   ("ol7-bg"                 . unspecified)
+   ("ol8-fg"                 . unspecified)
+   ("ol8-bg"                 . unspecified)
    ;; Misc
    ("colored-comments"       . "#ccffcc")
    ("transient-highlight"    . "yellow")
blob - eee587a2bdc47e7e6532d87266b69b9983a4718d
blob + cb6e9383d1725d8e0a55a2a4c5c5e40067c4275e
--- themes/eziam/eziam-light-theme.el
+++ themes/eziam/eziam-light-theme.el
@@ -50,22 +50,22 @@
    ("color-7"                . "#222222")
    ("color-8"                . "#000000")
    ;; Headings
-   ("ol1-fg"                 . nil)
+   ("ol1-fg"                 . unspecified)
    ("ol1-bg"                 . "#ffffff")
-   ("ol2-fg"                 . nil)
+   ("ol2-fg"                 . unspecified)
    ("ol2-bg"                 . "#d6eaf4")
-   ("ol3-fg"                 . nil)
+   ("ol3-fg"                 . unspecified)
    ("ol3-bg"                 . "#c1d3dc")
-   ("ol4-fg"                 . nil)
+   ("ol4-fg"                 . unspecified)
    ("ol4-bg"                 . "#abbbc3")
    ("ol5-fg"                 . "#eeeeee")
    ("ol5-bg"                 . "#96a4ab")
-   ("ol6-fg"                 . nil)
+   ("ol6-fg"                 . unspecified)
    ("ol6-bg"                 . "#d7d7d7")
-   ("ol7-fg"                 . nil)
-   ("ol7-bg"                 . nil)
-   ("ol8-fg"                 . nil)
-   ("ol8-bg"                 . nil)
+   ("ol7-fg"                 . unspecified)
+   ("ol7-bg"                 . unspecified)
+   ("ol8-fg"                 . unspecified)
+   ("ol8-bg"                 . unspecified)
    ;; Misc
    ("colored-comments"       . "#117711")
    ("transient-highlight"    . "#ffff00")
blob - 4057140a5e711062efbd4ede1333ebbca64cec88
blob + 2652a69526d1b9962c7ca473dd3a54ac0ca4819c
--- themes/eziam/eziam-themes.el
+++ themes/eziam/eziam-themes.el
@@ -111,7 +111,10 @@ Also bind `class' to ((class color) (min-colors 89))."
   (declare (indent 0))
   `(let ((class '((class color) (min-colors 89)))
          ,@(mapcar (lambda (c)
-                     (list (intern (car c)) (cdr c)))
+                     (list (intern (car c))
+                         (if (symbolp (cdr c))
+                             (list 'quote (cdr c))
+                           (cdr c))))
                    eziam-colors))
      ,@body))
 
@@ -284,7 +287,7 @@ this macro inside that macro."
      `(ack-match                                        ((t (:foreground ,color-8 :background ,color-1 :weight bold))))
 ;;;;; auctex
      `(font-latex-bold-face                             ((t (:inherit bold))))
-     `(font-latex-warning-face                          ((t (:foreground nil :inherit font-lock-warning-face))))
+     `(font-latex-warning-face                          ((t (:foreground unspecified :inherit font-lock-warning-face))))
      `(font-latex-sectioning-5-face                     ((t (:foreground ,color-7 :weight bold ))))
      `(font-latex-sedate-face                           ((t (:foreground ,color-8))))
      `(font-latex-italic-face                           ((t (:foreground ,color-8 :slant italic))))
@@ -330,15 +333,15 @@ this macro inside that macro."
      `(clojure-test-error-face                          ((t (:foreground ,color-7 :weight bold :underline t))))
      `(clojure-test-success-face                        ((t (:foreground ,color-7 :weight bold :underline t))))
 ;;;;; coq
-     `(coq-solve-tactics-face                           ((t (:foreground nil :inherit font-lock-constant-face))))
+     `(coq-solve-tactics-face                           ((t (:foreground unspecified :inherit font-lock-constant-face))))
 ;;;;; ctable
      `(ctbl:face-cell-select                            ((t (:background ,color-8 :foreground ,color-2))))
      `(ctbl:face-continue-bar                           ((t (:background ,color-1 :foreground ,color-2))))
      `(ctbl:face-row-select                             ((t (:background ,color-8 :foreground ,color-2))))
 ;;;;; diff
-     `(diff-added                                       ((,class (:foreground ,color-8 :background nil)) (t (:foreground ,color-5 :background nil))))
+     `(diff-added                                       ((,class (:foreground ,color-8 :background unspecified)) (t (:foreground ,color-5 :background unspecified))))
      `(diff-changed                                     ((t (:foreground ,color-8))))
-     `(diff-removed                                     ((,class (:foreground ,color-7 :background nil)) (t (:foreground ,color-5 :background nil))))
+     `(diff-removed                                     ((,class (:foreground ,color-7 :background unspecified)) (t (:foreground ,color-5 :background unspecified))))
      `(diff-refine-added                                ((t :inherit diff-added :weight bold)))
      `(diff-refine-change                               ((t :inherit diff-changed :weight bold)))
      `(diff-refine-removed                              ((t :inherit diff-removed :weight bold)))
@@ -529,8 +532,8 @@ this macro inside that macro."
      `(helm-time-zone-current                           ((t (:foreground ,color-8 :background ,color-1))))
      `(helm-time-zone-home                              ((t (:foreground ,color-7 :background ,color-1))))
      `(helm-bookmark-addressbook                        ((t (:foreground ,color-8 :background ,color-1))))
-     `(helm-bookmark-directory                          ((t (:foreground nil :background nil :inherit helm-ff-directory))))
-     `(helm-bookmark-file                               ((t (:foreground nil :background nil :inherit helm-ff-file))))
+     `(helm-bookmark-directory                          ((t (:foreground unspecified :background unspecified :inherit helm-ff-directory))))
+     `(helm-bookmark-file                               ((t (:foreground unspecified :background unspecified :inherit helm-ff-file))))
      `(helm-bookmark-gnus                               ((t (:foreground ,color-7 :background ,color-1))))
      `(helm-bookmark-info                               ((t (:foreground ,color-8 :background ,color-1))))
      `(helm-bookmark-man                                ((t (:foreground ,color-8 :background ,color-1))))
@@ -715,7 +718,7 @@ this macro inside that macro."
      `(mu4e-ok-face                                     ((t (:foreground ,ok :weight bold))))
      `(mu4e-warning-face                                ((t (:foreground ,warning :weight bold))))
 ;;;;; mumamo
-     `(mumamo-background-chunk-major                    ((t (:background nil))))
+     `(mumamo-background-chunk-major                    ((t (:background unspecified))))
      `(mumamo-background-chunk-submode1                 ((t (:background ,color-1))))
      `(mumamo-background-chunk-submode2                 ((t (:background ,color-4))))
      `(mumamo-background-chunk-submode3                 ((t (:background ,color-5))))
@@ -814,7 +817,7 @@ this macro inside that macro."
      `(proof-boring-face                                ((t (:foreground ,color-8 :background ,color-4))))
      `(proof-command-mouse-highlight-face               ((t (:inherit proof-mouse-highlight-face))))
      `(proof-debug-message-face                         ((t (:inherit proof-boring-face))))
-     `(proof-declaration-name-face                      ((t (:inherit font-lock-keyword-face :foreground nil))))
+     `(proof-declaration-name-face                      ((t (:inherit font-lock-keyword-face :foreground unspecified))))
      `(proof-eager-annotation-face                      ((t (:foreground ,color-2 :background ,color-8))))
      `(proof-error-face                                 ((t (:foreground ,color-8 :background ,color-4))))
      `(proof-highlight-dependency-face                  ((t (:foreground ,color-2 :background ,color-8))))
@@ -824,8 +827,8 @@ this macro inside that macro."
      `(proof-queue-face                                 ((t (:background ,color-4))))
      `(proof-region-mouse-highlight-face                ((t (:inherit proof-mouse-highlight-face))))
      `(proof-script-highlight-error-face                ((t (:background ,color-6))))
-     `(proof-tacticals-name-face                        ((t (:inherit font-lock-constant-face :foreground nil :background ,color-1))))
-     `(proof-tactics-name-face                          ((t (:inherit font-lock-constant-face :foreground nil :background ,color-1))))
+     `(proof-tacticals-name-face                        ((t (:inherit font-lock-constant-face :foreground unspecified :background ,color-1))))
+     `(proof-tactics-name-face                          ((t (:inherit font-lock-constant-face :foreground unspecified :background ,color-1))))
      `(proof-warning-face                               ((t (:foreground ,color-2 :background ,color-8))))
 ;;;;; rainbow-delimiters
      `(rainbow-delimiters-depth-1-face                  ((t (:foreground ,rainbow-1 :bold t))))