1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
|
;;; init.el -*- lexical-binding: t; -*-
;;;
;;; Author: Jakob L. Kreuze <zerodaysfordays@sdf.org>
;;; URL: https://git.sr.ht/~jakob/.emacs.d/
;;;
;;; What follows is my personal configuration for GNU Emacs. Alas, what once was
;;; a literate configuration has turned into a modularized set of Elisp files. I
;;; have a number of reasons for this.
;;;
;;; - There was a considerable amount of friction in changing my configuration.
;;; There are a few things that could remedy this, namely the suggestion of
;;; using poly-org as suggested in [1], but my biggest grievance is putting
;;; documentation between snippets of code. There were a couple of answers to
;;; the Emacs StackExchange question I asked on this [2], but the only
;;; suggestion that remotely close to what I was looking for was to use
;;; <<noweb>> syntax. Too much overhead for my tastes; I have to make a new
;;; named block every time I want to document part of a package configuration?
;;; Color me unexcited. Configuration reloading was also a massive pain, as
;;; some s-exps were split across blocks and I couldn't evaluate them with
;;; C-M-x.
;;;
;;; - My current method for tangling doesn't support byte compilation. The byte
;;; compiler will emit warnings for problematic Elisp. I can lint an Elisp
;;; file. With the way I was tangling, any errors in my code would be a
;;; pleasant surprise for the next time I tried to start Emacs. Furthermore,
;;; if I want to reap the benefits of using GCCEmacs [3], I'd better be
;;; compiling my sources. This is another grievance that could have been
;;; remedied with literate-elisp as suggested in [1], but I've decided it's
;;; too much work. I like the idea of being able to byte-compile with the
;;; native Emacs machinery better.
;;;
;;; - It's difficult to split up a literate configuration into multiple files,
;;; which is something I'd like to do for reasons of loading efficiency and
;;; organization. I think there's a reason that other sufficiently built-up
;;; configurations of note, such as Doom [4] and Purcell's [5], are written in
;;; plain ol' Elisp, leaving documentation to another file if stuctured text
;;; is really necessary.
;;;
;;; And, really, links were the only the only rich text I was using in the Org
;;; version. If I can survive writing emails without Org-style links, I can
;;; survive writing Elisp without Org-style links. I still love Org, but for
;;; right now, I'm not going to adopt it for anything outside of my personal
;;; information management workflow. Two conversations that influenced this
;;; decision and are worth documenting are [6] and [7].
;;;
;;; Also worth noting is that there is no namespace (i.e. =jakob/= or =my-=) for
;;; functions defined in this file. I'm happy to use a consistent namespacing
;;; for packages I plan to publish on Melpa, but I don't see the point in a
;;; configuration file.
;;;
;;; [1]: https://www.reddit.com/r/emacs/comments/gfiadj/thoughts_on_having_a_literate_config/fpxqmf8/
;;; [2]: https://emacs.stackexchange.com/questions/57608/split-code-across-multiple-src-blocks
;;; [3]: http://akrl.sdf.org/gccemacs.html
;;; [4]: https://github.com/hlissner/doom-emacs
;;; [5]: https://github.com/purcell/emacs.d
;;; [6]: https://www.reddit.com/r/emacs/comments/gfiadj/thoughts_on_having_a_literate_config/
;;; [7]: https://www.colinmclear.net/posts/emacs-configuration/
;; There are a few packages I have installed which do not play nicely with
;; native compilation (looking at you org-plus-contrib). Disabling deferred
;; compilation gives me some more control.
(setq native-comp-deferred-compilation nil)
(setq native-comp-async-report-warnings-errors nil)
(setq native-comp-deferred-compilation-deny-list '("/usr/share/emacs/28.0.50/lisp"))
;; The traditional dance of calming down the garbage collector during init,
;; as that improves startup times. Taken from Doom Emacs [1].
;;
;; [1]: https://github.com/hlissner/doom-emacs/blob/develop/docs/faq.org#how-does-doom-start-up-so-quickly
(setq gc-cons-threshold most-positive-fixnum)
(setq gc-cons-percentage 0.6)
;; Fill whatever space the window manager has given us.
(setq frame-resize-pixelwise t)
;; straight.el is my package manager of choice. Here's the necessary bootstrap
;; code for that.
(defvar bootstrap-version)
(let ((bootstrap-file
(expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
(bootstrap-version 5))
(unless (file-exists-p bootstrap-file)
(with-current-buffer
(url-retrieve-synchronously
"https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
'silent 'inhibit-cookies)
(goto-char (point-max))
(eval-print-last-sexp)))
(load bootstrap-file nil 'nomessage))
;; As for ensuring that the packages listed in this configuration are installed,
;; I prefer use-package. `straight-use-package-by-default' ensures that packages
;; are registered and built without reqiring an explicit `:straight t'.
(straight-use-package 'use-package)
(setq straight-use-package-by-default t)
;; `bind-key' is necessary for `:bind' in `use-package' declarations, and I
;; actually use it quite a bit in this configuration.
(use-package bind-key)
(require 'bind-key)
;; But we do want to reset the garbage collector settings eventually. When we
;; do, we'll use the GCMH [1] package to schedule the garbage collector to run
;; during idle time, rather than the haphazard "whenever some threshold is
;; reached".
;;
;; [1]: https://gitlab.com/koral/gcmh/
(use-package gcmh :defer t)
(add-hook 'emacs-startup-hook
(lambda ()
(setq gc-cons-threshold 16777216) ; 16mb
(setq gc-cons-percentage 0.1)
(require 'gcmh)
(gcmh-mode 1)))
;; A handful of the Elisp snippets in this file depend on third-party libraries
;; which aren't loaded by default.
;;; TODO
;;; Everything above is what I classify as the "early-load" part of my
;;; configuration. The rest of my configuration is broken into "modules", which
;;; I include into the init.el at macro expansion time.
(defvar module-directory (expand-file-name "lisp" user-emacs-directory)
"Directory containing configuration 'modules'.")
(defmacro insert-code-from-file (path)
"Read the forms in the file at PATH into a progn."
(with-temp-buffer
(insert-file-contents path)
(goto-char (point-min))
(let (forms (eof nil))
(while (not eof)
(condition-case nil
(push (read (current-buffer)) forms)
(end-of-file (setq eof t))))
`(progn ,@(reverse forms)))))
(defmacro load-module (name)
"Locate the module NAME and insert its contents as a progn."
(let* ((file-name (concat name ".el"))
(path (expand-file-name file-name module-directory)))
`(insert-code-from-file ,path)))
(defmacro expand-when (conditional &rest form)
"Expand if and only if `CONDITIONAL' is truthy at compile-time."
(if (eval conditional)
`(progn ,@form)
'(progn)))
(require 'cl-lib)
(defmacro choose-for-machine (&rest clauses)
"Return the `cadr' of the CLAUSE whose `car' is `(system-name)'."
(let* ((name-clause (cl-find-if #'(lambda (x)
(string= (system-name) (car x)))
clauses))
(last-clause (cl-find-if #'(lambda (x) (eq 't (car x)))
clauses)))
(cond (name-clause (cadr name-clause))
(last-clause (cadr last-clause))
(t 'nil))))
(load-module "core")
(load-module "jakob")
(load-module "appearance")
(load-module "appearance/theme")
(load-module "appearance/modeline")
(load-module "quality-of-life")
(load-module "shell")
(load-module "terminal")
(load-module "system")
(load-module "documents")
(load-module "irc")
(load-module "news")
(load-module "programming")
(load-module "programming/rust")
(load-module "programming/c")
(load-module "programming/c++")
(load-module "programming/elisp")
(load-module "programming/common-lisp")
(load-module "programming/markup")
(load-module "programming/scheme")
(load-module "programming/janet")
(load-module "programming/javascript")
(load-module "programming/graphql")
(load-module "programming/python")
(load-module "programming/lua")
(load-module "programming/haskell")
|