diff options
Diffstat (limited to 'lisp/+emacs.el')
-rw-r--r-- | lisp/+emacs.el | 422 |
1 files changed, 0 insertions, 422 deletions
diff --git a/lisp/+emacs.el b/lisp/+emacs.el deleted file mode 100644 index 97377a3..0000000 --- a/lisp/+emacs.el +++ /dev/null | |||
@@ -1,422 +0,0 @@ | |||
1 | ;;; +emacs.el --- measured defaults for Emacs -*- lexical-binding: t -*- | ||
2 | |||
3 | ;;; Commentary: | ||
4 | |||
5 | ;; I find myself copy-pasting a lot of "boilerplate" type code when | ||
6 | ;; bankrupting my Emacs config and starting afresh. Instead of doing | ||
7 | ;; that, I'm putting it here, where it'll be easier to include in my | ||
8 | ;; config. | ||
9 | |||
10 | ;; Of course, some might say I could just ... stop bankrupting my | ||
11 | ;; Emacs. But like, why would I want to? | ||
12 | |||
13 | ;; Other notable packages include | ||
14 | ;; - https://git.sr.ht/~technomancy/better-defaults/ | ||
15 | ;; - https://github.com/susam/emfy | ||
16 | |||
17 | ;;; Code: | ||
18 | |||
19 | (require 'early-init (locate-user-emacs-file "early-init.el")) | ||
20 | |||
21 | (defun +set-major-mode-from-buffer-name (&optional buf) | ||
22 | "Set the major mode for BUF from the buffer's name. | ||
23 | Do this only if the buffer is not visiting a file." | ||
24 | (unless buffer-file-name | ||
25 | (let ((buffer-file-name (buffer-name buf))) | ||
26 | (set-auto-mode)))) | ||
27 | |||
28 | |||
29 | ;;; General settings | ||
30 | |||
31 | (setq-default | ||
32 | apropos-do-all t | ||
33 | async-shell-command-buffer 'new-buffer | ||
34 | async-shell-command-display-buffer nil | ||
35 | auto-hscroll-mode 'current-line | ||
36 | auto-revert-verbose t | ||
37 | auto-save-default nil | ||
38 | auto-save-file-name-transforms `((".*" ,(.etc "auto-save/") ,(car (secure-hash-algorithms))) | ||
39 | (".*" ,(.etc "auto-save/") t)) | ||
40 | auto-save-interval 30 | ||
41 | auto-save-list-file-prefix (.etc "auto-save/.saves-" t) | ||
42 | auto-save-timeout 30 | ||
43 | auto-save-visited-interval 5 | ||
44 | auto-window-vscroll nil | ||
45 | backup-by-copying t | ||
46 | backup-directory-alist `((".*" . ,(.etc "backup/" t))) | ||
47 | blink-cursor-blinks 1 | ||
48 | comp-deferred-compilation nil | ||
49 | completion-category-defaults nil | ||
50 | completion-category-overrides '((file (styles . (partial-completion)))) | ||
51 | completion-ignore-case t | ||
52 | completion-styles '(substring partial-completion) | ||
53 | create-lockfiles nil | ||
54 | cursor-in-non-selected-windows 'hollow | ||
55 | cursor-type 'bar | ||
56 | custom-file (.etc "custom.el") | ||
57 | delete-old-versions t | ||
58 | echo-keystrokces 0.1 | ||
59 | ediff-window-setup-function 'ediff-setup-windows-plain | ||
60 | eldoc-echo-area-use-multiline-p nil | ||
61 | eldoc-idle-delay 0.1 | ||
62 | enable-recursive-minibuffers t | ||
63 | executable-prefix-env t | ||
64 | fast-but-imprecise-scrolling t | ||
65 | file-name-shadow-properties '(invisible t intangible t) | ||
66 | fill-column 80 | ||
67 | find-file-visit-truename t | ||
68 | frame-resize-pixelwise t | ||
69 | global-auto-revert-non-file-buffers t | ||
70 | global-mark-ring-max 100 | ||
71 | hscroll-margin 1 | ||
72 | hscroll-step 1 | ||
73 | imenu-auto-rescan t | ||
74 | image-use-external-converter (or (executable-find "convert") | ||
75 | (executable-find "gm") | ||
76 | (executable-find "ffmpeg")) | ||
77 | indent-tabs-mode nil | ||
78 | inhibit-startup-screen t | ||
79 | initial-buffer-choice t | ||
80 | kept-new-versions 6 | ||
81 | kept-old-versions 2 | ||
82 | kill-do-not-save-duplicates t | ||
83 | kill-read-only-ok t | ||
84 | kill-ring-max 500 | ||
85 | kmacro-ring-max 20 | ||
86 | load-prefer-newer noninteractive | ||
87 | major-mode '+set-major-mode-from-buffer-name | ||
88 | mark-ring-max 50 | ||
89 | minibuffer-eldef-shorten-default t | ||
90 | minibuffer-prompt-properties (list 'read-only t | ||
91 | 'cursor-intangible t | ||
92 | 'face 'minibuffer-prompt) | ||
93 | mode-require-final-newline 'visit-save | ||
94 | mouse-drag-copy-region t | ||
95 | mouse-wheel-progressive-speed nil | ||
96 | mouse-yank-at-point t | ||
97 | native-comp-async-report-warnings-errors 'silent | ||
98 | native-comp-deferred-compilation nil | ||
99 | read-answer-short t | ||
100 | read-buffer-completion-ignore-case t | ||
101 | ;; read-extended-command-predicate | ||
102 | ;; (when (fboundp | ||
103 | ;; 'command-completion-default-include-p) | ||
104 | ;; 'command-completion-default-include-p) | ||
105 | read-process-output-max 1048576 ; We’re in the future man. Set that to at least a megabyte | ||
106 | recenter-positions '(top 2 middle bottom) | ||
107 | regexp-search-ring-max 100 | ||
108 | regexp-search-ring-max 200 | ||
109 | save-interprogram-paste-before-kill t | ||
110 | save-some-buffers-default-predicate #'+save-some-buffers-p | ||
111 | scroll-conservatively 25 | ||
112 | scroll-margin 0 | ||
113 | scroll-preserve-screen-position 1 | ||
114 | scroll-step 1 | ||
115 | search-ring-max 200 | ||
116 | search-ring-max 200 | ||
117 | sentence-end-double-space t | ||
118 | set-mark-command-repeat-pop t | ||
119 | show-paren-delay 0 | ||
120 | show-paren-style 'parenthesis | ||
121 | show-paren-when-point-in-periphery t | ||
122 | show-paren-when-point-inside-paren t | ||
123 | ;;show-trailing-whitespace t | ||
124 | tab-bar-show 1 | ||
125 | tab-width 8 ; so alignment expecting the default looks right | ||
126 | tramp-backup-directory-alist backup-directory-alist | ||
127 | undo-limit 100000000 ; 10 MB | ||
128 | use-dialog-box nil | ||
129 | use-file-dialog nil | ||
130 | use-short-answers t | ||
131 | vc-follow-symlinks t | ||
132 | vc-make-backup-files t | ||
133 | version-control t | ||
134 | view-read-only t | ||
135 | visible-bell nil | ||
136 | window-resize-pixelwise t | ||
137 | x-select-enable-clipboard t | ||
138 | x-select-enable-primary t | ||
139 | yank-pop-change-selection t | ||
140 | ) | ||
141 | |||
142 | ;; Programming language offsets. | ||
143 | ;; Set these after the initial block so I can use `tab-width' | ||
144 | (setq-default | ||
145 | c-basic-offset tab-width) | ||
146 | |||
147 | ;; Emacs 28 ships with an option, `use-short-answers', that makes this form | ||
148 | ;; obsolete, but I still use 27 at work. | ||
149 | (when (version< emacs-version "28") | ||
150 | (fset 'yes-or-no-p 'y-or-n-p)) | ||
151 | |||
152 | |||
153 | ;;; Encodings | ||
154 | |||
155 | ;; Allegedly, this is the only one you need... | ||
156 | (set-language-environment "UTF-8") | ||
157 | ;; But I still set all of these, for fun. | ||
158 | (setq-default locale-coding-system 'utf-8-unix | ||
159 | coding-system-for-read 'utf-8-unix | ||
160 | coding-system-for-write 'utf-8-unix | ||
161 | buffer-file-coding-system 'utf-8-unix | ||
162 | default-process-coding-system '(utf-8-unix . utf-8-unix) | ||
163 | x-select-request-type '(UTF8_STRING | ||
164 | COMPOUND_TEXT | ||
165 | TEXT | ||
166 | STRING)) | ||
167 | |||
168 | (set-charset-priority 'unicode) | ||
169 | (prefer-coding-system 'utf-8-unix) | ||
170 | (set-default-coding-systems 'utf-8-unix) | ||
171 | (set-terminal-coding-system 'utf-8-unix) | ||
172 | (set-keyboard-coding-system 'utf-8-unix) | ||
173 | |||
174 | (pcase system-type | ||
175 | ((or 'ms-dos 'windows-nt) | ||
176 | (set-clipboard-coding-system 'utf-16-le) | ||
177 | (set-selection-coding-system 'utf-16-le)) | ||
178 | (_ | ||
179 | (set-selection-coding-system 'utf-8) | ||
180 | (set-clipboard-coding-system 'utf-8))) | ||
181 | |||
182 | |||
183 | ;;; Modes | ||
184 | |||
185 | (dolist (enable-mode '(global-auto-revert-mode | ||
186 | blink-cursor-mode | ||
187 | electric-pair-mode | ||
188 | show-paren-mode | ||
189 | global-so-long-mode | ||
190 | minibuffer-depth-indicate-mode | ||
191 | file-name-shadow-mode | ||
192 | minibuffer-electric-default-mode | ||
193 | delete-selection-mode | ||
194 | auto-save-visited-mode | ||
195 | ;; column-number-mode | ||
196 | )) | ||
197 | (when (fboundp enable-mode) | ||
198 | (funcall enable-mode +1))) | ||
199 | |||
200 | (dolist (disable-mode '(tooltip-mode | ||
201 | tool-bar-mode | ||
202 | menu-bar-mode | ||
203 | scroll-bar-mode | ||
204 | horizontal-scroll-bar-mode)) | ||
205 | (when (fboundp disable-mode) | ||
206 | (funcall disable-mode -1))) | ||
207 | |||
208 | |||
209 | ;;; Hooks | ||
210 | |||
211 | (defun +auto-create-missing-dirs () | ||
212 | "Automatically create missing directories when finding a file." | ||
213 | ;; https://emacsredux.com/blog/2022/06/12/auto-create-missing-directories/ | ||
214 | (let ((target-dir (file-name-directory buffer-file-name))) | ||
215 | (unless (file-exists-p target-dir) | ||
216 | (make-directory target-dir t)))) | ||
217 | |||
218 | (defvar +save-some-buffers-debounce-time nil | ||
219 | "Last time `+save-some-buffers-debounce' was run.") | ||
220 | |||
221 | (defcustom +save-some-buffers-debounce-timeout 5 | ||
222 | "Number of seconds to wait before saving buffers again.") | ||
223 | |||
224 | (defun +save-some-buffers-debounce (&rest _) | ||
225 | "Run `save-some-buffers', but only if it's been a while." | ||
226 | (unless (and +save-some-buffers-debounce-time | ||
227 | (< (- (time-convert nil 'integer) +save-some-buffers-debounce-time) | ||
228 | +save-some-buffers-debounce-timeout)) | ||
229 | (save-some-buffers t) | ||
230 | (setf +save-some-buffers-debounce-time (time-convert nil 'integer)))) | ||
231 | |||
232 | |||
233 | ;;; Better-default functions ... | ||
234 | |||
235 | (defun +cycle-spacing (&optional n preserve-nl-back mode) | ||
236 | "Negate N argument on `cycle-spacing'. | ||
237 | That is, with a positive N, deletes newlines as well, leaving -N | ||
238 | spaces. If N is negative, it will not delete newlines and leave | ||
239 | N spaces. See docstring of `cycle-spacing' for the meaning of | ||
240 | PRESERVE-NL-BACK and MODE." | ||
241 | (interactive "*p") | ||
242 | (cycle-spacing (- n))) | ||
243 | |||
244 | (defun +save-buffers-quit (&optional arg) | ||
245 | "Silently save each buffer, then kill the current connection. | ||
246 | If the current frame has no client, kill Emacs itself using | ||
247 | `save-buffers-kill-emacs' after confirming with the user. | ||
248 | |||
249 | With prefix ARG, silently save all file-visiting buffers, then | ||
250 | kill without asking." | ||
251 | (interactive "P") | ||
252 | (save-some-buffers t) | ||
253 | (if (and (not (frame-parameter nil 'client)) | ||
254 | (and (not arg))) | ||
255 | (when (yes-or-no-p "Sure you want to quit? ") | ||
256 | (save-buffers-kill-emacs)) | ||
257 | (delete-frame nil :force))) | ||
258 | |||
259 | (defun +kill-word-backward-or-region (&optional arg backward-kill-word-fn) | ||
260 | "Kill active region or ARG words backward. | ||
261 | BACKWARD-KILL-WORD-FN is the function to call to kill a word | ||
262 | backward. It defaults to `backward-kill-word'." | ||
263 | (interactive "P") | ||
264 | (call-interactively (if (region-active-p) | ||
265 | #'kill-region | ||
266 | (or backward-kill-word-fn #'backward-kill-word)))) | ||
267 | |||
268 | (defun +backward-kill-word-wrapper (fn &optional arg) | ||
269 | "Kill backward using FN until the beginning of a word, smartly. | ||
270 | If point is on at the beginning of a line, kill the previous new | ||
271 | line. If the only thing before point on the current line is | ||
272 | whitespace, kill that whitespace. | ||
273 | |||
274 | With argument ARG: if ARG is a number, just call FN | ||
275 | ARG times. Otherwise, just call FN." | ||
276 | ;; I want this to be a wrapper so that I can call other word-killing functions | ||
277 | ;; with it. It's *NOT* advice because those functions probably use | ||
278 | ;; `backward-kill-word' under the hood (looking at you, paredit), so advice | ||
279 | ;; will make things weird. | ||
280 | (if (null arg) | ||
281 | (cond | ||
282 | ((looking-back "^" 1) | ||
283 | (let ((delete-active-region nil)) | ||
284 | (delete-backward-char 1))) | ||
285 | ((looking-back "^[ ]*") | ||
286 | (delete-horizontal-space :backward-only)) | ||
287 | (t (call-interactively fn))) | ||
288 | (funcall fn (if (listp arg) 1 arg)))) | ||
289 | |||
290 | (defun +backward-kill-word (&optional arg) | ||
291 | "Kill word backward using `backward-kill-word'. | ||
292 | ARG is passed to `backward-kill-word'." | ||
293 | (interactive "P") | ||
294 | (+backward-kill-word-wrapper #'backward-kill-word arg)) | ||
295 | |||
296 | ;;; ... and advice | ||
297 | |||
298 | ;; Indent the region after a yank. | ||
299 | (defun +yank@indent (&rest _) | ||
300 | "Indent the current region." | ||
301 | (indent-region (min (point) (mark)) (max (point) (mark)))) | ||
302 | ;; (advice-add #'yank :after #'+yank@indent) | ||
303 | ;; (advice-add #'yank-pop :after #'+yank@indent) | ||
304 | |||
305 | ;; https://old.reddit.com/r/emacs/comments/y92y4b/tramp_users_slowness_got_you_down_check/it3a35r/ | ||
306 | (defun +vc-off-when-remote () | ||
307 | (when (file-remote-p (buffer-file-name)) | ||
308 | (setq-local vc-handled-backends nil))) | ||
309 | |||
310 | |||
311 | ;;; Extra functions | ||
312 | |||
313 | (defun +save-some-buffers-p () | ||
314 | "Predicate for `save-some-buffers-default-predicate'. | ||
315 | It returns nil with remote files and those without attached files." | ||
316 | (and (buffer-file-name) | ||
317 | (not (file-remote-p (buffer-file-name))))) | ||
318 | |||
319 | ;; https://www.wwwtech.de/articles/2013/may/emacs:-jump-to-matching-paren-beginning-of-block | ||
320 | (defun +goto-matching-paren (&optional arg) | ||
321 | "Go to the matching paren, similar to vi's %." | ||
322 | (interactive "p") | ||
323 | (or arg (setf arg 1)) | ||
324 | (cond | ||
325 | ;; Check for "outside of bracket" positions | ||
326 | ((looking-at "[\[\(\{]") (forward-sexp arg)) | ||
327 | ((looking-back "[\]\)\}]" 1) (backward-sexp arg)) | ||
328 | ;; Otherwise, move from inside the bracket | ||
329 | ((looking-at "[\]\)\}]") (forward-char) (backward-sexp arg)) | ||
330 | ((looking-back "[\[\(\{]" 1) (backward-char) (forward-sexp arg)) | ||
331 | (t (up-list arg t t)))) | ||
332 | |||
333 | (defun +delete-window-or-bury-buffer () | ||
334 | "Delete the current window, or bury the current buffer. | ||
335 | If the current window is the only window, bury the buffer." | ||
336 | (interactive) | ||
337 | (condition-case e | ||
338 | (delete-window) | ||
339 | (t (bury-buffer)))) | ||
340 | |||
341 | |||
342 | ;;; Required libraries | ||
343 | |||
344 | (when (require 'abbrev nil :noerror) | ||
345 | (setq-default abbrev-file-name (sync/ "abbrev.el") | ||
346 | save-abbrevs 'silent)) | ||
347 | |||
348 | (when (require 'autorevert nil :noerror) | ||
349 | (setq-default global-auto-revert-non-file-buffers t | ||
350 | auto-revert-verbose nil) | ||
351 | (global-auto-revert-mode +1)) | ||
352 | |||
353 | (when (require 'uniquify nil :noerror) | ||
354 | (setq-default uniquify-buffer-name-style 'forward | ||
355 | uniquify-separator path-separator | ||
356 | uniquify-after-kill-buffer-p t | ||
357 | uniquify-ignore-buffers-re "^\\*")) | ||
358 | |||
359 | (when (require 'goto-addr) | ||
360 | (if (fboundp 'global-goto-address-mode) | ||
361 | (global-goto-address-mode +1) | ||
362 | (add-hook 'after-change-major-mode-hook 'goto-address-mode))) | ||
363 | |||
364 | (when (require 'recentf nil :noerror) | ||
365 | (setq-default recentf-save-file (.etc "recentf.el") | ||
366 | recentf-max-menu-items 100 | ||
367 | recentf-max-saved-items nil | ||
368 | recentf-auto-cleanup 'mode) | ||
369 | (add-to-list 'recentf-exclude .etc) | ||
370 | (recentf-mode +1)) | ||
371 | |||
372 | (when (require 'savehist nil :noerror) | ||
373 | (setq-default history-length t | ||
374 | history-delete-duplicates t | ||
375 | history-autosave-interval 60 | ||
376 | savehist-file (.etc "savehist.el") | ||
377 | ;; Other variables --- don't truncate any of these. | ||
378 | ;; `add-to-history' uses the values of these variables unless | ||
379 | ;; they're nil, in which case it falls back to `history-length'. | ||
380 | kill-ring-max 100 | ||
381 | mark-ring-max 100 | ||
382 | global-mark-ring-max 100 | ||
383 | regexp-search-ring-max 100 | ||
384 | search-ring-max 100 | ||
385 | kmacro-ring-max 100 | ||
386 | eww-history-limit 100) | ||
387 | (dolist (var '(extended-command-history | ||
388 | global-mark-ring | ||
389 | mark-ring | ||
390 | kill-ring | ||
391 | kmacro-ring | ||
392 | regexp-search-ring | ||
393 | search-ring)) | ||
394 | (add-to-list 'savehist-additional-variables var)) | ||
395 | (savehist-mode +1)) | ||
396 | |||
397 | (when (require 'saveplace nil :noerror) | ||
398 | (setq-default save-place-file (.etc "places.el") | ||
399 | save-place-forget-unreadable-files (eq system-type 'gnu/linux)) | ||
400 | (save-place-mode +1)) | ||
401 | |||
402 | ;; (when (require 'tramp) | ||
403 | ;; ;; thanks Irreal! https://irreal.org/blog/?p=895 | ||
404 | ;; (add-to-list 'tramp-default-proxies-alist | ||
405 | ;; '(nil "\\`root\\'" "/ssh:%h:")) | ||
406 | ;; (add-to-list 'tramp-default-proxies-alist | ||
407 | ;; '((regexp-quote (system-name)) nil nil))) | ||
408 | |||
409 | |||
410 | ;;; Newer features | ||
411 | ;; These aren't in older version of Emacs, but they're so nice. | ||
412 | |||
413 | (when (fboundp 'repeat-mode) | ||
414 | (setq-default repeat-exit-key "g" | ||
415 | repeat-exit-timeout 5) | ||
416 | (repeat-mode +1)) | ||
417 | |||
418 | (when (fboundp 'pixel-scroll-precision-mode) | ||
419 | (pixel-scroll-precision-mode +1)) | ||
420 | |||
421 | (provide '+emacs) | ||
422 | ;;; +emacs.el ends here | ||