summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--early-init.el75
-rw-r--r--init.el687
-rw-r--r--lisp/acdw.el193
4 files changed, 381 insertions, 577 deletions
diff --git a/.gitignore b/.gitignore index e2bdc81..8de33a1 100644 --- a/.gitignore +++ b/.gitignore
@@ -6,4 +6,5 @@ var/
6etc/ 6etc/
7straight/ 7straight/
8transient/ 8transient/
9racket-mode/ \ No newline at end of file 9racket-mode/
10*~ \ No newline at end of file
diff --git a/early-init.el b/early-init.el index fac0705..b8f652e 100644 --- a/early-init.el +++ b/early-init.el
@@ -24,37 +24,21 @@
24 load-path) 24 load-path)
25(require 'acdw) 25(require 'acdw)
26 26
27;;; Refresh Emacs easily 27
28(defun refresh-emacs ()
29 "Reload Emacs's configuration files."
30 (interactive)
31 (dolist (file (list (locate-user-emacs-file "early-init.el")
32 (locate-user-emacs-file "init.el" ".emacs")))
33 (when (file-exists-p file)
34 (load-file file))))
35
36;;; Speed up init 28;;; Speed up init
37;; see doom-emacs, et al. 29;; see doom-emacs, et al.
38 30
39(defvar orig-file-name-handler-alist file-name-handler-alist 31(setq orig-file-name-handler-alist file-name-handler-alist
40 "The original value of `file-name-handler-alist' will be restored 32 file-name-handler-alist nil)
41 after init.") 33(acdw/gc-disable)
42
43(setq file-name-handler-alist nil)
44(setq gc-cons-threshold (* 800 1024 1024)
45 gc-cons-percentage 0.6)
46
47(add-hook 'after-init-hook
48 (defun hook--post-init-reset ()
49 "Reset `gc-cons-threshold', `gc-cons-percentage', and
50 `file-name-handler-alist' to their defaults after init."
51 (acdw/gc-enable)
52 (dolist (handler file-name-handler-alist)
53 (add-to-list 'orig-file-name-handler-alist handler))
54 (setq file-name-handler-alist orig-file-name-handler-alist)))
55 34
35(hook-defun post-init-reset after-init-hook
36 (acdw/gc-enable)
37 (dolist (handler file-name-handler-alist)
38 (add-to-list 'orig-file-name-handler-alist handler))
39 (setq file-name-handler-alist orig-file-name-handler-alist))
40
56;;; Frame settings 41;;; Frame settings
57
58(setq default-frame-alist ; Remove most UI 42(setq default-frame-alist ; Remove most UI
59 `((tool-bar-lines . 0) ; No tool bar 43 `((tool-bar-lines . 0) ; No tool bar
60 (menu-bar-lines . 0) ; No menu bar 44 (menu-bar-lines . 0) ; No menu bar
@@ -73,8 +57,7 @@
73 frame-resize-pixelwise t ; Resize by pixels, not chars 57 frame-resize-pixelwise t ; Resize by pixels, not chars
74 ) 58 )
75 59
76(defun hook--disable-ui-modes () 60(hook-defun disable-ui-modes after-init-hook
77 "Disable frame UI using modes, for toggling later."
78 (dolist (mode ;; each mode is of the form (MODE . FRAME-ALIST-VAR) 61 (dolist (mode ;; each mode is of the form (MODE . FRAME-ALIST-VAR)
79 '((tool-bar-mode . tool-bar-lines) 62 '((tool-bar-mode . tool-bar-lines)
80 (menu-bar-mode . menu-bar-lines) 63 (menu-bar-mode . menu-bar-lines)
@@ -86,8 +69,25 @@
86 (= 0 setting)) 69 (= 0 setting))
87 (funcall (car mode) -1))))) 70 (funcall (car mode) -1)))))
88 71
89(add-hook 'after-init-hook #'hook--disable-ui-modes) 72(add-function :after after-focus-change-function
90 73 (defun hook--setup-fonts ()
74 (dolist (face '(default fixed-pitch))
75 ;; `default' and `fixed-pitch' should be the same.
76 (set-face-attribute face nil
77 :font (pcase acdw/system
78 (:home "DejaVu Sans Mono-10")
79 (:work "Consolas-10")
80 (:other "monospace-10"))))
81 ;; `variable-pitch' is, of course, different.
82 (set-face-attribute 'variable-pitch nil
83 :font (pcase acdw/system
84 (:home "DejaVu Sans")
85 (:work "Calibri-11")
86 (:other "sans-serif")))
87 (remove-function after-focus-change-function
88 'hook--setup-fonts)))
89
90
91;;; Bootstrap package manager (`straight.el') 91;;; Bootstrap package manager (`straight.el')
92 92
93;; 1. Update `exec-path'. 93;; 1. Update `exec-path'.
@@ -108,7 +108,7 @@
108 package-quickstart nil 108 package-quickstart nil
109 straight-host-usernames '((github . "duckwork") 109 straight-host-usernames '((github . "duckwork")
110 (gitlab . "acdw")) 110 (gitlab . "acdw"))
111 straight-base-dir acdw/dir) 111 straight-base-dir (acdw/dir))
112 112
113;; 3. Bootstrap `straight'. 113;; 3. Bootstrap `straight'.
114(defvar bootstrap-version) 114(defvar bootstrap-version)
@@ -126,9 +126,10 @@
126 (goto-char (point-max)) 126 (goto-char (point-max))
127 (eval-print-last-sexp))) 127 (eval-print-last-sexp)))
128 (load bootstrap-file nil 'nomessage)) 128 (load bootstrap-file nil 'nomessage))
129 129
130;;; Message startup time for profiling 130;;; Message startup time for profiling
131 131;; This just redefines the Emacs function
132;; `display-startup-echo-area-message', so no hooks needed.
132(defun display-startup-echo-area-message () 133(defun display-startup-echo-area-message ()
133 "Show Emacs's startup time in the message buffer. For profiling." 134 "Show Emacs's startup time in the message buffer. For profiling."
134 (message "Emacs ready in %s with %d garbage collections." 135 (message "Emacs ready in %s with %d garbage collections."
@@ -136,11 +137,3 @@
136 (float-time (time-subtract after-init-time 137 (float-time (time-subtract after-init-time
137 before-init-time))) 138 before-init-time)))
138 gcs-done)) 139 gcs-done))
139
140;;; Install `no-littering', pointing both directories at `acdw/dir'. This will
141;;; take care of the packages I don't care about configuring.
142
143(straight-use-package 'no-littering)
144(setq no-littering-etc-directory acdw/dir
145 no-littering-var-directory acdw/dir)
146(require 'no-littering)
diff --git a/init.el b/init.el index 09a4fe8..19c0f9a 100644 --- a/init.el +++ b/init.el
@@ -15,23 +15,19 @@
15;; - Make good choices. 15;; - Make good choices.
16 16
17;;;- Code: 17;;;- Code:
18
19;; Necessary packages
18 20
19;;; `setup' -- configuration macro 21;; `setup'
20(straight-use-package '(setup :host nil 22(progn
21 :repo "https://git.sr.ht/~zge/setup")) 23 (straight-use-package '(setup :host nil
22(require 'setup) 24 :repo "https://git.sr.ht/~zge/setup"))
23 25 (require 'setup))
24;;;; shorthand for `customize-set-variable' (via setup)
25(defmacro setc (&rest args)
26 "Customize user options using ARGS like `setq'."
27 (declare (debug setq))
28 `(setup (:option ,@args)))
29 26
30;;;; Install packages with `straight-use-package'
31(setup-define :straight 27(setup-define :straight
32 (lambda (recipe) 28 (lambda (recipe)
33 `(straight-use-package ',recipe)) 29 `(straight-use-package ',recipe))
34 :documentation "Install RECIPE with `straight-use-package'." 30 :documenation "Install RECIPE with `straight-use-package'."
35 :repeatable t 31 :repeatable t
36 :shorthand (lambda (sexp) 32 :shorthand (lambda (sexp)
37 (let ((recipe (cadr sexp))) 33 (let ((recipe (cadr sexp)))
@@ -39,173 +35,243 @@
39 (car recipe) 35 (car recipe)
40 recipe)))) 36 recipe))))
41 37
42;;;; Set options using `setq-default', instead of `customize-set-variable' 38(setup-define :leader
43;; From what I can tell, `customize-set-variable' loads "all the dependencies
44;; for each SYMBOL it sets (see `custom-load-symbol'). Since I don't want to do
45;; that all the time, here's `:set'. DON'T USE THIS HARDLY EVER. Honestly, I
46;; might want to do a `:option-after' instead (with `:after-loaded' set to t)...
47(setup-define :setq-default
48 (lambda (variable value)
49 `(setq-default ,variable ,value))
50 :documentation "Set options with `setq-default'. USE SPARINGLY!"
51 :debug '(sexp form)
52 :repeatable t)
53
54
55;;;; Bind keys to `acdw/leader'
56(setup-define :acdw/leader
57 (lambda (key command) 39 (lambda (key command)
58 `(progn 40 `(progn
59 (autoload #',command (symbol-name setup-name)) 41 (autoload #',command (symbol-name setup-name))
60 (define-key acdw/leader 42 (define-key acdw/leader
61 ,(if (stringp key) (kbd key) key) 43 ,(if (stringp key) (kbd key) key)
62 #',command))) 44 #',command))))
63 :documentation "Bind KEY to COMMAND in `acdw/leader' map."
64 :debug '(form sexp)
65 :repeatable t)
66 45
67;;;; Bind keys, and autoload the functions they're bound to. 46;; `no-littering'
68(setup-define :bind-autoload 47(setup (:straight no-littering)
69 (lambda (key command) 48 (:option no-littering-etc-directory (acdw/dir)
70 `(progn 49 no-littering-var-directory (acdw/dir))
71 (autoload #',command (symbol-name setup-name)) 50 (require 'no-littering))
72 (define-key (symbol-value setup-map)
73 ,(if (stringp key) (kbd key) key)
74 #',command)))
75 :documentation "Bind KEY to COMMAND, and autload COMMAND from FEATURE."
76 :debug '(form sexp)
77 :repeatable t)
78 51
79 52
80;;; Good defaults 53;; Good defaults
81 54
82;;;; About me 55(defmacro setc (&rest args)
83(setc user-full-name "Case Duckworth" 56 "Customize user options using ARGS like `setq'."
84 user-mail-address "acdw@acdw.net" 57 (declare (debug setq))
85 calendar-location-name "Baton Rouge, LA" 58 `(setup (:option ,@args)))
86 calendar-latitude 30.4 59
87 calendar-longitude -91.1) 60(setup emacs
88 61 ;; Me
89;;;; Lines 62 (:option user-full-name "Case Duckworth"
90(setc fill-column 80 63 user-mail-address "acdw@acdw.net"
91 word-wrap t 64 calendar-location-name "Baton Rouge, LA"
92 truncate-lines nil) 65 calendar-latitude 30.4
93(add-hook 'text-mode-hook #'turn-on-auto-fill) 66 calendar-longitude -91.1)
94(global-display-fill-column-indicator-mode +1) 67
95(global-so-long-mode +1) 68 ;; Lines
96 69 (:option fill-column 80
97;; Only fill comments in prog-mode. 70 word-wrap t
98(add-hook 'prog-mode-hook 71 truncate-lines nil)
99 (defun hook--auto-fill-prog-mode () 72
100 (setq-local comment-auto-fill-only-comments t) 73 (global-display-fill-column-indicator-mode +1)
101 (turn-on-auto-fill))) 74 (global-so-long-mode +1)
102 75
103;; Don't truncate lines in the minibuffer. 76 ;; Whitespace
104(add-hook 'minibuffer-setup-hook 77 (:option whitespace-style
105 (defun hook--minibuffer-enable-truncate-lines () 78 '(empty indentation space-before-tab space-after-tab)
106 (setq-local truncate-lines t))) 79 indent-tabs-mode nil
107 80 tab-width 4)
108;;;; Whitespace 81
109(setc whitespace-style 82 (add-hook 'before-save-hook #'whitespace-cleanup)
110 '(empty indentation space-before-tab space-after-tab) 83
111 indent-tabs-mode nil 84 ;; Killing and yanking
112 tab-width 4 85 (:option save-interprogram-paste-before-kill t
113 smie-indent-basic tab-width) 86 yank-pop-change-selection t
114(add-hook 'before-save-hook #'whitespace-cleanup) 87 x-select-enable-clipboard t
115 88 x-select-enable-primary t
116;;;; Pairs 89 mouse-drag-copy-region t
117(setc show-paren-delay 0 90 kill-do-not-save-duplicates t)
118 show-paren-style 'mixed 91
119 show-paren-when-point-inside-paren t 92 (delete-selection-mode +1)
120 show-paren-when-point-in-periphery t) 93
121(add-hook 'prog-mode-hook #'electric-pair-local-mode) 94 ;; Encoding
122 95 (:option local-coding-system 'utf-8-unix
123;;;; Killing and yanking 96 coding-system-for-read 'utf-8-unix
124(setc save-interprogram-paste-before-kill t 97 coding-system-for-write 'utf-8-unix
125 yank-pop-change-selection t 98 buffer-file-coding-system 'utf-8-unix
126 x-select-enable-clipboard t 99 org-export-coding-system 'utf-8-unix
127 x-select-enable-primary t 100 org-html-coding-system 'utf-8-unix
128 mouse-drag-copy-region t 101 default-process-coding-system '(utf-8-unix . utf-8-unix)
129 kill-do-not-save-duplicates t) 102 x-select-request-type '(UTF8_STRING
130(delete-selection-mode +1) 103 COMPOUND_TEXT
131 104 TEXT
132;;;; Encoding 105 STRING))
133(setc local-coding-system 'utf-8-unix 106
134 coding-system-for-read 'utf-8-unix 107 (set-charset-priority 'unicode)
135 coding-system-for-write 'utf-8-unix 108 (set-language-environment "UTF-8")
136 buffer-file-coding-system 'utf-8-unix 109 (prefer-coding-system 'utf-8-unix)
137 org-export-coding-system 'utf-8-unix 110 (set-default-coding-systems 'utf-8-unix)
138 org-html-coding-system 'utf-8-unix 111 (set-terminal-coding-system 'utf-8-unix)
139 default-process-coding-system '(utf-8-unix . utf-8-unix) 112 (set-keyboard-coding-system 'utf-8-unix)
140 x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING)) 113 (set-selection-coding-system 'utf-8-unix)
141(set-charset-priority 'unicode) 114
142(set-language-environment "UTF-8") 115 ;; Cursor
143(prefer-coding-system 'utf-8-unix) 116 (:option cursor-type 'bar
144(set-default-coding-systems 'utf-8-unix) 117 cursor-in-non-selected-windows 'hollow)
145(set-terminal-coding-system 'utf-8-unix) 118
146(set-keyboard-coding-system 'utf-8-unix) 119 ;; Scrolling
147(set-selection-coding-system 'utf-8-unix) 120 (:option auto-window-vscroll nil
148 121 fast-but-imprecise-scrolling t
149;;;; Uniquify 122 scroll-margin 0
150(setup (:require uniquify) 123 scroll-conservatively 101
124 scroll-preserve-screen-position 1)
125
126 ;; Minibuffer
127 (:option minibuffer-prompt-properties
128 '(read-only t cursor-intangible t face minibuffer-prompt)
129 enable-recursive-minibuffers t
130 file-name-shadow-properties '(invisible t intangible t)
131 read-answer-short t)
132
133 (add-hook 'minibuffer-setup-hook #'acdw/gc-disable)
134 (add-hook 'minibuffer-exit-hook #'acdw/gc-enable)
135
136 (hook-defun minibuffer-enable-truncate-lines minibuffer-setup-hook
137 (setq-local truncate-lines t))
138
139 (minibuffer-depth-indicate-mode +1)
140 (file-name-shadow-mode +1)
141 (fset 'yes-or-no-p #'y-or-n-p)
142
143 ;; Completion
144 (:option completion-ignore-case t
145 read-buffer-completion-ignore-case t
146 icomplete-delay-completions-threshold 0
147 icomplete-max-delay-chars 0
148 icomplete-compute-delay 0
149 icomplete-show-matches-on-no-input t
150 icomplete-with-buffer-completion-tables t
151 icomplete-in-buffer t
152 completion-styles '(partial-completion substring flex)
153 completion-category-defaults nil
154 completion-category-overrides
155 '((file (styles . (partial-completion)))))
156
157 ;; Etc.
158 (:option custom-file (acdw/dir "custom.el")
159 inhibit-startup-screen t
160 initial-buffer-choice t
161 initial-scratch-message (concat ";; Howdy, "
162 (nth 0 (split-string
163 user-full-name))
164 "! "
165 "Welcome to GNU Emacs.\n\n")
166 disabled-command-function nil
167 load-prefer-newer t
168 comp-async-report-warnings-errors nil
169 frame-title-format '("%b %+%* GNU Emacs"
170 (:eval (when (frame-parameter
171 nil 'client)
172 " Client")))
173 tab-bar-show 1
174 use-dialog-box nil
175 use-file-dialog nil
176 echo-keystrokes 0.25
177 recenter-positions '(top middle bottom)
178 attempt-stack-overflow-recovery nil
179 attempt-orderly-shutdown-on-fatal-signal nil
180 window-resize-pixelwise t
181 find-function-C-source-directory
182 (pcase acdw/system
183 (:work (expand-file-name (concat "~/src/emacs-"
184 emacs-version
185 "/src")))
186 (:home (expand-file-name
187 "~/src/pkg/emacs/src/emacs-git/src"))
188 (:other nil))
189 w32-allow-system-shell t
190 w32-pass-lwindow-to-system nil
191 w32-lwindow-modifier 'super
192 w32-pass-rwindow-to-system nil
193 w32-rwindow-modifier 'super
194 w32-pass-apps-to-system nil
195 w32-apps-modifier 'hyper)
196
197 (when-unfocused garbage-collect
198 (garbage-collect))
199
200 (tooltip-mode -1)
201 (winner-mode +1)
202
203 ;; Bindings
204 (:global "M-SPC" cycle-spacing
205 "M-/" hippie-expand
206 "M-=" count-words
207 "C-x C-b" ibuffer))
208
209;; Regular modes (`text-mode', `prog-mode', etc.)
210(defun acdw/setup-regular-modes ()
211 (setq-local indicate-empty-lines t
212 indicate-buffer-boundaries '((top . right)
213 (bottom . right))))
214
215(setup text
216 (:hook turn-on-auto-fill
217 acdw/setup-regular-modes))
218
219(setup prog
220 (:option smie-indent-basic tab-width)
221
222 (hook-defun auto-fill-prog-mode prog-mode-hook
223 (setq-local comment-auto-fill-only-comments t)
224 (turn-on-auto-fill))
225
226 (:option show-paren-delay 0
227 show-paren-style 'mixed
228 show-paren-when-point-inside-paren t
229 show-paren-when-point-in-periphery t)
230
231 (:hook show-paren-mode
232 electric-pair-local-mode
233 acdw/setup-regular-modes)
234
235 (add-hook 'after-save-hook
236 #'executable-make-buffer-file-executable-if-script-p))
237
238(setup uniquify
151 (:option uniquify-buffer-name-style 'forward 239 (:option uniquify-buffer-name-style 'forward
152 uniquify-separator path-separator 240 uniquify-separator path-separator
153 uniquify-after-kill-buffer-p t 241 uniquify-after-kill-buffer-p t
154 uniquify-ignore-buffers-re "^\\*")) 242 uniquify-ignore-buffers-re "^\\*"))
155 243
156;;;; Files 244(setup files
157(setc backup-directory-alist `((".*" . ,(acdw/in-dir "backup/" t))) 245 (:option backup-directory-alist `((".*" . ,(acdw/dir "backup/" t)))
158 tramp-backup-directory-alist backup-directory-alist 246 tramp-backup-directory-alist backup-directory-alist
159 auto-save-file-name-transforms `((".*" ,(acdw/in-dir "auto-save/" t) t)) 247 auto-save-file-name-transforms `((".*" ,(acdw/dir "auto-save/" t) t))
160 auto-save-list-file-prefix (acdw/in-dir "auto-save-list/.saves-" t) 248 auto-save-list-file-prefix (acdw/dir "auto-save-list/.saves-" t)
161 backup-by-copying t 249 backup-by-copying t
162 delete-old-versions t 250 delete-old-versions t
163 version-control t 251 version-control t
164 vc-make-backup-files t) 252 vc-make-backup-files t)
165 253
166(add-hook 'after-save-hook #'executable-make-buffer-file-executable-if-script-p) 254 (auto-save-visited-mode +1)
167 255
168;;;;; Auto-save files 256 (when-unfocused save-some-buffers
169(auto-save-visited-mode +1) 257 (save-some-buffers t)))
170;; And /actually/ save all buffers when unfocused 258
171(add-function :after after-focus-change-function 259(setup autorevert
172 (defun hook--auto-save-when-unfocused ()
173 "Save all buffers when out of focus."
174 (acdw/when-unfocused #'save-some-buffers t)))
175
176;;;;; Autorevert files
177(setup (:require autorevert)
178 (global-auto-revert-mode +1)) 260 (global-auto-revert-mode +1))
179 261
180;;;;; Save place in files 262(setup saveplace
181(setup (:require saveplace) 263 (:option save-place-file (acdw/dir "places.el")
182 (:option save-place-file (acdw/in-dir "places.el")
183 save-place-forget-unreadable-files (eq acdw/system :home)) 264 save-place-forget-unreadable-files (eq acdw/system :home))
184 (save-place-mode +1)) 265 (save-place-mode +1))
185 266
186;;;;; Keep track of recent files
187(setup (:require recentf) 267(setup (:require recentf)
188 (:option recentf-save-file (acdw/in-dir "recentf.el") 268 (:option recentf-save-file (acdw/dir "recentf.el")
189 recentf-max-menu-items 100 269 recentf-max-menu-items 100
190 recentf-max-saved-items nil 270 recentf-max-saved-items nil
191 recentf-auto-cleanup 60 271 recentf-auto-cleanup 60
192 (append recentf-exclude) acdw/dir) 272 (append recentf-exclude) (acdw/dir))
193 (recentf-mode +1)) 273 (recentf-mode +1))
194 274
195;;;; Windows
196(winner-mode +1)
197
198;;;; Minibuffer
199(setc minibuffer-prompt-properties
200 '(read-only t cursor-intangible t face minibuffer-prompt)
201 enable-recursive-minibuffers t
202 file-name-shadow-properties '(invisible t intangible t)
203 read-answer-short t)
204(minibuffer-depth-indicate-mode +1)
205(file-name-shadow-mode +1)
206(fset 'yes-or-no-p #'y-or-n-p)
207
208;;;;; Save minibuffer command history (and others)
209(setup (:require savehist) 275(setup (:require savehist)
210 (:option (append savehist-additional-variables) 'kill-ring 276 (:option (append savehist-additional-variables) 'kill-ring
211 (append savehist-additional-variables) 'search-ring 277 (append savehist-additional-variables) 'search-ring
@@ -213,151 +279,36 @@
213 history-length t 279 history-length t
214 history-delete-duplicates t 280 history-delete-duplicates t
215 savehist-autosave-interval 6 281 savehist-autosave-interval 6
216 savehist-file (acdw/in-dir "savehist.el")) 282 savehist-file (acdw/dir "savehist.el"))
217 (savehist-mode +1)) 283 (savehist-mode +1))
218 284
219;;;;; Completion framework
220(setup (:require icomplete)
221 (:option completion-ignore-case t
222 read-buffer-completion-ignore-case t
223 icomplete-delay-completions-threshold 0
224 icomplete-max-delay-chars 0
225 icomplete-compute-delay 0
226 icomplete-show-matches-on-no-input t
227 icomplete-with-buffer-completion-tables t
228 icomplete-in-buffer t
229 completion-styles '(partial-completion substring flex)
230 completion-category-defaults nil
231 completion-category-overrides
232 '((file (styles . (partial-completion)))))
233 (fido-mode -1)
234 (icomplete-mode +1))
235
236;;;;; `imenu'
237(setup imenu 285(setup imenu
238 (:option imenu-auto-rescan t)) 286 (:option imenu-auto-rescan t))
239 287
240;;;; Cursor
241(setc cursor-type 'bar
242 cursor-in-non-selected-windows 'hollow)
243
244;;;; Scrolling
245(setc auto-window-vscroll nil
246 fast-but-imprecise-scrolling t
247 scroll-margin 0
248 scroll-conservatively 101
249 scroll-preserve-screen-position 1)
250
251;;;; Fonts
252;; Load them /after/ the first frame comes into focus
253(add-function :after after-focus-change-function
254 (defun hook--setup-fonts ()
255 (dolist (face '(default fixed-pitch))
256 ;; `default' and `fixed-pitch' should be the same.
257 (set-face-attribute face nil
258 :font (pcase acdw/system
259 (:home "DejaVu Sans Mono-10")
260 (:work "Consolas-10")
261 (:other "monospace-10"))))
262 ;; `variable-pitch' is, of course, different.
263 (set-face-attribute 'variable-pitch nil
264 :font (pcase acdw/system
265 (:home "DejaVu Sans")
266 (:work "Calibri-11")
267 (:other "sans-serif")))
268 (remove-function after-focus-change-function
269 'hook--setup-fonts)))
270
271;;;; Debugger
272(setup debugger 288(setup debugger
273 (:hook visual-line-mode) 289 (:hook visual-line-mode)
274 (:acdw/leader "d" toggle-debug-on-error)) 290 (:leader "d" toggle-debug-on-error))
275 291
276;;;; Garbage collection 292(setup eldoc
277(add-hook 'minibuffer-setup-hook #'acdw/gc-disable) 293 (:option eldoc-idle-delay 0.1
278(add-hook 'minibuffer-exit-hook #'acdw/gc-enable) 294 eldoc-echo-area-use-multiline-p nil))
279(add-function :after after-focus-change-function
280 (defun hook--gc-when-unfocused ()
281 (acdw/when-unfocused #'garbage-collect)))
282 295
283;;;; Spelling
284(setup flyspell 296(setup flyspell
285 (setenv "LANG" "en_US")
286 (:option ispell-program-name "hunspell" 297 (:option ispell-program-name "hunspell"
287 ispell-dictionary "en_US" 298 ispell-dictionary "en_US"
288 ispell-personal-dictionary "~/.hunspell_personal") 299 ispell-personal-dictionary "~/.hunspell_personal")
300 (:needs ispell-program-name) ; don't proceed if not installed
301
289 (ispell-set-spellchecker-params) 302 (ispell-set-spellchecker-params)
290 (unless (file-exists-p ispell-personal-dictionary) 303 (unless (file-exists-p ispell-personal-dictionary)
291 (write-region "" nil ispell-personal-dictionary nil 0)) 304 (write-region "" nil ispell-personal-dictionary nil 0))
292 305
293 (:needs ispell-program-name)
294 ;; add hooks
295 (add-hook 'text-mode-hook #'flyspell-mode) 306 (add-hook 'text-mode-hook #'flyspell-mode)
296 (add-hook 'prog-mode-hook #'flyspell-prog-mode)) 307 (add-hook 'prog-mode-hook #'flyepell-prog-mode))
297
298;;;; MS Windows
299(when (eq acdw/system :work)
300 (setc w32-allow-system-shell t
301 w32-pass-lwindow-to-system nil
302 w32-lwindow-modifier 'super
303 w32-pass-rwindow-to-system nil
304 w32-rwindow-modifier 'super
305 w32-pass-apps-to-system nil
306 w32-apps-modifier 'hyper))
307
308;;;; Set up non-special modes
309;; Great idea from brause.cc
310(defun-with-hooks '(text-mode-hook prog-mode-hook diff-mode-hook)
311 (defun hook--setup-regular-modes ()
312 (setq indicate-empty-lines t
313 indicate-buffer-boundaries '((top . right) (bottom . right)))
314 (goto-address-mode +1)
315 (show-paren-mode +1)))
316
317;;;; Etc. good defaults
318(setc custom-file (acdw/in-dir "custom.el")
319 inhibit-startup-screen t
320 initial-buffer-choice t
321 initial-scratch-message (concat ";; Howdy, " (nth 0 (split-string
322 user-full-name))
323 "! Welcome to GNU Emacs.\n\n")
324 default-directory (expand-file-name "~/")
325 disabled-command-function nil
326 load-prefer-newer t
327 comp-async-report-warnings-errors nil
328 frame-title-format '("%b %+%* GNU Emacs"
329 (:eval (when (frame-parameter nil 'client)
330 " Client")))
331 tab-bar-show 1
332 use-dialog-box nil
333 use-file-dialog nil
334 echo-keystrokes 0.25
335 recenter-positions '(top middle bottom)
336 attempt-stack-overflow-recovery nil
337 attempt-orderly-shutdown-on-fatal-signal nil
338 window-resize-pixelwise t
339 find-function-C-source-directory
340 (pcase acdw/system
341 (:work (expand-file-name (concat "~/src/emacs-"
342 emacs-version
343 "/src")))
344 (:home (expand-file-name "~/src/pkg/emacs/src/emacs-git/src"))
345 (:other nil)))
346
347;;;; Etc. modes
348(tooltip-mode -1)
349
350;;;; Etc. bindings
351(global-set-key [remap just-one-space] #'cycle-spacing)
352(global-set-key (kbd "M-/") #'hippie-expand)
353(global-set-key (kbd "M-=") #'count-words)
354(global-set-key (kbd "C-x C-b") #'ibuffer)
355 308
356 309
357;;; Applications 310;; Applications
358;; Some of these are built-in, some are packages; all are "extra" functionality 311
359;; in Emacs (i.e., they're not /just/ editing text)
360;;;; Org mode
361(setup (:straight (org :host nil 312(setup (:straight (org :host nil
362 :repo "https://code.orgmode.org/bzg/org-mode.git")) 313 :repo "https://code.orgmode.org/bzg/org-mode.git"))
363 (require 'acdw-org) 314 (require 'acdw-org)
@@ -383,38 +334,35 @@
383 (:bind "RET" unpackaged/org-return-dwim) 334 (:bind "RET" unpackaged/org-return-dwim)
384 (add-hook 'before-save-hook #'acdw/hook--org-mode-fix-blank-lines)) 335 (add-hook 'before-save-hook #'acdw/hook--org-mode-fix-blank-lines))
385 336
386;;;; Eshell
387(setup eshell 337(setup eshell
338 (:option eshell-directory-name (acdw/dir "eshell/" t)
339 eshell-aliases-file (acdw/dir "eshell/aliases" t))
340
388 (defun eshell-quit-or-delete-char (arg) 341 (defun eshell-quit-or-delete-char (arg)
389 "Delete the character to the right, or quit eshell on an empty line." 342 "Delete the character to the right, or quit eshell on an empty line."
390 (interactive "p") 343 (interactive "p")
391 (if (and (eolp) (looking-back eshell-prompt-regexp)) 344 (if (and (eolp) (looking-back eshell-prompt-regexp))
392 (eshell-life-is-too-much) 345 (eshell-life-is-too-much)
393 (delete-forward-char arg))) 346 (delete-forward-char arg)))
394 (:option eshell-directory-name (acdw/in-dir "eshell/" t) 347
395 eshell-aliases-file (acdw/in-dir "eshell/aliases" t)) 348 (hook-defun eshell-setup 'eshell-mode-hook
396 (add-hook 'eshell-mode-hook 349 (define-key eshell-mode-map (kbd "C-d")
397 (defun hook--eshell-setup () 350 #'eshell-quit-or-delete-char)
398 "Stuff to do after eshell is done setting up." 351 (when (fboundp simple-modeline--mode-line)
399 (define-key eshell-mode-map (kbd "C-d") 352 (setq mode-line-format '(:eval simple-modeline--mode-line)))))
400 #'eshell-quit-or-delete-char)
401 (setq mode-line-format '(:eval simple-modeline--mode-line)))))
402
403 353
404;;;; Ediff
405(setup ediff 354(setup ediff
406 (:option ediff-window-setup-function 'ediff-setup-windows-plain 355 (:option ediff-window-setup-function 'ediff-setup-windows-plain
407 ediff-split-window-function 'split-window-horizontally)) 356 ediff-split-window-function 'split-window-horizontally))
408 357
409;;;; Web browsing
410(setup browse-url 358(setup browse-url
411 (:setq-default browse-url-browser-function 'eww-browse-url 359 (:option browse-url-browser-function 'eww-browse-url
412 browse-url-secondary-browser-function 360 browse-url-secondary-browser-function
413 (if (executable-find "firefox") 361 (if (executable-find "firefox")
414 'browse-url-firefox 362 'browse-url-firefox
415 'browse-url-default-browser) 363 'browse-url-default-browser)
416 browse-url-new-window-flag t 364 browse-url-new-window-flag t
417 browse-url-firefox-new-window-is-tab t) 365 browse-url-firefox-new-window-is-tab t)
418 (when (eq acdw/system :work) 366 (when (eq acdw/system :work)
419 (add-to-list 'exec-path "C:/Program Files/Mozilla Firefox"))) 367 (add-to-list 'exec-path "C:/Program Files/Mozilla Firefox")))
420 368
@@ -428,11 +376,10 @@
428(setup eww 376(setup eww
429 (:hook acdw/reading-mode)) 377 (:hook acdw/reading-mode))
430 378
431;;;; Gemini/gopher browsing
432(setup (:straight (elpher :host nil 379(setup (:straight (elpher :host nil
433 :repo "git://thelambdalab.xyz/elpher.git")) 380 :repo "git://thelambdalab.xyz/elpher.git"))
434 (:option elpher-ipv4-always t 381 (:option elpher-ipv4-always t
435 elpher-certificate-directory (acdw/in-dir "elpher/") 382 elpher-certificate-directory (acdw/dir "elpher/")
436 elpher-gemini-max-fill-width fill-column) 383 elpher-gemini-max-fill-width fill-column)
437 (:bind "n" elpher-next-link 384 (:bind "n" elpher-next-link
438 "p" elpher-prev-link 385 "p" elpher-prev-link
@@ -455,7 +402,6 @@
455 (:option (append auto-mode-alist) 402 (:option (append auto-mode-alist)
456 '("\\.\\(gemini\\|gmi\\)\\'" . gemini-mode))) 403 '("\\.\\(gemini\\|gmi\\)\\'" . gemini-mode)))
457 404
458;;;; File browsing
459(setup dired 405(setup dired
460 (:setq-default dired-recursive-copies 'always 406 (:setq-default dired-recursive-copies 'always
461 dired-recursive-deletes 'always 407 dired-recursive-deletes 'always
@@ -486,7 +432,6 @@
486 (setup (:straight trashed) 432 (setup (:straight trashed)
487 (:option trashed-action-confirmer 'y-or-n-p)))) 433 (:option trashed-action-confirmer 'y-or-n-p))))
488 434
489;;;; Magit
490(setup (:straight magit) 435(setup (:straight magit)
491 (:acdw/leader "g" magit-status) 436 (:acdw/leader "g" magit-status)
492 (:option magit-display-buffer-function 437 (:option magit-display-buffer-function
@@ -495,39 +440,30 @@
495 (display-buffer buffer '(display-buffer-same-window))) 440 (display-buffer buffer '(display-buffer-same-window)))
496 magit-popup-display-buffer-action '((display-buffer-same-window)))) 441 magit-popup-display-buffer-action '((display-buffer-same-window))))
497 442
498;;;; Read e-books (nov.el)
499(setup (:straight nov) 443(setup (:straight nov)
500 (:option nov-text-width fill-column 444 (:option nov-text-width fill-column
501 (append auto-mode-alist) '("\\.epub\\'" . nov-mode))) 445 (append auto-mode-alist) '("\\.epub\\'" . nov-mode)))
502 446
503;;;; PDF Tools
504(when (eq acdw/system :home) 447(when (eq acdw/system :home)
505 (setup (:straight pdf-tools) 448 (setup (:straight pdf-tools)
506 (pdf-loader-install))) 449 (pdf-loader-install)))
507 450
508;;;; VTerm
509(when (eq acdw/system :home) 451(when (eq acdw/system :home)
510 (setup (:straight vterm))) 452 (setup (:straight vterm)))
511 453
512 454
513;;; Packages 455;; Extra packages
514
515;;;; Interactivity
516 456
517;;;;; Begin-end
518(setup (:straight beginend) 457(setup (:straight beginend)
519 (beginend-global-mode +1)) 458 (beginend-global-mode +1))
520 459
521;;;;; MWIM
522(setup (:straight mwim) 460(setup (:straight mwim)
523 (:global "C-a" mwim-beginning 461 (:global "C-a" mwim-beginning
524 "C-e" mwim-end)) 462 "C-e" mwim-end))
525 463
526;;;;; Expand-region
527(setup (:straight expand-region) 464(setup (:straight expand-region)
528 (:global "C-=" er/expand-region)) 465 (:global "C-=" er/expand-region))
529 466
530;;;;; CRUX
531(setup (:straight crux) 467(setup (:straight crux)
532 (:global "M-o" crux-other-window-or-switch-buffer 468 (:global "M-o" crux-other-window-or-switch-buffer
533 "C-k" crux-kill-and-join-forward 469 "C-k" crux-kill-and-join-forward
@@ -537,7 +473,6 @@
537 "C-c i" crux-find-user-init-file) 473 "C-c i" crux-find-user-init-file)
538 (crux-reopen-as-root-mode +1)) 474 (crux-reopen-as-root-mode +1))
539 475
540;;;;; AVY ... & friends
541(setup (:straight avy) 476(setup (:straight avy)
542 (:global "C-:" avy-goto-char 477 (:global "C-:" avy-goto-char
543 "C-'" avy-goto-char-timer 478 "C-'" avy-goto-char-timer
@@ -547,7 +482,6 @@
547 (eval-after-load "isearch" 482 (eval-after-load "isearch"
548 '(define-key isearch-mode-map (kbd "C-'") #'avy-isearch))) 483 '(define-key isearch-mode-map (kbd "C-'") #'avy-isearch)))
549 484
550;;;;; zzz-to-char
551(setup (:straight zzz-to-char) 485(setup (:straight zzz-to-char)
552 (defun acdw/zzz-up-to-char (prefix) 486 (defun acdw/zzz-up-to-char (prefix)
553 "Call `zzz-up-to-char', unless issued a PREFIX, in which case 487 "Call `zzz-up-to-char', unless issued a PREFIX, in which case
@@ -556,9 +490,9 @@ call `zzz-to-char'."
556 (if prefix 490 (if prefix
557 (call-interactively #'zzz-to-char) 491 (call-interactively #'zzz-to-char)
558 (call-interactively #'zzz-up-to-char))) 492 (call-interactively #'zzz-up-to-char)))
493
559 (:global "M-z" acdw/zzz-up-to-char)) 494 (:global "M-z" acdw/zzz-up-to-char))
560 495
561;;;;; anzu
562(setup (:straight anzu) 496(setup (:straight anzu)
563 (:option anzu-replace-to-string-separator " → " 497 (:option anzu-replace-to-string-separator " → "
564 anzu-cons-mode-line-p nil) 498 anzu-cons-mode-line-p nil)
@@ -573,20 +507,10 @@ call `zzz-to-char'."
573 507
574 (global-anzu-mode +1)) 508 (global-anzu-mode +1))
575 509
576;;;;; smart hungry delete
577(setup (:straight smart-hungry-delete)
578 (:global "<backspace>" smart-hungry-delete-backward-char
579 "C-d" smart-hungry-delete-forward-char)
580 (smart-hungry-delete-add-default-hooks))
581
582;;;; Functionality
583
584;;;;; Async
585(setup (:straight async) 510(setup (:straight async)
586 (autoload 'dired-async-mode "dired-async.el" nil t) 511 (autoload 'dired-async-mode "dired-async.el" nil t)
587 (dired-async-mode +1)) 512 (dired-async-mode +1))
588 513
589;;;;; Undo-fu
590(setup (:straight undo-fu) 514(setup (:straight undo-fu)
591 (:global "C-/" undo-fu-only-undo 515 (:global "C-/" undo-fu-only-undo
592 "C-?" undo-fu-only-redo)) 516 "C-?" undo-fu-only-redo))
@@ -594,25 +518,24 @@ call `zzz-to-char'."
594(setup (:straight undo-fu-session) 518(setup (:straight undo-fu-session)
595 (:option undo-fu-session-incompatible-files '("/COMMIT_EDITMSG\\'" 519 (:option undo-fu-session-incompatible-files '("/COMMIT_EDITMSG\\'"
596 "/git-rebase-todo\\'") 520 "/git-rebase-todo\\'")
597 undo-fu-session-directory (acdw/in-dir "undo/" t) 521 undo-fu-session-directory (acdw/dir "undo/" t)
598 undo-fu-session-compression (eq acdw/system :home)) 522 undo-fu-session-compression (eq acdw/system :home))
523
599 (global-undo-fu-session-mode +1)) 524 (global-undo-fu-session-mode +1))
600 525
601;;;; Minibuffer
602(setup (:straight (vertico 526(setup (:straight (vertico
603 :host github 527 :host github
604 :repo "minad/vertico")) 528 :repo "minad/vertico"))
529
605 (advice-add #'completing-read-multiple :filter-args 530 (advice-add #'completing-read-multiple :filter-args
606 (defun crm-indicator (args) 531 (defun crm-indicator (args)
607 (cons (concat "[CRM] " (car args)) (cdr args)))) 532 (cons (concat "[CRM] " (car args)) (cdr args))))
608 (icomplete-mode -1) 533
609 (vertico-mode +1)) 534 (vertico-mode +1))
610 535
611;;;;; Orderless
612(setup (:straight orderless) 536(setup (:straight orderless)
613 (:option (prepend completion-styles) 'orderless)) 537 (:option (prepend completion-styles) 'orderless))
614 538
615;;;;; Consult
616(setup (:straight consult) 539(setup (:straight consult)
617 540
618 ;; "Sensible" functions 541 ;; "Sensible" functions
@@ -625,6 +548,7 @@ if ripgrep is installed, otherwise `consult-grep'."
625 ((executable-find "rg") 548 ((executable-find "rg")
626 (call-interactively #'consult-ripgrep)) 549 (call-interactively #'consult-ripgrep))
627 (t (call-interactively #'consult-grep)))) 550 (t (call-interactively #'consult-grep))))
551
628 (defun consult-sensible-find () 552 (defun consult-sensible-find ()
629 "Peform `consult-locate' if locate is installed, otehrwise `consult-find'." 553 "Peform `consult-locate' if locate is installed, otehrwise `consult-find'."
630 (interactive "P") 554 (interactive "P")
@@ -686,15 +610,11 @@ if ripgrep is installed, otherwise `consult-grep'."
686 ;; Projects 610 ;; Projects
687 (:option consult-project-root-function #'vc-root-dir)) 611 (:option consult-project-root-function #'vc-root-dir))
688 612
689;;;;; Marginalia
690(setup (:straight marginalia) 613(setup (:straight marginalia)
691 (:option marginalia-annotators '(marginalia-annotators-heavy 614 (:option marginalia-annotators '(marginalia-annotators-heavy
692 marginalia-annotators-light)) 615 marginalia-annotators-light))
693 (marginalia-mode +1)) 616 (marginalia-mode +1))
694 617
695;;;; UI
696
697;;;;; Modus themes
698(setup (:straight (modus-themes 618(setup (:straight (modus-themes
699 :host gitlab 619 :host gitlab
700 :repo "protesilaos/modus-themes")) 620 :repo "protesilaos/modus-themes"))
@@ -708,7 +628,6 @@ if ripgrep is installed, otherwise `consult-grep'."
708 (acdw/sunrise-sunset #'modus-themes-load-operandi 628 (acdw/sunrise-sunset #'modus-themes-load-operandi
709 #'modus-themes-load-vivendi)) 629 #'modus-themes-load-vivendi))
710 630
711;;;;; Mode line
712(setup (:straight simple-modeline) 631(setup (:straight simple-modeline)
713 (setup (:straight minions)) 632 (setup (:straight minions))
714 (:option simple-modeline-segments 633 (:option simple-modeline-segments
@@ -725,22 +644,13 @@ if ripgrep is installed, otherwise `consult-grep'."
725 (require 'acdw-modeline) 644 (require 'acdw-modeline)
726 (simple-modeline-mode +1)) 645 (simple-modeline-mode +1))
727 646
728;;;;; Olivetti
729;; also useful for `acdw/reading-mode'
730(setup (:straight olivetti) 647(setup (:straight olivetti)
731 (:option olivetti-body-width (+ fill-column 4) 648 (:option olivetti-body-width (+ fill-column 4)
732 olivetti-minimum-body-width fill-column)) 649 olivetti-minimum-body-width fill-column))
733 650
734;;;;; Outshine
735(setup (:straight outshine)
736 (:option outline-minor-mode-prefix "")
737 (:hook-into emacs-lisp-mode))
738
739;;;;; Form-feed
740(setup (:straight form-feed) 651(setup (:straight form-feed)
741 (global-form-feed-mode +1)) 652 (global-form-feed-mode +1))
742 653
743;;;;; Which-key
744(setup (:straight which-key) 654(setup (:straight which-key)
745 (:option which-key-show-early-on-C-h t 655 (:option which-key-show-early-on-C-h t
746 which-key-idle-delay 10000 656 which-key-idle-delay 10000
@@ -748,7 +658,6 @@ if ripgrep is installed, otherwise `consult-grep'."
748 (which-key-setup-side-window-bottom) 658 (which-key-setup-side-window-bottom)
749 (which-key-mode +1)) 659 (which-key-mode +1))
750 660
751;;;;; Helpful
752(setup (:straight helpful) 661(setup (:straight helpful)
753 (:global "<help> f" helpful-callable 662 (:global "<help> f" helpful-callable
754 "<help> v" helpful-variable 663 "<help> v" helpful-variable
@@ -756,73 +665,48 @@ if ripgrep is installed, otherwise `consult-grep'."
756 "<help> o" helpful-symbol 665 "<help> o" helpful-symbol
757 "C-c C-d" helpful-at-point)) 666 "C-c C-d" helpful-at-point))
758 667
759;;;; Utilities
760
761;;;;; 0x0 -- upload files to a nullpointer
762(setup (:straight (0x0 :host nil 668(setup (:straight (0x0 :host nil
763 :repo "https://git.sr.ht/~zge/nullpointer-emacs")) 669 :repo "https://git.sr.ht/~zge/nullpointer-emacs"))
764 (:option 0x0-default-host 'ttm)) 670 (:option 0x0-default-host 'ttm))
765 671
766;;;;; Flyspell-correct
767(with-eval-after-load 'flyspell 672(with-eval-after-load 'flyspell
768 (setup (:straight flyspell-correct) 673 (setup (:straight flyspell-correct)
769 (define-key flyspell-mode-map (kbd "C-;") #'flyspell-correct-wrapper))) 674 (define-key flyspell-mode-map (kbd "C-;") #'flyspell-correct-wrapper)))
770 675
771;;;; System tie-ins
772;; Insctead of using `setup''s `:needs', I'm going to wrap these in
773;; `executable-find' forms. I don't want to waste time with pulling packages
774;; that won't work on a machine.
775
776;;;;; PKGBUILDs
777(when (eq acdw/system :home) 676(when (eq acdw/system :home)
778 (setup (:straight pkgbuild-mode))) 677 (setup (:straight pkgbuild-mode)))
779 678
780
781;;; Programming languages
782;; This section includes packages and other settings, because most languages'
783;; packages aren't packaged with Emacs.
784
785;;;; Formatting
786(setup (:straight (apheleia :host github 679(setup (:straight (apheleia :host github
787 :repo "raxod502/apheleia")) 680 :repo "raxod502/apheleia"))
788 (apheleia-global-mode +1) 681 (apheleia-global-mode +1)
789 682
790 ;; Use a dumb formatter on modes that `apheleia' doesn't work for. 683 ;; Use a dumb formatter on modes that `apheleia' doesn't work for.
791 (add-hook 'before-save-hook 684 (hook-defun dumb-auto-format before-save-hook
792 (defun dumb-auto-format () 685 (unless (and (fboundp 'apheleia--get-formatter-command)
793 "Run `indent-region' in buffers that don't have an `apheleia' 686 (apheleia--get-formatter-command))
794 formatter set." 687 (indent-region (point-min) (point-max)))))
795 (unless (and (fboundp 'apheleia--get-formatter-command)
796 (apheleia--get-formatter-command))
797 (indent-region (point-min) (point-max))))))
798
799;;;; Eldoc
800(setup eldoc
801 (:option eldoc-idle-delay 0.1
802 eldoc-echo-area-use-multiline-p nil))
803 688
804;;;; Lisps
805(setup (:straight paren-face) 689(setup (:straight paren-face)
806 (global-paren-face-mode +1)) 690 (global-paren-face-mode +1))
807 691
808;;;;; Paredit mode
809(setup (:straight paredit) 692(setup (:straight paredit)
810 (autoload 'enable-paredit-mode "paredit" nil t) 693 (autoload 'enable-paredit-mode "paredit" nil t)
811 (dolist (hook '(emacs-lisp-mode-hook 694
812 eval-expression-minibuffer-setup-hook 695 (:hook-into emacs-lisp-mode
813 ielm-mode-hook 696 eval-expression-minibuffer
814 lisp-mode-hook 697 ielm-mode
815 lisp-interaction-mode-hook 698 lisp-mode
816 scheme-mode-hook)) 699 lisp-interaction-mode
817 (add-hook hook #'enable-paredit-mode)) 700 scheme-mode)
818 (add-hook 'paredit-mode-hook 701
819 (defun hook--paredit-disable-electric-pair () 702 (defun disable-electric-pair-local-mode ()
820 (electric-pair-local-mode -1))) 703 (electric-pair-local-mode -1))
704
705 (:hook disable-electric-pair-local-mode)
706
821 (require 'eldoc) 707 (require 'eldoc)
822 (eldoc-add-command 'paredit-backward-delete 'paredit-close-round) 708 (eldoc-add-command 'paredit-backward-delete 'paredit-close-round))
823 (:bind "<backspace>" paredit-backward-delete))
824 709
825;;;;; Emacs lisp
826(setup elisp-mode 710(setup elisp-mode
827 (:option eval-expression-print-length nil 711 (:option eval-expression-print-length nil
828 eval-expression-print-level nil 712 eval-expression-print-level nil
@@ -839,34 +723,25 @@ if ripgrep is installed, otherwise `consult-grep'."
839 "C-c C-z" ielm)) 723 "C-c C-z" ielm))
840 724
841 (add-hook 'emacs-lisp-mode-hook 'turn-on-eldoc-mode) 725 (add-hook 'emacs-lisp-mode-hook 'turn-on-eldoc-mode)
842 (add-hook 'ielm-mode-hook 'turn-on-eldoc-mode)) 726 (add-hook 'ielm-mode-hook 'turn-on-eldoc-mode)
843 727
844(setup (:straight macrostep) 728 (setup (:straight macrostep)
845 (define-key emacs-lisp-mode-map (kbd "C-c e") #'macrostep-expand)) 729 (define-key emacs-lisp-mode-map (kbd "C-c e") #'macrostep-expand))
846 730
847(setup (:straight eros) 731 (setup (:straight eros)
848 (:hook-into emacs-lisp-mode)) 732 (:hook-into emacs-lisp-mode)))
849 733
850;;;;; Fennel
851(when (executable-find "fennel") 734(when (executable-find "fennel")
852 (setup (:straight fennel-mode) 735 (setup (:straight fennel-mode)
853 (autoload 'fennel-mode "fennel-mode" nil t) 736 (autoload 'fennel-mode "fennel-mode" nil t)
854 (:option (append auto-mode-alist) '("\\.fnl\\'" . fennel-mode)) 737 (:option (append auto-mode-alist) '("\\.fnl\\'" . fennel-mode))
855 (:bind "C-c C-c" ))) 738 (:bind "C-c C-c" )))
856 739
857;;;;; Scheme 740(setup (:straight geiser))
858(when (or (executable-find "guile")
859 (executable-find "csi")
860 (executable-find "racket"))
861 (setup (:straight geiser)
862 (:with-mode geiser-repl-mode
863 (:hook enable-paredit-mode))))
864 741
865;;;; Lua
866(setup (:straight lua-mode) 742(setup (:straight lua-mode)
867 (:option (append auto-mode-alist) '("\\.lua\\'" . lua-mode))) 743 (:option (append auto-mode-alist) '("\\.lua\\'" . lua-mode)))
868 744
869;;;; Shell scripts
870(setup sh-mode 745(setup sh-mode
871 (:option sh-basic-offset tab-width 746 (:option sh-basic-offset tab-width
872 sh-indent-after-case 0 747 sh-indent-after-case 0
@@ -884,7 +759,6 @@ if ripgrep is installed, otherwise `consult-grep'."
884 (:hook flymake-mode 759 (:hook flymake-mode
885 flymake-shellcheck-load))) 760 flymake-shellcheck-load)))
886 761
887;;;; Web languages
888(setup (:straight web-mode) 762(setup (:straight web-mode)
889 (:option css-level-offset 2 763 (:option css-level-offset 2
890 js-indent-level 2 764 js-indent-level 2
@@ -899,11 +773,8 @@ if ripgrep is installed, otherwise `consult-grep'."
899 (add-to-list 'auto-mode-alist 773 (add-to-list 'auto-mode-alist
900 `(,(concat "\\." extension "\\'") . web-mode)))) 774 `(,(concat "\\." extension "\\'") . web-mode))))
901 775
902;;;; FORTH
903(when (locate-library "gforth") 776(when (locate-library "gforth")
904 (autoload 'forth-mode "gforth") 777 (autoload 'forth-mode "gforth")
905 (add-to-list 'auto-mode-alist '("\\.fs\\'" . forth-mode)) 778 (add-to-list 'auto-mode-alist '("\\.fs\\'" . forth-mode))
906 (autoload 'forth-block-mode "gforth") 779 (autoload 'forth-block-mode "gforth")
907 (add-to-list 'auto-mode-alist '("\\.fb\\'" . forth-block-mode))) 780 (add-to-list 'auto-mode-alist '("\\.fb\\'" . forth-block-mode)))
908
909;;;- init.el ends here
diff --git a/lisp/acdw.el b/lisp/acdw.el index d412b4b..69f9a7f 100644 --- a/lisp/acdw.el +++ b/lisp/acdw.el
@@ -18,139 +18,79 @@
18;; functions for me, acdw. 18;; functions for me, acdw.
19 19
20;;; Code: 20;;; Code:
21
22;; Utility constants
21 23
22;;; Utilities
23
24;;;; Determine the system I'm on
25(defconst acdw/system (pcase system-type 24(defconst acdw/system (pcase system-type
26 ('gnu/linux :home) 25 ('gnu/linux :home)
27 ((or 'msdos 'windows-nt) :work) 26 ((or 'msdos 'windows-nt) :work)
28 (_ :other)) 27 (_ :other))
29 "Which system is currently being used.") 28 "Which computer system is currently being used.")
30 29
31;;;; Run commands only when unfocused 30
32(defun acdw/when-unfocused (func &rest args) 31;; Utility functions
33 "Call FUNC, with ARGS, iff all Emacs frames are out of focus. 32
34 33(defmacro when-unfocused (name &rest forms)
35Ready for use with `after-focus-change-function'." 34 "Define a function NAME, executing FORMS, that fires when Emacs
36 (when (seq-every-p #'null (mapcar #'frame-focus-state (frame-list))) 35is unfocused."
37 (apply func args))) 36 (declare (indent 1))
38 37 (let ((func-name (intern (concat "when-unfocused-" (symbol-name name)))))
39;;;; Run commands at sunrise and sunset 38 `(progn
40(defun acdw/sunrise-sunset (sunrise-command sunset-command) 39 (defun ,func-name () "Defined by `when-unfocused'."
41 "Run commands at sunrise and sunset." 40 (when (seq-every-p #'null
42 (let* ((times-regex (rx (* nonl) 41 (mapcar #'frame-focus-state (frame-list)))
43 (: (any ?s ?S) "unrise") " " 42 ,@forms))
44 (group (repeat 1 2 digit) ":" 43 (add-function :after after-focus-change-function #',func-name))))
45 (repeat 1 2 digit) 44
46 (: (any ?a ?A ?p ?P) (any ?m ?M))) 45(defmacro hook-defun (name hooks &rest forms)
47 (* nonl) 46 "Define a function NAME that executes FORMS, and add it to
48 (: (any ?s ?S) "unset") " " 47each hook in HOOKS."
49 (group (repeat 1 2 digit) ":" 48 (declare (indent 2))
50 (repeat 1 2 digit) 49 (let ((func-name (intern (concat "hook-defun-" (symbol-name name))))
51 (: (any ?a ?A ?p ?P) (any ?m ?M))) 50 (hook-list (if (consp hooks) hooks (list hooks)))
52 (* nonl))) 51 (hook-defun-add-hook-list))
53 (ss (sunrise-sunset)) 52 `(progn
54 (_m (string-match times-regex ss)) 53 (defun ,func-name () "Defined by `hook-defun'." ,@forms)
55 (sunrise-time (match-string 1 ss)) 54 ,@(dolist (hook hook-list hook-defun-add-hook-list)
56 (sunset-time (match-string 2 ss))) 55 (push `(add-hook ',hook #',func-name) hook-defun-add-hook-list)))))
57 (run-at-time sunrise-time (* 60 60 24) sunrise-command) 56
58 (run-at-time sunset-time (* 60 60 24) sunset-command) 57(defun refresh-emacs ()
59 (run-at-time "12:00am" (* 60 60 24) sunset-command))) 58 "Reload Emacs's configuration files."
60 59 (interactive)
61;;;; Define a function and add it to hooks 60 (dolist (file (list (locate-user-emacs-file "early-init.el")
62(defun defun-with-hooks (hooks function-def) 61 (locate-user-emacs-file "init.el" ".emacs")))
63 "Add FUNCTION-DEF to HOOKS. 62 (when (file-exists-p file)
63 (load-file file))))
64
65(defun acdw/dir (&optional file make-directory)
66 "Place Emacs files in one place.
67
68If called without parameters, `acdw/dir' expands to
69~/.emacs.d/var or similar. If called with FILE, `acdw/dir'
70expands FILE to ~/.emacs.d/var, optionally making its directory
71if MAKE-DIRECTORY is non-nil."
72 (let ((dir (expand-file-name (convert-standard-filename "var/")
73 user-emacs-directory)))
74 (if file
75 (let ((file-name (expand-file-name (convert-standard-filename file)
76 dir)))
77 (when make-directory
78 (make-directory (file-name-directory file-name) 'parents))
79 file-name)
80 dir)))
64 81
65FUNCTION-DEF should be a `defun' form. This function is just to 82(defun acdw/gc-enable ()
66 put functions that only exist for hooks closer to the hooks 83 "Enable the Garbage collector."
67 they bind to." 84 (setq gc-cons-threshold (* 800 1024 1024)
68 (let ((func function-def)) 85 gc-cons-percentage 0.1))
69 (dolist (hook hooks)
70 (add-hook hook func))))
71
72;;; Garbage collection hacks
73
74(defconst acdw/gc-cons-threshold-basis (* 800 1024)
75 "Basis value for `gc-cons-threshold' to return to after jumping.
76800 KB is Emacs's default.")
77
78(defconst acdw/gc-cons-percentage-basis 0.1
79 "Basis value for `gc-cons-percentage' to return to after jumping.
800.1 is Emacs's default.")
81 86
82(defun acdw/gc-disable () 87(defun acdw/gc-disable ()
83 "Disable garbage collection by setting relevant variables to their maxima." 88 "Functionally disable the Garbage collector."
84 (setq gc-cons-threshold most-positive-fixnum 89 (setq gc-cons-threshold most-positive-fixnum
85 gc-cons-percentage 0.8)) 90 gc-cons-percentage 0.8))
86 91
87(defun acdw/gc-enable () 92
88 "Re-enable garbage collection by setting relevant variables back to bases." 93;; Make `C-z' more useful
89 (setq gc-cons-threshold acdw/gc-cons-threshold-basis
90 gc-cons-percentage acdw/gc-cons-percentage-basis))
91
92;;; Directories (think `no-littering')
93
94(defvar acdw/dir (expand-file-name
95 (convert-standard-filename "var/")
96 user-emacs-directory)
97 "A directory to hold extra configuration and emacs data.")
98
99(defun acdw/in-dir (file &optional make-directory)
100 "Expand FILE relative to `acdw/dir', optionally creating its
101directory."
102 (let ((f (expand-file-name (convert-standard-filename file)
103 acdw/dir)))
104 (when make-directory
105 (make-directory (file-name-directory f) 'parents))
106 f))
107
108;;; Reading mode
109
110(define-minor-mode acdw/reading-mode
111 "A mode for reading."
112 :init-value t
113 :lighter " Read"
114 (if acdw/reading-mode
115 (progn ;; turn on
116 ;; settings
117 (setq-local mode-line-format
118 '(:eval
119 (let* ((fmt " Reading %b (%m) ")
120 (len (length (format-mode-line fmt))))
121 (concat
122 (propertize " "
123 'display `((space :align-to (- right
124 ,len)))
125 'face '(:inherit italic))
126 fmt))))
127 ;; modes to disable
128 (dolist (mode '(display-fill-column-indicator-mode))
129 (when (fboundp mode)
130 (funcall mode -1)))
131 ;; modes to enable
132 (dolist (mode '(iscroll-mode
133 olivetti-mode))
134 (when (fboundp mode)
135 (funcall mode +1))))
136 ;; turn off
137 ;; settings
138 (kill-local-variable 'mode-line-format)
139 ;; modes to re-enable
140 (dolist (mode '(display-fill-column-indicator-mode
141 simple-modeline-mode))
142 (when (fboundp mode)
143 (funcall mode +1)))
144 ;; modes to re-disable
145 (dolist (mode '(olivetti-mode
146 iscroll-mode))
147 (when (fboundp mode)
148 (funcall mode -1)))
149 (force-mode-line-update)))
150
151;;; Keymap & Mode
152
153;; Set up a leader key for `acdw/mode'
154(defvar acdw/leader 94(defvar acdw/leader
155 (let ((map (make-sparse-keymap)) 95 (let ((map (make-sparse-keymap))
156 (c-z (global-key-binding "\C-z"))) 96 (c-z (global-key-binding "\C-z")))
@@ -159,5 +99,4 @@ directory."
159 map)) 99 map))
160 100
161(provide 'acdw) 101(provide 'acdw)
162
163;;; acdw.el ends here 102;;; acdw.el ends here