about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--README.md764
1 files changed, 393 insertions, 371 deletions
diff --git a/README.md b/README.md index b839b12..adf04f8 100644 --- a/README.md +++ b/README.md
@@ -1,3 +1,5 @@
1
2
1# Basics 3# Basics
2 4
3 5
@@ -11,7 +13,7 @@
11## About me 13## About me
12 14
13 (setq user-full-name "Case Duckworth" 15 (setq user-full-name "Case Duckworth"
14 user-mail-address "acdw@acdw.net") 16 user-mail-address "acdw@acdw.net")
15 17
16 18
17## Correct `exec-path` 19## Correct `exec-path`
@@ -20,25 +22,25 @@ Straight depends on Git, so I need to tell Emacs where different paths are.
20 22
21 (let ((win-downloads "c:/Users/aduckworth/Downloads")) 23 (let ((win-downloads "c:/Users/aduckworth/Downloads"))
22 (dolist (path (list 24 (dolist (path (list
23 ;; Linux 25 ;; Linux
24 (expand-file-name "bin" 26 (expand-file-name "bin"
25 user-emacs-directory) 27 user-emacs-directory)
26 (expand-file-name "~/bin") 28 (expand-file-name "~/bin")
27 (expand-file-name "~/.local/bin") 29 (expand-file-name "~/.local/bin")
28 (expand-file-name "~/Scripts") 30 (expand-file-name "~/Scripts")
29 ;; Windows 31 ;; Windows
30 (expand-file-name "emacs/bin" 32 (expand-file-name "emacs/bin"
31 win-downloads) 33 win-downloads)
32 (expand-file-name "m/usr/bin" 34 (expand-file-name "m/usr/bin"
33 win-downloads) 35 win-downloads)
34 (expand-file-name "m/mingw64/bin" 36 (expand-file-name "m/mingw64/bin"
35 win-downloads) 37 win-downloads)
36 (expand-file-name "PortableGit/bin" 38 (expand-file-name "PortableGit/bin"
37 win-downloads) 39 win-downloads)
38 (expand-file-name "PortableGit/usr/bin" 40 (expand-file-name "PortableGit/usr/bin"
39 win-downloads))) 41 win-downloads)))
40 (when (file-exists-p path) 42 (when (file-exists-p path)
41 (add-to-list 'exec-path path)))) 43 (add-to-list 'exec-path path))))
42 44
43 45
44## Package management 46## Package management
@@ -53,21 +55,21 @@ bootstrap code from straight's repo in a function.
53 "Bootstrap straight.el." 55 "Bootstrap straight.el."
54 (defvar bootstrap-version) 56 (defvar bootstrap-version)
55 (let ((bootstrap-file 57 (let ((bootstrap-file
56 (expand-file-name 58 (expand-file-name
57 "straight/repos/straight.el/bootstrap.el" 59 "straight/repos/straight.el/bootstrap.el"
58 user-emacs-directory)) 60 user-emacs-directory))
59 (bootstrap-version 5)) 61 (bootstrap-version 5))
60 (unless (file-exists-p bootstrap-file) 62 (unless (file-exists-p bootstrap-file)
61 (with-current-buffer 63 (with-current-buffer
62 (url-retrieve-synchronously 64 (url-retrieve-synchronously
63 (concat 65 (concat
64 "https://raw.githubusercontent.com/" 66 "https://raw.githubusercontent.com/"
65 "raxod502/straight.el/" 67 "raxod502/straight.el/"
66 "develop/install.el") 68 "develop/install.el")
67 'silent 'inhibit-cookies) 69 'silent 'inhibit-cookies)
68 (goto-char (point-max)) 70 (goto-char (point-max))
69 (eval-print-last-sexp))) 71 (eval-print-last-sexp)))
70 (load bootstrap-file nil 'nomessage))) 72 (load bootstrap-file nil 'nomessage)))
71 73
72Now, I'll *try* running it regular-style, ignoring the errors. If it 74Now, I'll *try* running it regular-style, ignoring the errors. If it
73doesn't work, I'll call git directly and clone the repo myself. 75doesn't work, I'll call git directly and clone the repo myself.
@@ -75,11 +77,11 @@ doesn't work, I'll call git directly and clone the repo myself.
75 (unless (ignore-errors (acdw/bootstrap-straight)) 77 (unless (ignore-errors (acdw/bootstrap-straight))
76 (message "%s" "Straight.el didn't bootstrap correctly. Cloning directly...") 78 (message "%s" "Straight.el didn't bootstrap correctly. Cloning directly...")
77 (call-process "git" nil 79 (call-process "git" nil
78 (get-buffer-create "*bootstrap-straight-messages*") nil 80 (get-buffer-create "*bootstrap-straight-messages*") nil
79 "clone" 81 "clone"
80 "https://github.com/raxod502/straight.el" 82 "https://github.com/raxod502/straight.el"
81 (expand-file-name "straight/repos/straight.el" 83 (expand-file-name "straight/repos/straight.el"
82 user-emacs-directory)) 84 user-emacs-directory))
83 (acdw/bootstrap-straight)) 85 (acdw/bootstrap-straight))
84 86
85 87
@@ -91,9 +93,9 @@ doesn't work, I'll call git directly and clone the repo myself.
91 (defmacro cuss (var val &optional docstring) 93 (defmacro cuss (var val &optional docstring)
92 "Basically, `:custom' from `use-package', but without `use-package'." 94 "Basically, `:custom' from `use-package', but without `use-package'."
93 (declare (doc-string 3) 95 (declare (doc-string 3)
94 (indent 2)) 96 (indent 2))
95 `(funcall (or (get ',var 'custom-set) #'set-default) 97 `(funcall (or (get ',var 'custom-set) #'set-default)
96 ',var ,val)) 98 ',var ,val))
97 99
98 100
99### Emulate use-package’s `:custom-face`, but better 101### Emulate use-package’s `:custom-face`, but better
@@ -120,7 +122,7 @@ This comes in handy when I want to garbage collect, say, or save recent files.
120 (defun acdw/when-unfocused (func &rest args) 122 (defun acdw/when-unfocused (func &rest args)
121 "Run FUNC with ARGS only if all frames are out of focus." 123 "Run FUNC with ARGS only if all frames are out of focus."
122 (if (seq-every-p #'null (mapcar #'frame-focus-state (frame-list))) 124 (if (seq-every-p #'null (mapcar #'frame-focus-state (frame-list)))
123 (apply func args))) 125 (apply func args)))
124 126
125 127
126### Determine where I am 128### Determine where I am
@@ -131,13 +133,13 @@ I use Emacs at home, with Linux, and at work, with Windows.
131 "Only do COMMANDS when at work." 133 "Only do COMMANDS when at work."
132 (declare (indent defun)) 134 (declare (indent defun))
133 `(when (memq system-type '(ms-dos windows-nt)) 135 `(when (memq system-type '(ms-dos windows-nt))
134 ,@commands)) 136 ,@commands))
135 137
136 (defmacro at-home (&rest commands) 138 (defmacro at-home (&rest commands)
137 "Only do COMMANDS when at home." 139 "Only do COMMANDS when at home."
138 (declare (indent defun)) 140 (declare (indent defun))
139 `(when (memq system-type '(gnu gnu/linux gnu/kfreebsd)) 141 `(when (memq system-type '(gnu gnu/linux gnu/kfreebsd))
140 ,@commands)) 142 ,@commands))
141 143
142 144
143## Clean `.emacs.d` 145## Clean `.emacs.d`
@@ -198,7 +200,7 @@ I use Emacs at home, with Linux, and at work, with Windows.
198from [EmacsWiki](https://www.emacswiki.org/emacs/AlarmBell#h5o-3). 200from [EmacsWiki](https://www.emacswiki.org/emacs/AlarmBell#h5o-3).
199 201
200 (setq visible-bell nil 202 (setq visible-bell nil
201 ring-bell-function 'flash-mode-line) 203 ring-bell-function 'flash-mode-line)
202 204
203 (defun flash-mode-line () 205 (defun flash-mode-line ()
204 (invert-face 'mode-line) 206 (invert-face 'mode-line)
@@ -221,14 +223,14 @@ from [EmacsWiki](https://www.emacswiki.org/emacs/AlarmBell#h5o-3).
221#### Minibuffer 223#### Minibuffer
222 224
223 (cuss minibuffer-prompt-properties 225 (cuss minibuffer-prompt-properties
224 '(read-only t cursor-intangible t face minibuffer-prompt) 226 '(read-only t cursor-intangible t face minibuffer-prompt)
225 "Keep the cursor away from the minibuffer prompt.") 227 "Keep the cursor away from the minibuffer prompt.")
226 228
227 229
228#### Tabs 230#### Tabs
229 231
230 (cuss tab-bar-tab-name-function 232 (cuss tab-bar-tab-name-function
231 #'tab-bar-tab-name-current-with-count 233 #'tab-bar-tab-name-current-with-count
232 "Show the tab name as the name of the current buffer, plus a 234 "Show the tab name as the name of the current buffer, plus a
233 count of the windows in the tab.") 235 count of the windows in the tab.")
234 236
@@ -291,16 +293,16 @@ from [EmacsWiki](https://www.emacswiki.org/emacs/AlarmBell#h5o-3).
291 Prompt only if there are unsaved changes." 293 Prompt only if there are unsaved changes."
292 (interactive "P") 294 (interactive "P")
293 (pcase (or (car prefix) 0) 295 (pcase (or (car prefix) 0)
294 ;; C-x k ⇒ Kill current buffer & window 296 ;; C-x k ⇒ Kill current buffer & window
295 (0 (kill-current-buffer) 297 (0 (kill-current-buffer)
296 (unless (one-window-p) (delete-window))) 298 (unless (one-window-p) (delete-window)))
297 ;; C-u C-x k ⇒ Kill OTHER window and its buffer 299 ;; C-u C-x k ⇒ Kill OTHER window and its buffer
298 (4 (other-window 1) 300 (4 (other-window 1)
299 (kill-current-buffer) 301 (kill-current-buffer)
300 (unless (one-window-p) (delete-window))) 302 (unless (one-window-p) (delete-window)))
301 ;; C-u C-u C-x C-k ⇒ Kill all other buffers and windows 303 ;; C-u C-u C-x C-k ⇒ Kill all other buffers and windows
302 (16 (mapc 'kill-buffer (delq (current-buffer) (buffer-list))) 304 (16 (mapc 'kill-buffer (delq (current-buffer) (buffer-list)))
303 (delete-other-windows)))) 305 (delete-other-windows))))
304 306
305 (define-key ctl-x-map "k" #'acdw/kill-a-buffer) 307 (define-key ctl-x-map "k" #'acdw/kill-a-buffer)
306 308
@@ -314,9 +316,9 @@ from [EmacsWiki](https://www.emacswiki.org/emacs/AlarmBell#h5o-3).
314 316
315 (defun immortal-scratch () 317 (defun immortal-scratch ()
316 (if (eq (current-buffer) (get-buffer "*scratch*")) 318 (if (eq (current-buffer) (get-buffer "*scratch*"))
317 (progn (bury-buffer) 319 (progn (bury-buffer)
318 nil) 320 nil)
319 t)) 321 t))
320 322
321 (add-hook 'kill-buffer-query-functions 'immortal-scratch) 323 (add-hook 'kill-buffer-query-functions 'immortal-scratch)
322 324
@@ -343,10 +345,10 @@ helper function, though, to add things to the whitelist.
343 (defun rm/whitelist-add (regexp) 345 (defun rm/whitelist-add (regexp)
344 "Add a REGEXP to the whitelist for `rich-minority'." 346 "Add a REGEXP to the whitelist for `rich-minority'."
345 (if (listp 'rm--whitelist-regexps) 347 (if (listp 'rm--whitelist-regexps)
346 (add-to-list 'rm--whitelist-regexps regexp) 348 (add-to-list 'rm--whitelist-regexps regexp)
347 (setq rm--whitelist-regexps `(,regexp))) 349 (setq rm--whitelist-regexps `(,regexp)))
348 (setq rm-whitelist 350 (setq rm-whitelist
349 (mapconcat 'identity rm--whitelist-regexps "\\|"))) 351 (mapconcat 'identity rm--whitelist-regexps "\\|")))
350 352
351 (straight-use-package 'rich-minority) 353 (straight-use-package 'rich-minority)
352 354
@@ -371,8 +373,8 @@ helper function, though, to add things to the whitelist.
371 (cuss modus-themes-org-blocks 'grayscale 373 (cuss modus-themes-org-blocks 'grayscale
372 "Show org-blocks with a grayscale background.") 374 "Show org-blocks with a grayscale background.")
373 (cuss modus-themes-headings 375 (cuss modus-themes-headings
374 '((1 . line) 376 '((1 . line)
375 (t . t)) 377 (t . t))
376 "Highlight top headings with `line' style, and others by default.") 378 "Highlight top headings with `line' style, and others by default.")
377 379
378 (cuss modus-themes-scale-headings t 380 (cuss modus-themes-scale-headings t
@@ -393,15 +395,15 @@ helper function, though, to add things to the whitelist.
393 395
394 ;; sunrise 396 ;; sunrise
395 (run-at-time (nth 1 (split-string (sunrise-sunset))) 397 (run-at-time (nth 1 (split-string (sunrise-sunset)))
396 (* 60 60 24) 398 (* 60 60 24)
397 (lambda () 399 (lambda ()
398 (modus-themes-load-operandi))) 400 (modus-themes-load-operandi)))
399 401
400 ;; sunset 402 ;; sunset
401 (run-at-time (nth 4 (split-string (sunrise-sunset))) 403 (run-at-time (nth 4 (split-string (sunrise-sunset)))
402 (* 60 60 24) 404 (* 60 60 24)
403 (lambda () 405 (lambda ()
404 (modus-themes-load-vivendi))) 406 (modus-themes-load-vivendi)))
405 407
406 408
407### Fonts 409### Fonts
@@ -411,13 +413,13 @@ helper function, though, to add things to the whitelist.
411 413
412 (defun set-face-from-alternatives (face fonts) 414 (defun set-face-from-alternatives (face fonts)
413 (catch :return 415 (catch :return
414 (dolist (font fonts) 416 (dolist (font fonts)
415 (when (find-font (font-spec :family (car font))) 417 (when (find-font (font-spec :family (car font)))
416 (apply #'set-face-attribute `(,face 418 (apply #'set-face-attribute `(,face
417 nil 419 nil
418 :family (car font) 420 :family (car font)
419 ,@(cdr font))) 421 ,@(cdr font)))
420 (throw :return font))))) 422 (throw :return font)))))
421 423
422 (defun acdw/setup-fonts () 424 (defun acdw/setup-fonts ()
423 "Setup fonts. This has to happen after the frame is setup for 425 "Setup fonts. This has to happen after the frame is setup for
@@ -425,24 +427,24 @@ helper function, though, to add things to the whitelist.
425 removes itself from that hook." 427 removes itself from that hook."
426 (interactive) 428 (interactive)
427 (when (display-graphic-p) 429 (when (display-graphic-p)
428 (set-face-from-alternatives 'default 430 (set-face-from-alternatives 'default
429 '(("Input Mono" 431 '(("Input Mono"
430 :height 105) 432 :height 105)
431 ("Go Mono" 433 ("Go Mono"
432 :height 100) 434 :height 100)
433 ("Consolas" 435 ("Consolas"
434 :height 100))) 436 :height 100)))
435 437
436 (set-face-from-alternatives 'fixed-pitch 438 (set-face-from-alternatives 'fixed-pitch
437 '(("Input Mono") 439 '(("Input Mono")
438 ("Go Mono") 440 ("Go Mono")
439 ("Consolas"))) 441 ("Consolas")))
440 442
441 (set-face-from-alternatives 'variable-pitch 443 (set-face-from-alternatives 'variable-pitch
442 '(("Input Serif") 444 '(("Input Serif")
443 ("Georgia"))) 445 ("Georgia")))
444 446
445 (remove-function after-focus-change-function #'acdw/setup-fonts))) 447 (remove-function after-focus-change-function #'acdw/setup-fonts)))
446 448
447 (add-function :before after-focus-change-function #'acdw/setup-fonts) 449 (add-function :before after-focus-change-function #'acdw/setup-fonts)
448 450
@@ -450,7 +452,7 @@ helper function, though, to add things to the whitelist.
450#### Custom faces 452#### Custom faces
451 453
452 (cussface '(font-lock-comment-face 454 (cussface '(font-lock-comment-face
453 ((t (:inherit (custom-comment italic variable-pitch)))))) 455 ((t (:inherit (custom-comment italic variable-pitch))))))
454 456
455 457
456#### Line spacing 458#### Line spacing
@@ -519,13 +521,13 @@ helper function, though, to add things to the whitelist.
519#### Consult 521#### Consult
520 522
521 (straight-use-package '(consult 523 (straight-use-package '(consult
522 :host github 524 :host github
523 :repo "minad/consult")) 525 :repo "minad/consult"))
524 (require 'consult) 526 (require 'consult)
525 527
526 (straight-use-package '(consult-selectrum 528 (straight-use-package '(consult-selectrum
527 :host github 529 :host github
528 :repo "minad/consult")) 530 :repo "minad/consult"))
529 (require 'consult-selectrum) 531 (require 'consult-selectrum)
530 532
531 (with-eval-after-load 'consult 533 (with-eval-after-load 'consult
@@ -552,13 +554,13 @@ helper function, though, to add things to the whitelist.
552#### Marginalia 554#### Marginalia
553 555
554 (straight-use-package '(marginalia 556 (straight-use-package '(marginalia
555 :host github 557 :host github
556 :repo "minad/marginalia" 558 :repo "minad/marginalia"
557 :branch "main")) 559 :branch "main"))
558 560
559 (cuss marginalia-annotators 561 (cuss marginalia-annotators
560 '(marginalia-annotators-heavy 562 '(marginalia-annotators-heavy
561 marginalia-annotators-light)) 563 marginalia-annotators-light))
562 564
563 (marginalia-mode +1) 565 (marginalia-mode +1)
564 566
@@ -576,10 +578,10 @@ helper function, though, to add things to the whitelist.
576 (defun dotfiles--gc-on-last-frame-out-of-focus () 578 (defun dotfiles--gc-on-last-frame-out-of-focus ()
577 "GC if all frames are inactive." 579 "GC if all frames are inactive."
578 (if (seq-every-p #'null (mapcar #'frame-focus-state (frame-list))) 580 (if (seq-every-p #'null (mapcar #'frame-focus-state (frame-list)))
579 (garbage-collect))) 581 (garbage-collect)))
580 582
581 (add-function :after after-focus-change-function 583 (add-function :after after-focus-change-function
582 #'dotfiles--gc-on-last-frame-out-of-focus) 584 #'dotfiles--gc-on-last-frame-out-of-focus)
583 585
584 586
585## Keyboard 587## Keyboard
@@ -594,11 +596,11 @@ helper function, though, to add things to the whitelist.
594 596
595 (defvar acdw/map 597 (defvar acdw/map
596 (let ((map (make-sparse-keymap)) 598 (let ((map (make-sparse-keymap))
597 (c-z (global-key-binding "\C-z"))) 599 (c-z (global-key-binding "\C-z")))
598 (global-unset-key "\C-z") 600 (global-unset-key "\C-z")
599 (define-key global-map "\C-z" map) 601 (define-key global-map "\C-z" map)
600 (define-key map "\C-z" c-z) 602 (define-key map "\C-z" c-z)
601 map)) 603 map))
602 604
603 (run-hooks 'acdw/map-defined-hook) 605 (run-hooks 'acdw/map-defined-hook)
604 606
@@ -622,7 +624,7 @@ from [u/TheFrenchPoulp](https://www.reddit.com/r/emacs/comments/km9by4/weekly_ti
622 "Like `mwheel-scroll' but preserve screen position. 624 "Like `mwheel-scroll' but preserve screen position.
623 See `scroll-preserve-screen-position'." 625 See `scroll-preserve-screen-position'."
624 (let ((scroll-preserve-screen-position :always)) 626 (let ((scroll-preserve-screen-position :always))
625 (apply original arguments))) 627 (apply original arguments)))
626 628
627 629
628## Persistence 630## Persistence
@@ -633,9 +635,9 @@ from [u/TheFrenchPoulp](https://www.reddit.com/r/emacs/comments/km9by4/weekly_ti
633 (require 'savehist) 635 (require 'savehist)
634 636
635 (cuss savehist-additional-variables 637 (cuss savehist-additional-variables
636 '(kill-ring 638 '(kill-ring
637 search-ring 639 search-ring
638 regexp-search-ring) 640 regexp-search-ring)
639 "Other variables to save alongside the minibuffer history.") 641 "Other variables to save alongside the minibuffer history.")
640 642
641 (cuss history-length t 643 (cuss history-length t
@@ -677,15 +679,15 @@ from [u/TheFrenchPoulp](https://www.reddit.com/r/emacs/comments/km9by4/weekly_ti
677 "Save `recentf-file' when out of focus, but only if we haven't 679 "Save `recentf-file' when out of focus, but only if we haven't
678 in five minutes." 680 in five minutes."
679 (defvar recentf-last-save (time-convert nil 'integer) 681 (defvar recentf-last-save (time-convert nil 'integer)
680 "How long it's been since we last saved the recentf list.") 682 "How long it's been since we last saved the recentf list.")
681 683
682 (when (> (time-convert (time-since recentf-last-save) 'integer) 684 (when (> (time-convert (time-since recentf-last-save) 'integer)
683 (* 60 5)) 685 (* 60 5))
684 (setq recentf-last-save (time-convert nil 'integer)) 686 (setq recentf-last-save (time-convert nil 'integer))
685 (acdw/when-unfocused #'recentf-save-list))) 687 (acdw/when-unfocused #'recentf-save-list)))
686 688
687 (add-function :after after-focus-change-function 689 (add-function :after after-focus-change-function
688 #'acdw/maybe-save-recentf) 690 #'acdw/maybe-save-recentf)
689 691
690 692
691## Undo 693## Undo
@@ -700,14 +702,14 @@ from [u/TheFrenchPoulp](https://www.reddit.com/r/emacs/comments/km9by4/weekly_ti
700 (require 'undo-fu-session) 702 (require 'undo-fu-session)
701 703
702 (cuss undo-fu-session-incompatible-files 704 (cuss undo-fu-session-incompatible-files
703 '("/COMMIT_EDITMSG\\'" 705 '("/COMMIT_EDITMSG\\'"
704 "/git-rebase-todo\\'") 706 "/git-rebase-todo\\'")
705 "A list of files that are incompatible with the concept of undo sessions.") 707 "A list of files that are incompatible with the concept of undo sessions.")
706 708
707 (with-eval-after-load 'no-littering 709 (with-eval-after-load 'no-littering
708 (let ((dir (no-littering-expand-var-file-name "undos"))) 710 (let ((dir (no-littering-expand-var-file-name "undos")))
709 (make-directory dir 'parents) 711 (make-directory dir 'parents)
710 (cuss undo-fu-session-directory dir))) 712 (cuss undo-fu-session-directory dir)))
711 713
712 (global-undo-fu-session-mode +1) 714 (global-undo-fu-session-mode +1)
713 715
@@ -735,8 +737,8 @@ from [Emacs Wiki](https://www.emacswiki.org/emacs/EndOfLineTips).
735 (defun ewiki/no-junk-please-were-unixish () 737 (defun ewiki/no-junk-please-were-unixish ()
736 "Convert line endings to UNIX, dammit." 738 "Convert line endings to UNIX, dammit."
737 (let ((coding-str (symbol-name buffer-file-coding-system))) 739 (let ((coding-str (symbol-name buffer-file-coding-system)))
738 (when (string-match "-\\(?:dos\\|mac\\)$" coding-str) 740 (when (string-match "-\\(?:dos\\|mac\\)$" coding-str)
739 (set-buffer-file-coding-system 'unix)))) 741 (set-buffer-file-coding-system 'unix))))
740 742
741I add it to the `find-file-hook` *and* `before-save-hook` because I 743I add it to the `find-file-hook` *and* `before-save-hook` because I
742don't want to ever work with anything other than UNIX line endings 744don't want to ever work with anything other than UNIX line endings
@@ -756,20 +758,35 @@ UNIX line endings, so I don't want to hear it.
756 758
757 (with-eval-after-load 'no-littering 759 (with-eval-after-load 'no-littering
758 (let ((dir (no-littering-expand-var-file-name "backup"))) 760 (let ((dir (no-littering-expand-var-file-name "backup")))
759 (make-directory dir 'parents) 761 (make-directory dir 'parents)
760 (cuss backup-directory-alist 762 (cuss backup-directory-alist
761 `((".*" . ,dir))))) 763 `((".*" . ,dir)))))
762 764
763 765
764### Auto-saves 766### Auto-saves
765 767
766 (with-eval-after-load 'no-littering 768 (with-eval-after-load 'no-littering
767 (let ((dir (no-littering-expand-var-file-name "autosaves"))) 769 (let ((dir (no-littering-expand-var-file-name "autosaves")))
768 (make-directory dir 'parents) 770 (make-directory dir 'parents)
769 (cuss auto-save-file-name-transforms 771 (cuss auto-save-file-name-transforms
770 `((".*" ,dir t)))) 772 `((".*" ,dir t))))
771 773
772 (auto-save-visited-mode +1)) 774 (auto-save-mode +1))
775
776
777### Super-save
778
779Because I like *overkill*, or at least … over-*saving*.
780
781 (straight-use-package 'super-save)
782
783 (cuss super-save-remote-files nil
784 "Don't super-save remote files.")
785
786 (cuss super-save-exclude '(".gpg")
787 "Ignore these files when saving.")
788
789 (super-save-mode +1)
773 790
774 791
775### Auto-revert buffers to files on disk 792### Auto-revert buffers to files on disk
@@ -803,19 +820,19 @@ I’ve pretty much cribbed this from [recentf-remove-sudo-tramp-prefix](https://
803 "Remove sudo from PATH." 820 "Remove sudo from PATH."
804 (require 'tramp) 821 (require 'tramp)
805 (if (tramp-tramp-file-p path) 822 (if (tramp-tramp-file-p path)
806 (let ((tx (tramp-dissect-file-name path))) 823 (let ((tx (tramp-dissect-file-name path)))
807 (if (string-equal "sudo" (tramp-file-name-method tx)) 824 (if (string-equal "sudo" (tramp-file-name-method tx))
808 (tramp-file-name-localname tx) 825 (tramp-file-name-localname tx)
809 path)) 826 path))
810 path)) 827 path))
811 828
812 (defun recentf-remove-sudo-tramp-prefix-from-recentf-list () 829 (defun recentf-remove-sudo-tramp-prefix-from-recentf-list ()
813 (require 'recentf) 830 (require 'recentf)
814 (setq recentf-list 831 (setq recentf-list
815 (mapcar #'recentf-remove-sudo-tramp-prefix recentf-list))) 832 (mapcar #'recentf-remove-sudo-tramp-prefix recentf-list)))
816 833
817 (advice-add 'recentf-cleanup 834 (advice-add 'recentf-cleanup
818 :before #'recentf-remove-sudo-tramp-prefix-from-recentf-list) 835 :before #'recentf-remove-sudo-tramp-prefix-from-recentf-list)
819 836
820 837
821## Text editing 838## Text editing
@@ -867,7 +884,7 @@ I’ve pretty much cribbed this from [recentf-remove-sudo-tramp-prefix](https://
867 (global-anzu-mode +1) 884 (global-anzu-mode +1)
868 885
869 (cuss anzu-replace-to-string-separator " → " 886 (cuss anzu-replace-to-string-separator " → "
870 "What to separate the search from the replacement.") 887 "What to separate the search from the replacement.")
871 888
872 (global-set-key [remap query-replace] #'anzu-query-replace) 889 (global-set-key [remap query-replace] #'anzu-query-replace)
873 (global-set-key [remap query-replace-regexp] #'anzu-query-replace-regexp) 890 (global-set-key [remap query-replace-regexp] #'anzu-query-replace-regexp)
@@ -896,12 +913,16 @@ I’ve pretty much cribbed this from [recentf-remove-sudo-tramp-prefix](https://
896### Whitespace 913### Whitespace
897 914
898 (cuss whitespace-style 915 (cuss whitespace-style
899 '(empty ;; remove blank lines at the beginning and end of buffers 916 '(empty ;; remove blank lines at the beginning and end of buffers
900 indentation ;; clean up indentation 917 indentation ;; clean up indentation
901 space-before-tab ;; fix mixed spaces and tabs 918 space-before-tab ;; fix mixed spaces and tabs
902 space-after-tab)) 919 space-after-tab))
903 920
904 (add-hook 'before-save-hook #'whitespace-cleanup) 921 (defun acdw/whitespace-cleanup-maybe ()
922 "Only cleanup whitespace when out-of-focus."
923 (acdw/when-unfocused #'whitespace-cleanup))
924
925 (add-hook 'before-save-hook #'acdw/whitespace-cleanup-maybe)
905 926
906 927
907# Programming 928# Programming
@@ -956,9 +977,9 @@ I’ve pretty much cribbed this from [recentf-remove-sudo-tramp-prefix](https://
956 977
957 (with-eval-after-load 'company 978 (with-eval-after-load 'company
958 (define-key company-active-map (kbd "C-n") 979 (define-key company-active-map (kbd "C-n")
959 (lambda () (interactive) (company-complete-common-or-cycle +1))) 980 (lambda () (interactive) (company-complete-common-or-cycle +1)))
960 (define-key company-active-map (kbd "C-p") 981 (define-key company-active-map (kbd "C-p")
961 (lambda () (interactive) (company-complete-common-or-cycle -1)))) 982 (lambda () (interactive) (company-complete-common-or-cycle -1))))
962 983
963 984
964### Give it a frame and better help 985### Give it a frame and better help
@@ -992,7 +1013,7 @@ I’ve pretty much cribbed this from [recentf-remove-sudo-tramp-prefix](https://
992 (straight-use-package 'ini-mode) 1013 (straight-use-package 'ini-mode)
993 1014
994 (add-to-list 'auto-mode-alist 1015 (add-to-list 'auto-mode-alist
995 '("\\.ini\\'" . ini-mode)) 1016 '("\\.ini\\'" . ini-mode))
996 1017
997 1018
998# Writing 1019# Writing
@@ -1007,20 +1028,20 @@ This has to be done *before* loading the package. It's included in `visual-fill
1007 1028
1008 (dolist (margin '(right-margin left-margin)) 1029 (dolist (margin '(right-margin left-margin))
1009 (dolist (button '(mouse-1 mouse-2 mouse-3)) 1030 (dolist (button '(mouse-1 mouse-2 mouse-3))
1010 (global-set-key (vector margin button) 1031 (global-set-key (vector margin button)
1011 (global-key-binding (vector button))))) 1032 (global-key-binding (vector button)))))
1012 1033
1013 (mouse-wheel-mode +1) 1034 (mouse-wheel-mode +1)
1014 1035
1015 (when (bound-and-true-p mouse-wheel-mode) 1036 (when (bound-and-true-p mouse-wheel-mode)
1016 (dolist (margin '(right-margin left-margin)) 1037 (dolist (margin '(right-margin left-margin))
1017 (dolist (event '(mouse-wheel-down-event 1038 (dolist (event '(mouse-wheel-down-event
1018 mouse-wheel-up-event 1039 mouse-wheel-up-event
1019 wheel-down 1040 wheel-down
1020 wheel-up 1041 wheel-up
1021 mouse-4 1042 mouse-4
1022 mouse-5)) 1043 mouse-5))
1023 (global-set-key (vector margin event) #'mwheel-scroll)))) 1044 (global-set-key (vector margin event) #'mwheel-scroll))))
1024 1045
1025 1046
1026### Load the package 1047### Load the package
@@ -1034,7 +1055,7 @@ This has to be done *before* loading the package. It's included in `visual-fill
1034 "Width of fill-column, and thus, visual-fill-column.") 1055 "Width of fill-column, and thus, visual-fill-column.")
1035 1056
1036 (advice-add 'text-scale-adjust 1057 (advice-add 'text-scale-adjust
1037 :after #'visual-fill-column-adjust) 1058 :after #'visual-fill-column-adjust)
1038 1059
1039 (global-visual-fill-column-mode +1) 1060 (global-visual-fill-column-mode +1)
1040 1061
@@ -1056,7 +1077,7 @@ This has to be done *before* loading the package. It's included in `visual-fill
1056 ;; Disable `typo-mode' when inside an Org source block 1077 ;; Disable `typo-mode' when inside an Org source block
1057 (with-eval-after-load 'typo 1078 (with-eval-after-load 'typo
1058 (add-to-list 'typo-disable-electricity-functions 1079 (add-to-list 'typo-disable-electricity-functions
1059 #'org-in-src-block-p)) 1080 #'org-in-src-block-p))
1060 1081
1061 1082
1062### Show `^L` as a horizontal line 1083### Show `^L` as a horizontal line
@@ -1109,7 +1130,7 @@ I’ve put org mode under Applications, as opposed to Writing, because it’s m
1109### Basics 1130### Basics
1110 1131
1111 (straight-use-package '(org 1132 (straight-use-package '(org
1112 :repo "https://code.orgmode.org/bzg/org-mode.git")) 1133 :repo "https://code.orgmode.org/bzg/org-mode.git"))
1113 1134
1114 (with-eval-after-load 'org 1135 (with-eval-after-load 'org
1115 (require 'org-tempo) 1136 (require 'org-tempo)
@@ -1145,8 +1166,8 @@ I’ve put org mode under Applications, as opposed to Writing, because it’s m
1145 (cussface 1166 (cussface
1146 '(org-tag 1167 '(org-tag
1147 ((t 1168 ((t
1148 (:height 0.8 :weight normal :slant italic :foreground "grey40" :inherit 1169 (:height 0.8 :weight normal :slant italic :foreground "grey40" :inherit
1149 (variable-pitch)))))) 1170 (variable-pitch))))))
1150 1171
1151 1172
1152#### Prettify 1173#### Prettify
@@ -1154,9 +1175,9 @@ I’ve put org mode under Applications, as opposed to Writing, because it’s m
1154 (defun acdw/org-mode-prettify () 1175 (defun acdw/org-mode-prettify ()
1155 "Prettify `org-mode'." 1176 "Prettify `org-mode'."
1156 (dolist (cell '(("[ ]" . ?□) ("[X]" . ?☑) ("[-]" . ?◐) 1177 (dolist (cell '(("[ ]" . ?□) ("[X]" . ?☑) ("[-]" . ?◐)
1157 ("#+begin_src" . ?✎) ("#+BEGIN_SRC" . ?✎) 1178 ("#+begin_src" . ?✎) ("#+BEGIN_SRC" . ?✎)
1158 ("#+end_src" . ?■) ("#+END_SRC" . ?■))) 1179 ("#+end_src" . ?■) ("#+END_SRC" . ?■)))
1159 (add-to-list 'prettify-symbols-alist cell :append)) 1180 (add-to-list 'prettify-symbols-alist cell :append))
1160 (prettify-symbols-mode +1)) 1181 (prettify-symbols-mode +1))
1161 1182
1162 (add-hook 'org-mode-hook #'acdw/org-mode-prettify) 1183 (add-hook 'org-mode-hook #'acdw/org-mode-prettify)
@@ -1173,8 +1194,8 @@ I’ve put org mode under Applications, as opposed to Writing, because it’s m
1173 ELEMENT should be a list like that returned by `org-element-context'." 1194 ELEMENT should be a list like that returned by `org-element-context'."
1174 ;; MAYBE: Use `org-element-lineage'. 1195 ;; MAYBE: Use `org-element-lineage'.
1175 (when-let* ((parent (org-element-property :parent element))) 1196 (when-let* ((parent (org-element-property :parent element)))
1176 (or (eq type (car parent)) 1197 (or (eq type (car parent))
1177 (unpackaged/org-element-descendant-of type parent)))) 1198 (unpackaged/org-element-descendant-of type parent))))
1178 1199
1179 ;;;###autoload 1200 ;;;###autoload
1180 (defun unpackaged/org-return-dwim (&optional default) 1201 (defun unpackaged/org-return-dwim (&optional default)
@@ -1186,83 +1207,83 @@ I’ve put org mode under Applications, as opposed to Writing, because it’s m
1186 ;; Inspired by John Kitchin: http://kitchingroup.cheme.cmu.edu/blog/2017/04/09/A-better-return-in-org-mode/ 1207 ;; Inspired by John Kitchin: http://kitchingroup.cheme.cmu.edu/blog/2017/04/09/A-better-return-in-org-mode/
1187 (interactive "P") 1208 (interactive "P")
1188 (if default 1209 (if default
1189 (org-return) 1210 (org-return)
1190 (cond 1211 (cond
1191 ;; Act depending on context around point. 1212 ;; Act depending on context around point.
1192 1213
1193 ;; NOTE: I prefer RET to not follow links, but by uncommenting this block, links will be 1214 ;; NOTE: I prefer RET to not follow links, but by uncommenting this block, links will be
1194 ;; followed. 1215 ;; followed.
1195 1216
1196 ;; ((eq 'link (car (org-element-context))) 1217 ;; ((eq 'link (car (org-element-context)))
1197 ;; ;; Link: Open it. 1218 ;; ;; Link: Open it.
1198 ;; (org-open-at-point-global)) 1219 ;; (org-open-at-point-global))
1199 1220
1200 ((org-at-heading-p) 1221 ((org-at-heading-p)
1201 ;; Heading: Move to position after entry content. 1222 ;; Heading: Move to position after entry content.
1202 ;; NOTE: This is probably the most interesting feature of this function. 1223 ;; NOTE: This is probably the most interesting feature of this function.
1203 (let ((heading-start (org-entry-beginning-position))) 1224 (let ((heading-start (org-entry-beginning-position)))
1204 (goto-char (org-entry-end-position)) 1225 (goto-char (org-entry-end-position))
1205 (cond ((and (org-at-heading-p) 1226 (cond ((and (org-at-heading-p)
1206 (= heading-start (org-entry-beginning-position))) 1227 (= heading-start (org-entry-beginning-position)))
1207 ;; Entry ends on its heading; add newline after 1228 ;; Entry ends on its heading; add newline after
1208 (end-of-line) 1229 (end-of-line)
1209 (insert "\n\n")) 1230 (insert "\n\n"))
1210 (t 1231 (t
1211 ;; Entry ends after its heading; back up 1232 ;; Entry ends after its heading; back up
1212 (forward-line -1) 1233 (forward-line -1)
1213 (end-of-line) 1234 (end-of-line)
1214 (when (org-at-heading-p) 1235 (when (org-at-heading-p)
1215 ;; At the same heading 1236 ;; At the same heading
1216 (forward-line) 1237 (forward-line)
1217 (insert "\n") 1238 (insert "\n")
1218 (forward-line -1)) 1239 (forward-line -1))
1219 ;; FIXME: looking-back is supposed to be called with more arguments. 1240 ;; FIXME: looking-back is supposed to be called with more arguments.
1220 (while (not (looking-back (rx (repeat 3 (seq (optional blank) "\n"))) nil)) 1241 (while (not (looking-back (rx (repeat 3 (seq (optional blank) "\n"))) nil))
1221 (insert "\n")) 1242 (insert "\n"))
1222 (forward-line -1))))) 1243 (forward-line -1)))))
1223 1244
1224 ((org-at-item-checkbox-p) 1245 ((org-at-item-checkbox-p)
1225 ;; Checkbox: Insert new item with checkbox. 1246 ;; Checkbox: Insert new item with checkbox.
1226 (org-insert-todo-heading nil)) 1247 (org-insert-todo-heading nil))
1227 1248
1228 ((org-in-item-p) 1249 ((org-in-item-p)
1229 ;; Plain list. Yes, this gets a little complicated... 1250 ;; Plain list. Yes, this gets a little complicated...
1230 (let ((context (org-element-context))) 1251 (let ((context (org-element-context)))
1231 (if (or (eq 'plain-list (car context)) ; First item in list 1252 (if (or (eq 'plain-list (car context)) ; First item in list
1232 (and (eq 'item (car context)) 1253 (and (eq 'item (car context))
1233 (not (eq (org-element-property :contents-begin context) 1254 (not (eq (org-element-property :contents-begin context)
1234 (org-element-property :contents-end context)))) 1255 (org-element-property :contents-end context))))
1235 (unpackaged/org-element-descendant-of 'item context)) ; Element in list item, e.g. a link 1256 (unpackaged/org-element-descendant-of 'item context)) ; Element in list item, e.g. a link
1236 ;; Non-empty item: Add new item. 1257 ;; Non-empty item: Add new item.
1237 (org-insert-item) 1258 (org-insert-item)
1238 ;; Empty item: Close the list. 1259 ;; Empty item: Close the list.
1239 ;; TODO: Do this with org functions rather than operating on the text. Can't seem to find the right function. 1260 ;; TODO: Do this with org functions rather than operating on the text. Can't seem to find the right function.
1240 (delete-region (line-beginning-position) (line-end-position)) 1261 (delete-region (line-beginning-position) (line-end-position))
1241 (insert "\n")))) 1262 (insert "\n"))))
1242 1263
1243 ((when (fboundp 'org-inlinetask-in-task-p) 1264 ((when (fboundp 'org-inlinetask-in-task-p)
1244 (org-inlinetask-in-task-p)) 1265 (org-inlinetask-in-task-p))
1245 ;; Inline task: Don't insert a new heading. 1266 ;; Inline task: Don't insert a new heading.
1246 (org-return)) 1267 (org-return))
1247 1268
1248 ((org-at-table-p) 1269 ((org-at-table-p)
1249 (cond ((save-excursion 1270 (cond ((save-excursion
1250 (beginning-of-line) 1271 (beginning-of-line)
1251 ;; See `org-table-next-field'. 1272 ;; See `org-table-next-field'.
1252 (cl-loop with end = (line-end-position) 1273 (cl-loop with end = (line-end-position)
1253 for cell = (org-element-table-cell-parser) 1274 for cell = (org-element-table-cell-parser)
1254 always (equal (org-element-property :contents-begin cell) 1275 always (equal (org-element-property :contents-begin cell)
1255 (org-element-property :contents-end cell)) 1276 (org-element-property :contents-end cell))
1256 while (re-search-forward "|" end t))) 1277 while (re-search-forward "|" end t)))
1257 ;; Empty row: end the table. 1278 ;; Empty row: end the table.
1258 (delete-region (line-beginning-position) (line-end-position)) 1279 (delete-region (line-beginning-position) (line-end-position))
1259 (org-return)) 1280 (org-return))
1260 (t 1281 (t
1261 ;; Non-empty row: call `org-return'. 1282 ;; Non-empty row: call `org-return'.
1262 (org-return)))) 1283 (org-return))))
1263 (t 1284 (t
1264 ;; All other cases: call `org-return'. 1285 ;; All other cases: call `org-return'.
1265 (org-return))))) 1286 (org-return)))))
1266 1287
1267 (with-eval-after-load 'org 1288 (with-eval-after-load 'org
1268 (define-key org-mode-map (kbd "RET") #'unpackaged/org-return-dwim)) 1289 (define-key org-mode-map (kbd "RET") #'unpackaged/org-return-dwim))
@@ -1279,42 +1300,42 @@ from [unpackaged.el](https://github.com/alphapapa/unpackaged.el#ensure-blank-lin
1279 exist after each headings's drawers." 1300 exist after each headings's drawers."
1280 (interactive "P") 1301 (interactive "P")
1281 (org-map-entries (lambda () 1302 (org-map-entries (lambda ()
1282 (org-with-wide-buffer 1303 (org-with-wide-buffer
1283 ;; `org-map-entries' narrows the buffer, which prevents us 1304 ;; `org-map-entries' narrows the buffer, which prevents us
1284 ;; from seeing newlines before the current heading, so we 1305 ;; from seeing newlines before the current heading, so we
1285 ;; do this part widened. 1306 ;; do this part widened.
1286 (while (not (looking-back "\n\n" nil)) 1307 (while (not (looking-back "\n\n" nil))
1287 ;; Insert blank lines before heading. 1308 ;; Insert blank lines before heading.
1288 (insert "\n"))) 1309 (insert "\n")))
1289 (let ((end (org-entry-end-position))) 1310 (let ((end (org-entry-end-position)))
1290 ;; Insert blank lines before entry content 1311 ;; Insert blank lines before entry content
1291 (forward-line) 1312 (forward-line)
1292 (while (and (org-at-planning-p) 1313 (while (and (org-at-planning-p)
1293 (< (point) (point-max))) 1314 (< (point) (point-max)))
1294 ;; Skip planning lines 1315 ;; Skip planning lines
1295 (forward-line)) 1316 (forward-line))
1296 (while (re-search-forward org-drawer-regexp end t) 1317 (while (re-search-forward org-drawer-regexp end t)
1297 ;; Skip drawers. You might think that `org-at-drawer-p' 1318 ;; Skip drawers. You might think that `org-at-drawer-p'
1298 ;; would suffice, but for some reason it doesn't work 1319 ;; would suffice, but for some reason it doesn't work
1299 ;; correctly when operating on hidden text. This 1320 ;; correctly when operating on hidden text. This
1300 ;; works, taken from `org-agenda-get-some-entry-text'. 1321 ;; works, taken from `org-agenda-get-some-entry-text'.
1301 (re-search-forward "^[ \t]*:END:.*\n?" end t) 1322 (re-search-forward "^[ \t]*:END:.*\n?" end t)
1302 (goto-char (match-end 0))) 1323 (goto-char (match-end 0)))
1303 (unless (or (= (point) (point-max)) 1324 (unless (or (= (point) (point-max))
1304 (org-at-heading-p) 1325 (org-at-heading-p)
1305 (looking-at-p "\n")) 1326 (looking-at-p "\n"))
1306 (insert "\n")))) 1327 (insert "\n"))))
1307 t (if prefix 1328 t (if prefix
1308 nil 1329 nil
1309 'tree))) 1330 'tree)))
1310 1331
1311 1332
1312##### Add a before-save-hook 1333##### Add a before-save-hook
1313 1334
1314 (defun cribbed/org-mode-fix-blank-lines () 1335 (defun cribbed/org-mode-fix-blank-lines ()
1315 (when (eq major-mode 'org-mode) 1336 (when (eq major-mode 'org-mode)
1316 (let ((current-prefix-arg 4)) ; Emulate C-u 1337 (let ((current-prefix-arg 4)) ; Emulate C-u
1317 (call-interactively 'unpackaged/org-fix-blank-lines)))) 1338 (call-interactively 'unpackaged/org-fix-blank-lines))))
1318 1339
1319 (add-hook 'before-save-hook #'cribbed/org-mode-fix-blank-lines) 1340 (add-hook 'before-save-hook #'cribbed/org-mode-fix-blank-lines)
1320 1341
@@ -1322,18 +1343,18 @@ from [unpackaged.el](https://github.com/alphapapa/unpackaged.el#ensure-blank-lin
1322### Org Agenda 1343### Org Agenda
1323 1344
1324 (cuss org-agenda-files 1345 (cuss org-agenda-files
1325 (let ((list)) 1346 (let ((list))
1326 (dolist (file '(;; add more files to this list 1347 (dolist (file '(;; add more files to this list
1327 "home.org" 1348 "home.org"
1328 "work.org") 1349 "work.org")
1329 list) 1350 list)
1330 (push (expand-file-name file org-directory) list)))) 1351 (push (expand-file-name file org-directory) list))))
1331 1352
1332 (define-key acdw/map (kbd "C-a") #'org-agenda) 1353 (define-key acdw/map (kbd "C-a") #'org-agenda)
1333 1354
1334 (cuss org-todo-keywords 1355 (cuss org-todo-keywords
1335 '((sequence "RECUR(r)" "TODO(t)" "|" "DONE(d)") 1356 '((sequence "RECUR(r)" "TODO(t)" "|" "DONE(d)")
1336 (sequence "|" "CANCELLED(c)"))) 1357 (sequence "|" "CANCELLED(c)")))
1337 1358
1338 (cuss org-agenda-skip-scheduled-if-done t) 1359 (cuss org-agenda-skip-scheduled-if-done t)
1339 (cuss org-agenda-skip-deadline-if-done t) 1360 (cuss org-agenda-skip-deadline-if-done t)
@@ -1345,8 +1366,8 @@ from [unpackaged.el](https://github.com/alphapapa/unpackaged.el#ensure-blank-lin
1345### Include Org links in source code 1366### Include Org links in source code
1346 1367
1347 (straight-use-package '(org-link-minor-mode 1368 (straight-use-package '(org-link-minor-mode
1348 :host github 1369 :host github
1349 :repo "seanohalpin/org-link-minor-mode")) 1370 :repo "seanohalpin/org-link-minor-mode"))
1350 1371
1351 ;; enable in elisp buffers 1372 ;; enable in elisp buffers
1352 (add-hook 'emacs-lisp-mode-hook #'org-link-minor-mode) 1373 (add-hook 'emacs-lisp-mode-hook #'org-link-minor-mode)
@@ -1362,8 +1383,8 @@ from [unpackaged.el](https://github.com/alphapapa/unpackaged.el#ensure-blank-lin
1362### Git file modes 1383### Git file modes
1363 1384
1364 (dolist (feat '(gitattributes-mode 1385 (dolist (feat '(gitattributes-mode
1365 gitconfig-mode 1386 gitconfig-mode
1366 gitignore-mode)) 1387 gitignore-mode))
1367 (straight-use-package feat) 1388 (straight-use-package feat)
1368 (require feat)) 1389 (require feat))
1369 1390
@@ -1371,8 +1392,8 @@ from [unpackaged.el](https://github.com/alphapapa/unpackaged.el#ensure-blank-lin
1371## Beancount mode 1392## Beancount mode
1372 1393
1373 (straight-use-package '(beancount-mode 1394 (straight-use-package '(beancount-mode
1374 :host github 1395 :host github
1375 :repo "beancount/beancount-mode")) 1396 :repo "beancount/beancount-mode"))
1376 (require 'beancount) 1397 (require 'beancount)
1377 1398
1378 (add-to-list 'auto-mode-alist '("\\.beancount\\'" . beancount-mode)) 1399 (add-to-list 'auto-mode-alist '("\\.beancount\\'" . beancount-mode))
@@ -1434,7 +1455,7 @@ I’m only enabling this at home for now, since it requires building stuff.
1434 (when (executable-find "mu") 1455 (when (executable-find "mu")
1435 1456
1436 (add-to-list 'load-path 1457 (add-to-list 'load-path
1437 "/usr/share/emacs/site-lisp/mu4e") 1458 "/usr/share/emacs/site-lisp/mu4e")
1438 (require 'mu4e) 1459 (require 'mu4e)
1439 1460
1440 (cuss mail-user-agent 'mu4e-user-agent) 1461 (cuss mail-user-agent 'mu4e-user-agent)
@@ -1463,54 +1484,54 @@ I’m only enabling this at home for now, since it requires building stuff.
1463 (cuss smtpmail-smtp-service 465) 1484 (cuss smtpmail-smtp-service 465)
1464 (cuss smtpmail-local-domain "acdw.net") 1485 (cuss smtpmail-local-domain "acdw.net")
1465 (cuss mu4e-compose-signature 1486 (cuss mu4e-compose-signature
1466 "Best,\nCase\n") 1487 "Best,\nCase\n")
1467 1488
1468 (cuss mu4e-completing-read-function 'completing-read) 1489 (cuss mu4e-completing-read-function 'completing-read)
1469 (cuss message-kill-buffer-on-exit t) 1490 (cuss message-kill-buffer-on-exit t)
1470 (cuss mu4e-confirm-quit nil) 1491 (cuss mu4e-confirm-quit nil)
1471 1492
1472 (cuss mu4e-bookmarks 1493 (cuss mu4e-bookmarks
1473 '((:name "Unread" 1494 '((:name "Unread"
1474 :query 1495 :query
1475 "flag:unread AND NOT flag:trashed AND NOT maildir:/Spam" 1496 "flag:unread AND NOT flag:trashed AND NOT maildir:/Spam"
1476 :key ?u) 1497 :key ?u)
1477 (:name "Today" 1498 (:name "Today"
1478 :query "date:today..now and not and not flag:trashed maildir:/Spam" 1499 :query "date:today..now and not and not flag:trashed maildir:/Spam"
1479 :key ?t) 1500 :key ?t)
1480 (:name "This week" 1501 (:name "This week"
1481 :query "date:7d..now and not maildir:/Spam and not flag:trashed" 1502 :query "date:7d..now and not maildir:/Spam and not flag:trashed"
1482 :hide-unread t 1503 :hide-unread t
1483 :key ?w))) 1504 :key ?w)))
1484 1505
1485 (cuss mu4e-headers-fields 1506 (cuss mu4e-headers-fields
1486 '((:human-date . 12) 1507 '((:human-date . 12)
1487 (:flags . 6) 1508 (:flags . 6)
1488 (:mailing-list . 10) 1509 (:mailing-list . 10)
1489 (:from-or-to . 22) 1510 (:from-or-to . 22)
1490 (:thread-subject))) 1511 (:thread-subject)))
1491 1512
1492 (cuss mu4e-maildir-shortcuts 1513 (cuss mu4e-maildir-shortcuts
1493 `(("/INBOX" . ?i) 1514 `(("/INBOX" . ?i)
1494 (,mu4e-refile-folder . ?a) 1515 (,mu4e-refile-folder . ?a)
1495 (,mu4e-sent-folder . ?s) 1516 (,mu4e-sent-folder . ?s)
1496 (,mu4e-drafts-folder . ?d) 1517 (,mu4e-drafts-folder . ?d)
1497 (,mu4e-trash-folder . ?t))) 1518 (,mu4e-trash-folder . ?t)))
1498 1519
1499 (defun acdw/setup-mu4e-headers-mode () 1520 (defun acdw/setup-mu4e-headers-mode ()
1500 (visual-line-mode -1)) 1521 (visual-line-mode -1))
1501 1522
1502 (add-hook 'mu4e-headers-mode #'acdw/setup-mu4e-headers-mode) 1523 (add-hook 'mu4e-headers-mode #'acdw/setup-mu4e-headers-mode)
1503 1524
1504 (defun acdw/setup-mu4e-view-mode () 1525 (defun acdw/setup-mu4e-view-mode ()
1505 (visual-fill-column-mode +1)) 1526 (visual-fill-column-mode +1))
1506 1527
1507 (add-hook 'mu4e-view-mode-hook #'acdw/setup-mu4e-view-mode) 1528 (add-hook 'mu4e-view-mode-hook #'acdw/setup-mu4e-view-mode)
1508 1529
1509 (cuss mu4e-get-mail-command (cond ((executable-find "mbsync") 1530 (cuss mu4e-get-mail-command (cond ((executable-find "mbsync")
1510 "mbsync -a")) 1531 "mbsync -a"))
1511 "The command to update mail with.") 1532 "The command to update mail with.")
1512 (cuss mu4e-update-interval 300 1533 (cuss mu4e-update-interval 300
1513 "Update automatically every 5 minutes.") 1534 "Update automatically every 5 minutes.")
1514 (mu4e +1)) 1535 (mu4e +1))
1515 1536
1516 1537
@@ -1520,8 +1541,8 @@ I’m only enabling this at home for now, since it requires building stuff.
1520 "If `mu4e' is around, run it, or tell the user it isn't." 1541 "If `mu4e' is around, run it, or tell the user it isn't."
1521 (interactive) 1542 (interactive)
1522 (if (featurep 'mu4e) 1543 (if (featurep 'mu4e)
1523 (mu4e) 1544 (mu4e)
1524 (warn "Mu4e isn't available :/."))) 1545 (warn "Mu4e isn't available :/.")))
1525 1546
1526 (define-key acdw/map "m" #'acdw/mu4e-or-warn) 1547 (define-key acdw/map "m" #'acdw/mu4e-or-warn)
1527 1548
@@ -1543,27 +1564,27 @@ I’m only enabling this at home for now, since it requires building stuff.
1543### Elpher 1564### Elpher
1544 1565
1545 (straight-use-package '(elpher 1566 (straight-use-package '(elpher
1546 :repo "git://thelambdalab.xyz/elpher.git")) 1567 :repo "git://thelambdalab.xyz/elpher.git"))
1547 1568
1548 (with-eval-after-load 'no-littering 1569 (with-eval-after-load 'no-littering
1549 (cuss elpher-certificate-directory 1570 (cuss elpher-certificate-directory
1550 (no-littering-expand-var-file-name "elpher-certificates/"))) 1571 (no-littering-expand-var-file-name "elpher-certificates/")))
1551 1572
1552 (cuss elpher-ipv4-always t) 1573 (cuss elpher-ipv4-always t)
1553 1574
1554 (cussface '(elpher-gemini-heading1 1575 (cussface '(elpher-gemini-heading1
1555 ((t (:inherit (modus-theme-heading-1 variable-pitch)))))) 1576 ((t (:inherit (modus-theme-heading-1 variable-pitch))))))
1556 (cussface '(elpher-gemini-heading2 1577 (cussface '(elpher-gemini-heading2
1557 ((t (:inherit (modus-theme-heading-2 variable-pitch)))))) 1578 ((t (:inherit (modus-theme-heading-2 variable-pitch))))))
1558 (cussface '(elpher-gemini-heading3 1579 (cussface '(elpher-gemini-heading3
1559 ((t (:inherit (modus-theme-heading-3 variable-pitch)))))) 1580 ((t (:inherit (modus-theme-heading-3 variable-pitch))))))
1560 1581
1561 (defun elpher:eww-browse-url (original url &optional new-window) 1582 (defun elpher:eww-browse-url (original url &optional new-window)
1562 "Handle gemini/gopher links with eww." 1583 "Handle gemini/gopher links with eww."
1563 (cond ((string-match-p "\\`\\(gemini\\|gopher\\)://" url) 1584 (cond ((string-match-p "\\`\\(gemini\\|gopher\\)://" url)
1564 (require 'elpher) 1585 (require 'elpher)
1565 (elpher-go url)) 1586 (elpher-go url))
1566 (t (funcall original url new-window)))) 1587 (t (funcall original url new-window))))
1567 (advice-add 'eww-browse-url :around 'elpher:eww-browse-url) 1588 (advice-add 'eww-browse-url :around 'elpher:eww-browse-url)
1568 1589
1569 (with-eval-after-load 'elpher 1590 (with-eval-after-load 'elpher
@@ -1581,17 +1602,17 @@ I’m only enabling this at home for now, since it requires building stuff.
1581### Gemini-mode 1602### Gemini-mode
1582 1603
1583 (straight-use-package '(gemini-mode 1604 (straight-use-package '(gemini-mode
1584 :repo "https://git.carcosa.net/jmcbray/gemini.el.git")) 1605 :repo "https://git.carcosa.net/jmcbray/gemini.el.git"))
1585 1606
1586 (add-to-list 'auto-mode-alist 1607 (add-to-list 'auto-mode-alist
1587 '("\\.\\(gemini\\|gmi\\)\\'" . gemini-mode)) 1608 '("\\.\\(gemini\\|gmi\\)\\'" . gemini-mode))
1588 1609
1589 (cussface '(gemini-heading-face-1 1610 (cussface '(gemini-heading-face-1
1590 ((t (:inherit (elpher-gemini-heading1)))))) 1611 ((t (:inherit (elpher-gemini-heading1))))))
1591 (cussface '(gemini-heading-face2 1612 (cussface '(gemini-heading-face2
1592 ((t (:inherit (elpher-gemini-heading2)))))) 1613 ((t (:inherit (elpher-gemini-heading2))))))
1593 (cussface '(gemini-heading-face3 1614 (cussface '(gemini-heading-face3
1594 ((t (:inherit (elpher-gemini-heading3)))))) 1615 ((t (:inherit (elpher-gemini-heading3))))))
1595 1616
1596 (add-hook 'gemini-mode-hook #'acdw/setup-smolweb) 1617 (add-hook 'gemini-mode-hook #'acdw/setup-smolweb)
1597 1618
@@ -1599,7 +1620,7 @@ I’m only enabling this at home for now, since it requires building stuff.
1599### Gemini-write 1620### Gemini-write
1600 1621
1601 (straight-use-package '(gemini-write 1622 (straight-use-package '(gemini-write
1602 :repo "https://alexschroeder.ch/cgit/gemini-write")) 1623 :repo "https://alexschroeder.ch/cgit/gemini-write"))
1603 (require 'gemini-write) 1624 (require 'gemini-write)
1604 1625
1605 ;; TODO : add tokens ... somehow 1626 ;; TODO : add tokens ... somehow
@@ -1618,20 +1639,20 @@ I’m only enabling this at home for now, since it requires building stuff.
1618 (setq load-prefer-newer t) 1639 (setq load-prefer-newer t)
1619 1640
1620 (let* (;; Speed up init 1641 (let* (;; Speed up init
1621 (gc-cons-threshold most-positive-fixnum) 1642 (gc-cons-threshold most-positive-fixnum)
1622 (file-name-handler-alist nil) 1643 (file-name-handler-alist nil)
1623 ;; Config file names 1644 ;; Config file names
1624 (conf (expand-file-name "config" 1645 (conf (expand-file-name "config"
1625 user-emacs-directory)) 1646 user-emacs-directory))
1626 (conf-el (concat conf ".el")) 1647 (conf-el (concat conf ".el"))
1627 (conf-org (concat conf ".org"))) 1648 (conf-org (concat conf ".org")))
1628 (unless (and (file-newer-than-file-p conf-el conf-org) 1649 (unless (and (file-newer-than-file-p conf-el conf-org)
1629 (load conf 'no-error)) 1650 (load conf 'no-error))
1630 ;; A plain require here just loads the older `org' in Emacs' install dir. We 1651 ;; A plain require here just loads the older `org' in Emacs' install dir. We
1631 ;; need to add the newer one to the `load-path', hopefully that's all. 1652 ;; need to add the newer one to the `load-path', hopefully that's all.
1632 (add-to-list 'load-path (expand-file-name "straight/build/org/")) 1653 (add-to-list 'load-path (expand-file-name "straight/build/org/"))
1633 (require 'org) 1654 (require 'org)
1634 (org-babel-load-file conf-org))) 1655 (org-babel-load-file conf-org)))
1635 1656
1636 1657
1637### early-init.el 1658### early-init.el
@@ -1654,29 +1675,29 @@ I’m only enabling this at home for now, since it requires building stuff.
1654 Then, load the byte-compilations unless passed with a prefix argument." 1675 Then, load the byte-compilations unless passed with a prefix argument."
1655 (interactive "P") 1676 (interactive "P")
1656 (let ((config (expand-file-name "config.org" user-emacs-directory))) 1677 (let ((config (expand-file-name "config.org" user-emacs-directory)))
1657 (save-mark-and-excursion 1678 (save-mark-and-excursion
1658 (with-current-buffer (find-file config) 1679 (with-current-buffer (find-file config)
1659 (let ((prog-mode-hook nil)) 1680 (let ((prog-mode-hook nil))
1660 ;; generate the readme 1681 ;; generate the readme
1661 (when (file-newer-than-file-p config (expand-file-name 1682 (when (file-newer-than-file-p config (expand-file-name
1662 "README.md" 1683 "README.md"
1663 user-emacs-directory)) 1684 user-emacs-directory))
1664 (message "%s" "Exporting README.md...") 1685 (message "%s" "Exporting README.md...")
1665 (require 'ox-md) 1686 (require 'ox-md)
1666 (with-demoted-errors "Problem exporting README.md: %S" 1687 (with-demoted-errors "Problem exporting README.md: %S"
1667 (org-md-export-to-markdown))) 1688 (org-md-export-to-markdown)))
1668 ;; tangle config.org 1689 ;; tangle config.org
1669 (when (file-newer-than-file-p config (expand-file-name 1690 (when (file-newer-than-file-p config (expand-file-name
1670 "config.el" 1691 "config.el"
1671 user-emacs-directory)) 1692 user-emacs-directory))
1672 (message "%s" "Tangling config.org...") 1693 (message "%s" "Tangling config.org...")
1673 (require 'org) 1694 (require 'org)
1674 (let ((inits (org-babel-tangle))) 1695 (let ((inits (org-babel-tangle)))
1675 ;; byte-compile resulting files 1696 ;; byte-compile resulting files
1676 (message "%s" "Byte-compiling...") 1697 (message "%s" "Byte-compiling...")
1677 (dolist (f inits) 1698 (dolist (f inits)
1678 (when (string-match "\\.el\\'" f) 1699 (when (string-match "\\.el\\'" f)
1679 (byte-compile-file f (not disable-load))))))))))) 1700 (byte-compile-file f (not disable-load)))))))))))
1680 1701
1681 1702
1682## Ancillary scripts 1703## Ancillary scripts
@@ -1692,8 +1713,8 @@ installing with either `ln -s bin/emacsdc $HOME/.local/bin/`, or
1692adding `$HOME/.local/bin` to your `$PATH`. 1713adding `$HOME/.local/bin` to your `$PATH`.
1693 1714
1694 if ! emacsclient -nc "$@" 2>/dev/null; then 1715 if ! emacsclient -nc "$@" 2>/dev/null; then
1695 emacs --daemon 1716 emacs --daemon
1696 emacsclient -nc "$@" 1717 emacsclient -nc "$@"
1697 fi 1718 fi
1698 1719
1699 1720
@@ -1746,3 +1767,4 @@ It's highly likely that the WTFPL is completely incompatible with the
1746GPL, for what should be fairly obvious reasons. To that, I say: 1767GPL, for what should be fairly obvious reasons. To that, I say:
1747 1768
1748**SUE ME, RMS!** 1769**SUE ME, RMS!**
1770