summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--init.el1725
-rw-r--r--lisp/acdw.el34
2 files changed, 996 insertions, 763 deletions
diff --git a/init.el b/init.el index 4a538f1..8503809 100644 --- a/init.el +++ b/init.el
@@ -20,10 +20,50 @@
20 20
21;; NOTE that some of the names in `setup' forms are arbitrary. 21;; NOTE that some of the names in `setup' forms are arbitrary.
22 22
23(setup (:straight (0x0 23(setup (:require auth-source)
24 :host gitlab 24 (:option auth-sources '("~/.authinfo" "~/.authinfo.gpg")))
25 :repo "willvaughn/emacs-0x0")) 25
26 (:option 0x0-default-server 'ttm)) 26(setup (:require gforth)
27 (:autoload forth-mode
28 forth-block-mode)
29 (add-to-list 'auto-mode-alist '("\\.fs\\'" . forth-mode))
30 (add-to-list 'auto-mode-alist '("\\.fb\\'" . forth-block-mode)))
31
32(setup (:require goto-addr)
33 (if (fboundp #'global-goto-address-mode)
34 (global-goto-address-mode)
35 (add-hook 'after-change-major-mode-hook #'goto-address-mode)))
36
37(setup (:require recentf)
38 (:option recentf-save-file (acdw/dir "recentf.el")
39 recentf-max-menu-items 100
40 recentf-max-saved-items nil
41 recentf-auto-cleanup 'mode
42 (append recentf-exclude) (acdw/dir))
43
44 (:advise dired-rename-file :after #'rjs/recentf-rename-notify)
45
46 (recentf-mode +1))
47
48(setup (:require savehist)
49 (:option history-length t
50 history-delete-duplicates t
51 savehist-autosave-interval 60
52 savehist-file (acdw/dir "savehist.el"))
53
54 (dolist (var '(extended-command-history
55 global-mark-ring
56 kill-ring
57 regexp-search-ring
58 search-ring
59 mark-ring))
60 (:option (append savehist-additional-variables) var))
61
62 (savehist-mode +1))
63
64(setup (:require server)
65 (unless (server-running-p)
66 (server-start)))
27 67
28(setup Info 68(setup Info
29 (:hook #'variable-pitch-mode 69 (:hook #'variable-pitch-mode
@@ -51,79 +91,45 @@
51 (defun acdw/sort-setups () 91 (defun acdw/sort-setups ()
52 "Sort `setup' forms in the current buffer. 92 "Sort `setup' forms in the current buffer.
53Actually sorts all forms, but based on the logic of `setup'. 93Actually sorts all forms, but based on the logic of `setup'.
54AKA, DO NOT USE THIS FUNCTION!!!" 94In short, DO NOT USE THIS FUNCTION!!!"
55 (save-excursion 95 (save-excursion
56 (sort-sexps (point-min) (point-max) 96 (sort-sexps
57 (lambda (sexp) 97 (point-min) (point-max)
58 (let ((name (cadr sexp))) 98 (lambda (sexp)
59 (symbol-name (if (listp name) ; this is /terrible/! 99 (format "%S" (cadr sexp)))
60 (if (keywordp (car name)) 100 (lambda (s1 s2) ; oh god, this is worse.
61 (let ((feature (cadr name))) 101 (let* ((s1 (cdr s1)) (s2 (cdr s2)) ; for the strings themselves
62 (if (listp feature) 102 (s1-require (string-match ":require" s1))
63 (car feature) 103 (s2-require (string-match ":require" s2))
64 feature)) 104 (s1-straight (string-match ":straight" s1))
65 (car name)) 105 (s2-straight (string-match ":straight" s2))
66 name)))))))) 106 (s1-bare (not (or s1-require s1-straight)))
67 107 (s2-bare (not (or s2-require s2-straight))))
68(setup (:straight-if affe 108 (cond
69 (and (or (executable-find "fd") 109 ;; if both are the same, sort regular style
70 (executable-find "find")) 110 ((or (and s1-require s2-require)
71 (executable-find "rg"))) 111 (and s1-bare s2-bare))
72 ;; Keys are bound in `acdw/sensible-grep' and `acdw/sensible-find' 112 (string< s1 s2))
73 (:option affe-regexp-compiler 113 ((and s1-straight s2-straight)
74 (defun affe-orderless-regexp-compiler (input _type) 114 (let* ((r (rx ":straight" (? "-if") (* space) (? "(")))
75 (setq input (orderless-pattern-compiler input)) 115 (s1 (replace-regexp-in-string r "" s1))
76 (cons input (lambda (str) (orderless--highlight input str)))))) 116 (s2 (replace-regexp-in-string r "" s2)))
77 117 (message "'%S' '%S'" s1 s2)
78(setup (:straight-if ahk-mode 118 (string< s1 s2)))
79 (acdw/system :work))) 119 ;; requires should go first
80 120 ((and s1-require (not s2-require)) t)
81(setup (:straight alert) 121 ((and (not s1-require) s2-require) nil)
82 (:option alert-default-style (acdw/system 122 ;; straights should go last
83 (:home 'libnotify) 123 ((and s1-straight (not s2-straight)) nil)
84 (_ 'message)))) 124 ((and (not s1-straight) s2-straight) t)
85 125 ;; else, just sort em.
86(setup (:straight (apheleia 126 (t (string< s1 s2)))))))))
87 :host github
88 :repo "raxod502/apheleia"))
89
90 (apheleia-global-mode +1)
91
92 ;; Use a dumb formatter on modes that `apheleia' doesn't work for.
93 (add-hook 'before-save-hook
94 (defun before-save@dumb-auto-format ()
95 (setq stupid-modes '(makefile-mode
96 org-mode))
97 ;; If there's no apheleia formatter for the mode, just indent the
98 ;; buffer.
99 (unless (or (apply #'derived-mode-p stupid-modes)
100 (and (fboundp 'apheleia--get-formatter-command)
101 (apheleia--get-formatter-command)))
102 (indent-region (point-min) (point-max))))))
103
104(setup (:straight async)
105 (dired-async-mode +1)
106
107 (:with-feature dired
108 (:hook (defun dired@disable-dired-async-mode-line ()
109 (autoload 'dired-async--modeline-mode "dired-async" nil t)
110 (dired-async--modeline-mode -1)))))
111
112(setup (:require auth-source)
113 (:option auth-sources '("~/.authinfo" "~/.authinfo.gpg")))
114 127
115(setup autorevert 128(setup autorevert
116 (:option global-auto-revert-non-file-buffers t 129 (:option global-auto-revert-non-file-buffers t
117 auto-revert-verbose nil) 130 auto-revert-verbose nil)
118 (global-auto-revert-mode +1)) 131 (global-auto-revert-mode +1))
119 132
120(setup (:straight avy)
121 (:global "C-'" #'avy-goto-char-timer
122 "C-c C-j" #'avy-resume)
123
124 (:with-feature isearch
125 (:bind "C-'" #'avy-isearch)))
126
127(setup browse-url 133(setup browse-url
128 (:require acdw-browse-url) 134 (:require acdw-browse-url)
129 135
@@ -338,104 +344,6 @@ AKA, DO NOT USE THIS FUNCTION!!!"
338 344
339 (:global "M-/" #'hippie-expand)) 345 (:global "M-/" #'hippie-expand))
340 346
341(setup (:straight (consult
342 :host github
343 :repo "minad/consult"))
344
345 (:require acdw-consult)
346 (:autoload consult-register-preview)
347
348 ;; Bindings
349 (:global
350 ;; C-c bindings (`mode-specific-map')
351 ;; I don't use any of these right now.
352 ;; "C-c h" #'consult-history
353 ;; "C-c m" #'consult-mode-command
354 ;; "C-c b" #'consult-bookmark
355 ;; "C-c k" #'consult-kmacro
356 ;; C-x bindings (`ctl-x-map')
357 "C-x M-:" #'consult-complex-command
358 "C-x b" #'consult-buffer
359 "C-x 4 b" #'consult-buffer-other-window
360 "C-x 5 b" #'consult-buffer-other-frame
361 ;; Custom M-# bindings for fast register access
362 "M-#" #'consult-register-load
363 "M-'" #'consult-register-store
364 "C-M-#" #'consult-register
365 ;; M-g bindings (`goto-map')
366 "M-g e" #'consult-compile-error
367 "M-g g" #'consult-goto-line
368 "M-g M-g" #'consult-goto-line
369 "M-g o" #'consult-outline
370 "M-g m" #'consult-mark
371 "M-g k" #'consult-global-mark
372 "M-g i" #'consult-imenu
373 "M-g I" #'consult-project-imenu
374 ;; M-s bindings (`search-map')
375 "M-s g" #'acdw-consult/sensible-grep
376 "M-s f" #'acdw-consult/sensible-find
377 "M-s l" #'consult-line
378 "M-s m" #'consult-multi-occur
379 "M-s k" #'consult-keep-lines
380 "M-s u" #'consult-focus-lines
381 ;; Other bindings
382 "M-y" #'consult-yank-pop
383 "<help> a" #'consult-apropos
384 ;; Isearch integration
385 "M-s e" #'consult-isearch)
386
387 (:with-map isearch-mode-map
388 (:bind "M-e" #'consult-isearch
389 "M-s e" #'consult-isearch
390 "M-s l" #'consult-line))
391
392 (consult-history-to-modes ((minibuffer-local-map . nil)
393 (shell-mode-map . shell-mode-hook)
394 (term-mode-map . term-mode-hook)
395 (term-raw-map . term-mode-hook)
396 (comint-mode-map . comint-mode-hook)
397 (sly-mrepl-mode-map . sly-mrepl-hook)))
398
399 (:option register-preview-delay 0
400 register-preview-function #'consult-register-format
401 xref-show-xrefs-function #'consult-xref
402 xref-show-definitions-function #'consult-xref
403 consult-project-root-function #'vc-root-dir
404 completion-in-region-function #'acdw-consult/complete-in-region
405 completion-cycle-threshold 3
406 consult-preview-key (kbd "M-.")
407 tab-always-indent 'complete)
408
409 (:advise register-preview :override #'consult-register-window)
410
411 ;; Completing-read-multple
412 (if (fboundp #'consult-completing-read-multiple)
413 (:advise completing-read-multple :override
414 #'consult-completing-read-multiple)
415 (:advise completing-read-multiple :filter-args
416 (defun crm-indicator (args)
417 (cons (concat "[CRM] " (car args)) (cdr args)))))
418
419 (with-eval-after-load 'orderless
420 (:option consult--regexp-compiler
421 #'consult--orderless-regexp-compiler))
422
423 (with-eval-after-loads (vertico consult)
424 (:with-map consult-crm-map
425 (:bind "RET" (defun +vertico-crm-exit ()
426 (interactive)
427 (run-at-time 0 nil #'vertico-exit)
428 (funcall #'vertico-exit))
429 "TAB" #'vertico-exit))))
430
431(setup (:straight crux)
432 (:global "C-o" #'crux-smart-open-line
433 "M-o" #'crux-smart-open-line-above
434 "C-M-\\" #'crux-cleanup-buffer-or-region
435 "C-x 4 t" #'crux-transpose-windows)
436
437 (crux-reopen-as-root-mode +1))
438
439(setup cursor 347(setup cursor
440 (:option cursor-type 'bar 348 (:option cursor-type 'bar
441 cursor-in-non-selected-windows 'hollow 349 cursor-in-non-selected-windows 'hollow
@@ -489,50 +397,6 @@ AKA, DO NOT USE THIS FUNCTION!!!"
489(setup debugger 397(setup debugger
490 (:hook visual-line-mode)) 398 (:hook visual-line-mode))
491 399
492(setup (:straight-if (define-repeat-map
493 :host nil
494 :repo "https://tildegit.org/acdw/define-repeat-map.el")
495 (acdw/system :home))
496
497 (defun acdw/other-window-or-switch-buffer-backward ()
498 (interactive)
499 (setq repeat-map 'other-window-repeat-map)
500 (acdw/other-window-or-switch-buffer -1))
501
502 (define-repeat-map other-window
503 ("o" acdw/other-window-or-switch-buffer
504 "O" acdw/other-window-or-switch-buffer-backward))
505
506 (define-repeat-map case
507 ("c" capitalize-word
508 "u" upcase-dwim
509 "l" downcase-dwim)
510 (:continue "f" forward-word
511 "b" backward-word)
512 (:enter capitalize-dwim
513 upcase-dwim
514 downcase-dwim))
515
516 (define-repeat-map page-navigation
517 ("]" forward-page
518 "[" backward-page))
519
520 (define-repeat-map windmove
521 (;; moving
522 "<left>" windmove-left
523 "<right>" windmove-right
524 "<up>" windmove-up
525 "<down>" windmove-down
526 ;; swapping
527 "<S-left>" windmove-swap-states-left
528 "<S-right>" windmove-swap-states-right
529 "<S-up>" windmove-swap-states-up
530 "<S-down>" windmove-swap-states-down))
531
532 (define-repeat-map winner-mode
533 ("/" winner-undo
534 "?" winner-redo)))
535
536(setup dired 400(setup dired
537 (:also-load dired-x) 401 (:also-load dired-x)
538 (:straight dired-subtree 402 (:straight dired-subtree
@@ -650,46 +514,6 @@ AKA, DO NOT USE THIS FUNCTION!!!"
650 (:option eldoc-idle-delay 0.1 514 (:option eldoc-idle-delay 0.1
651 eldoc-echo-area-use-multiline-p nil)) 515 eldoc-echo-area-use-multiline-p nil))
652 516
653(setup (:straight (electric-cursor
654 :host github
655 :repo "duckwork/electric-cursor"))
656 (electric-cursor-mode +1))
657
658(setup (:straight elfeed
659 elfeed-protocol)
660 (:option elfeed-use-curl t
661 elfeed-feeds `(("fever+https://acdw@mf.acdw.net"
662 :api-url "https://mf.acdw.net/fever/"
663 :password ,(acdw/make-password-fetcher
664 :host "mf.acdw.net"))))
665
666 (elfeed-protocol-enable)
667 (:advise elfeed :after
668 (defun elfeed@protocol-update (&rest _)
669 (elfeed-search-fetch nil)))
670
671 (:face message-header-subject
672 ((t (:height 1.5))))
673
674 (:with-mode elfeed-show-mode
675 (:hook #'reading-mode)
676
677 ;; see https://irreal.org/blog/?p=8885
678 (:bind "SPC" (defun elfeed-scroll-up-command (&optional arg)
679 "Scroll up or go to next feed item in Elfeed"
680 (interactive "^P")
681 (let ((scroll-error-top-bottom nil))
682 (condition-case-unless-debug nil
683 (scroll-up-command arg)
684 (error (elfeed-show-next)))))
685 "S-SPC" (defun elfeed-scroll-down-command (&optional arg)
686 "Scroll up or go to next feed item in Elfeed"
687 (interactive "^P")
688 (let ((scroll-error-top-bottom nil))
689 (condition-case-unless-debug nil
690 (scroll-down-command arg)
691 (error (elfeed-show-prev))))))))
692
693(setup elisp-mode 517(setup elisp-mode
694 (:with-mode emacs-lisp-mode ;; -_- 518 (:with-mode emacs-lisp-mode ;; -_-
695 (:option eval-expression-print-length nil 519 (:option eval-expression-print-length nil
@@ -723,35 +547,6 @@ AKA, DO NOT USE THIS FUNCTION!!!"
723 "C-c C-k" #'acdw/eval-region-or-buffer 547 "C-c C-k" #'acdw/eval-region-or-buffer
724 "C-c C-z" #'ielm))) 548 "C-c C-z" #'ielm)))
725 549
726(setup (:straight elisp-slime-nav)
727 (:hook-into emacs-lisp-mode
728 ielm-mode))
729
730(setup (:straight (elpher
731 :host nil
732 :repo "git://thelambdalab.xyz/elpher.git"))
733 (:option elpher-ipv4-always t
734 elpher-certificate-directory (acdw/dir "elpher/")
735 elpher-gemini-max-fill-width fill-column)
736
737 (:bind "n" #'elpher-next-link
738 "p" #'elpher-prev-link
739 "o" #'elpher-follow-current-link
740 "G" #'elpher-go-current)
741
742 (:hook #'reading-mode)
743
744 (:autoload (elpher-bookmarks :interactive t)
745 (elpher-go :interactive t))
746
747 ;; Make `eww' gemini/gopher aware. From Emacswiki.
748 ;; (define-advice eww-browse-url (:around (fn url &rest args) gemini-elpher)
749 ;; (cond ((string-match-p "\\`\\(gemini\\|gopher\\)://" url)
750 ;; (require 'elpher)
751 ;; (elpher-go url))
752 ;; (t (apply fn url args))))
753 )
754
755(setup emacs 550(setup emacs
756 ;; "Et cetera" settings 551 ;; "Et cetera" settings
757 ;; This should stay as /minimal/ as possible. Anything that can go somewhere 552 ;; This should stay as /minimal/ as possible. Anything that can go somewhere
@@ -816,29 +611,6 @@ AKA, DO NOT USE THIS FUNCTION!!!"
816 (unless (bound-and-true-p edit-server-frame-p) 611 (unless (bound-and-true-p edit-server-frame-p)
817 (toggle-frame-maximized frame))))) 612 (toggle-frame-maximized frame)))))
818 613
819(setup (:straight embark)
820 (:global "C-." #'embark-act)
821 (:option prefix-help-command #'embark-prefix-help-command
822 (append display-buffer-alist)
823 `(,(rx (seq bos "*Embark Collect "
824 (group (| "Live" "Completions"))
825 "*"))
826 nil
827 (window-parameters (mode-line-format . none)))
828 embark-prompter #'embark-keymap-prompter
829 embark-verbose-indicator-display-action
830 '(display-buffer-at-bottom (window-height . fit-window-to-buffer))
831 embark-action-indicator
832 (lambda (map _target)
833 (which-key--show-keymap "Embark" map nil nil 'no-paging)
834 #'which-key--hide--ignore-command)
835 embark-become-indicator embark-action-indicator)
836
837 (with-eval-after-loads (embark consult)
838 (:straight embark-consult)
839 (add-hook 'embark-collect-mode-hook
840 #'consult-preview-at-point-mode)))
841
842(setup encoding 614(setup encoding
843 (:option locale-coding-system 'utf-8-unix 615 (:option locale-coding-system 'utf-8-unix
844 coding-system-for-read 'utf-8-unix 616 coding-system-for-read 'utf-8-unix
@@ -863,57 +635,6 @@ AKA, DO NOT USE THIS FUNCTION!!!"
863 (_ (set-selection-coding-system 'utf-8) 635 (_ (set-selection-coding-system 'utf-8)
864 (set-clipboard-coding-system 'utf-8)))) 636 (set-clipboard-coding-system 'utf-8))))
865 637
866(setup (:straight epithet)
867 (dolist (hook '(Info-selection-hook
868 eww-after-render-hook
869 help-mode-hook
870 occur-mode-hook))
871 (add-hook hook #'epithet-rename-buffer)))
872
873;; TODO: look into emms or something related for this
874(setup (:straight-if eradio
875 (executable-find "mpv"))
876 (:option
877 eradio-player '("mpv" "--no-video" "--no-terminal")
878 eradio-channels `(("KLSU" .
879 "http://130.39.238.143:8010/stream.mp3")
880 ("Soma FM Synphaera" .
881 "https://somafm.com/synphaera256.pls")
882 ("SomaFM BAGel Radio" .
883 "https://somafm.com/bagel.pls")
884 ("SomaFM Boot Liquor" .
885 "https://somafm.com/bootliquor320.pls")
886 ("SomaFM Deep Space One" .
887 "https://somafm.com/deepspaceone.pls")
888 ("SomaFM Fluid" .
889 "https://somafm.com/fluid.pls")
890 ("SomaFM Underground 80s" .
891 "https://somafm.com/u80s256.pls")
892 ("WBRH: Jazz & More" .
893 "http://wbrh.streamguys1.com/wbrh-mp3")
894 ("KBRH Blues & Rhythm Hits" .
895 "http://wbrh.streamguys1.com/kbrh-mp3")
896 ("WRKF HD-2" .
897 ,(concat "https://playerservices.streamtheworld.com/"
898 "api/livestream-redirect/WRKFHD2.mp3"))
899 ("WRKF: NPR for the Capital Region" .
900 ,(concat "https://playerservices.streamtheworld.com/"
901 "api/livestream-redirect/WRKFFM.mp3"))
902 ("BadRadio: 24/7 PHONK" .
903 "https://s2.radio.co/s2b2b68744/listen")
904 ("tilderadio" .
905 "https://azuracast.tilderadio.org/radio/8000/radio.ogg")
906 ("vantaradio" .
907 "https://vantaa.black/radio")))
908 (:global "C-c r r" #'eradio-play ; mnemonic: radio
909 "C-c r s" #'eradio-stop ; mnemonic: stop
910 "C-c r p" #'eradio-toggle ; mnemonic: play/pause
911 ))
912
913(setup (:straight eros)
914 (:hook-into emacs-lisp-mode
915 lisp-interaction-mode))
916
917(setup eshell 638(setup eshell
918 (:also-load acdw-eshell 639 (:also-load acdw-eshell
919 em-smart 640 em-smart
@@ -960,19 +681,6 @@ AKA, DO NOT USE THIS FUNCTION!!!"
960 681
961 (:hook #'reading-mode)) 682 (:hook #'reading-mode))
962 683
963(setup (:straight-if exec-path-from-shell
964 (acdw/system :home))
965 (when (daemonp)
966 (exec-path-from-shell-initialize)))
967
968(setup (:straight expand-region)
969 (:global "C-=" #'er/expand-region))
970
971(setup (:straight-if fennel-mode
972 (executable-find "fennel"))
973 (:autoload (fennel-repl :interactive t))
974 (:file-match (rx ".fnl" eos)))
975
976(setup files 684(setup files
977 (:option 685 (:option
978 auto-save-file-name-transforms `((".*" ,(acdw/dir "auto-save/" t) t)) 686 auto-save-file-name-transforms `((".*" ,(acdw/dir "auto-save/" t) t))
@@ -1054,6 +762,886 @@ specific to most general, they are these:
1054(setup flyspell 762(setup flyspell
1055 (:hook-into text-mode)) 763 (:hook-into text-mode))
1056 764
765(setup frames
766 (:option frame-title-format '("%b@"
767 (:eval
768 (or (file-remote-p default-directory 'host)
769 system-name))
770 " %+%* GNU Emacs"
771 (:eval (when (frame-parameter nil 'client)
772 " Client")))
773 window-resize-pixelwise t))
774
775(setup ibuffer
776 (:also-load ibuf-ext)
777 (:option ibuffer-expert t
778 ibuffer-show-empty-filter-groups nil
779 ibuffer-saved-filter-groups
780 '(("default"
781 ("dired" (mode . dired-mode))
782 ("customize" (mode . Custom-mode))
783 ("emacs" (or (name . "^\\*scratch\\*$")
784 (name . "^\\*Messages\\*$")
785 (name . "^\\*Warnings\\*$")
786 (name . "^\\*straight-process\\*$")
787 (name . "^\\*Calendar\\*$")))
788 ("git" (or (name . "^\*magit")
789 (name . "^\magit")))
790 ("help" (or (mode . help-mode)
791 (mode . Info-mode)
792 (mode . helpful-mode)))
793 ("messaging" (or (mode . message-mode)
794 (mode . bbdb-mode)
795 (mode . mail-mode)
796 (mode . gnus-group-mode)
797 (mode . gnus-summary-mode)
798 (mode . gnus-article-mode)
799 (name . "^\\.bbdb$")
800 (name . "^\\.newsrc-dribble")
801 (mode . erc-mode)
802 (mode . circe-server-mode)
803 (mode . circe-channel-mode)))
804 ("shell" (or (mode . eshell-mode)
805 (mode . shell-mode)
806 (mode . vterm-mode)))
807 ("web" (or (mode . elpher-mode)
808 (mode . gemini-mode)
809 (mode . eww-mode))))))
810
811 (:global "C-x C-b" #'ibuffer)
812
813 (:hook (defun ibuffer@filter-to-default ()
814 (ibuffer-switch-to-saved-filter-groups "default"))))
815
816(setup ielm
817 (:hook #'turn-on-eldoc-mode))
818
819(setup imenu
820 (:option imenu-auto-rescan t))
821
822(setup isearch
823 (:option search-default-mode t))
824
825(setup lines
826 (:option fill-column 79
827 word-wrap t
828 truncate-lines nil)
829
830 (global-display-fill-column-indicator-mode +1)
831 (global-so-long-mode +1)
832
833 (add-hook 'visual-line-mode-hook
834 (defun acdw/disable-fill-column-indicator ()
835 (display-fill-column-indicator-mode
836 (if visual-line-mode -1 +1))))
837
838 ;; `acdw/kill-line-and-join-advice' cribs from `crux-kill-and-join-forward'.
839 ;; I can't simply advise `kill-line' with an override from crux because crux
840 ;; itself calls `kill-line', leading to a infinite nesting situation.
841 (advice-add 'kill-line :around
842 (defun kill-line@join (fn &rest args)
843 (if (and (eolp)
844 (not (bolp)))
845 (delete-indentation 1)
846 (apply fn args)))))
847
848(setup minibuffer
849 (:option enable-recursive-minibuffers t
850 file-name-shadow-properties '(invisible t intangible t)
851 minibuffer-eldef-shorten-default t
852 minibuffer-prompt-properties
853 '(read-only t cursor-intangible t face minibuffer-prompt)
854 read-answer-short t
855 read-extended-command-predicate ; used on >28
856 #'command-completion-default-include-p)
857
858 (add-hook 'minibuffer-setup-hook #'cursor-intangible-mode)
859
860 (add-hook 'minibuffer-setup-hook #'acdw/gc-disable)
861 (add-hook 'minibuffer-exit-hook #'acdw/gc-enable)
862
863 (minibuffer-depth-indicate-mode +1)
864 (file-name-shadow-mode +1)
865 (minibuffer-electric-default-mode +1)
866
867 (if (version< emacs-version "28")
868 (fset 'yes-or-no-p #'y-or-n-p)
869 (setq use-short-answers t)))
870
871(setup mouse-avoidance
872 (mouse-avoidance-mode 'exile))
873
874(setup page
875 (:option page-delimiter
876 (rx bol (or "\f" ";;;")
877 (not (any "#")) (* not-newline) "\n"
878 (* (* blank) (opt ";" (* not-newline)) "\n")))
879
880 (defun recenter-to-top (&rest _)
881 "Recenter the cursor to the top of the window."
882 (when (called-interactively-p 'any)
883 (recenter (if (or (null scroll-margin)
884 (zerop scroll-margin))
885 3
886 scroll-margin))))
887
888 (:advise forward-page :after #'recenter-to-top
889 backward-page :after #'recenter-to-top)
890
891 ;; I'm not sure where this is in /my/ version of Emacs
892 ;; (defvar page-navigation-repeat-map
893 ;; (let ((map (make-sparse-keymap)))
894 ;; (define-key map "]" #'forward-page)
895 ;; (define-key map "[" #'backward-page)
896 ;; map)
897 ;; "Keymap to repeat page navigation key sequences. Used in `repeat-mode'.")
898
899 ;; (put 'forward-page 'repeat-map 'page-navigation-repeat-map)
900 ;; (put 'backward-page 'repeat-map 'page-navigation-repeat-map)
901 )
902
903(setup prog
904 (:option show-paren-delay 0
905 show-paren-style 'mixed
906 show-paren-when-point-inside-paren t
907 show-paren-when-point-in-periphery t
908 smie-indent-basic tab-width)
909
910 (:hook show-paren-mode
911 electric-pair-local-mode
912 acdw/setup-fringes
913
914 (defun prog-mode@auto-fill ()
915 (setq-local comment-auto-fill-only-comments t)
916 (turn-on-auto-fill)))
917
918 (add-hook 'after-save-hook
919 #'executable-make-buffer-file-executable-if-script-p))
920
921(setup repeat
922 ;; new for Emacs 28!
923 (:only-if (fboundp #'repeat-mode))
924
925 (:option repeat-exit-key "g"
926 repeat-exit-timeout 5)
927
928 (repeat-mode +1))
929
930(setup saveplace
931 (:option save-place-file (acdw/dir "places.el")
932 save-place-forget-unreadable-files (acdw/system :home))
933
934 (save-place-mode +1))
935
936(setup scratch
937 (:option inhibit-startup-screen t
938 initial-buffer-choice t
939 initial-scratch-message ""
940 ;; (concat ";; Howdy, "
941 ;; (nth 0 (split-string
942 ;; user-full-name))
943 ;; "! "
944 ;; "Welcome to GNU Emacs.\n\n")
945 )
946
947 (add-hook 'kill-buffer-query-functions
948 (defun kill-buffer-query@immortal-scratch ()
949 (if (eq (current-buffer) (get-buffer "*scratch*"))
950 (progn (bury-buffer)
951 nil)
952 t))))
953
954(setup scrolling
955 (:option auto-window-vscroll nil
956 fast-but-imprecise-scrolling t
957 scroll-margin 3
958 scroll-conservatively 101
959 scroll-preserve-screen-position 1))
960
961(setup selection
962 (:option save-interprogram-paste-before-kill t
963 yank-pop-change-selection t
964 x-select-enable-clipboard t
965 x-select-enable-primary t
966 mouse-drag-copy-region t
967 kill-do-not-save-duplicates t)
968
969 (delete-selection-mode +1))
970
971(setup sh-mode
972 (:option sh-basic-offset tab-width
973 sh-indent-after-case 0
974 sh-indent-for-case-alt '+
975 sh-indent-for-case-label 0)
976
977 (:local-set indent-tabs-mode t)
978
979 (when (executable-find "shfmt")
980 (with-eval-after-load 'apheleia
981 (:option (append apheleia-formatters) '(shfmt . ("shfmt"))
982 (append apheleia-mode-alist) '(sh-mode . shfmt))))
983
984 (when (executable-find "shellcheck")
985 (:straight flymake-shellcheck)
986 (:hook flymake-mode
987 flymake-shellcheck-load)))
988
989(setup shell-command
990 (:option shell-command-switch (acdw/system
991 ;; I should be testing on some variable
992 (:home "-csi")
993 (:work "-c"))
994 shell-command-prompt-show-cwd t
995 shell-command-default-error-buffer "*shell-command-errors*"))
996
997(setup shr
998 (:option shr-width fill-column
999 shr-max-width fill-column
1000 shr-max-image-proportion 0.6
1001 shr-image-animate t
1002 shr-discard-aria-hidden t
1003 shr-folding-mode t))
1004
1005(setup text
1006 (:hook turn-on-auto-fill
1007 tildify-mode
1008 acdw/setup-fringes))
1009
1010(setup uniquify
1011 (:option uniquify-buffer-name-style 'forward
1012 uniquify-separator path-separator
1013 uniquify-after-kill-buffer-p t
1014 uniquify-ignore-buffers-re "^\\*"))
1015
1016(setup variable-pitch-mode
1017 ;; I might want to change this to `buffer-face-mode-hook'...
1018 (:advise variable-pitch-mode :after
1019 (defun variable-pitch-mode@setup (&rest _)
1020 "Set up `variable-pitch-mode' with my customizations."
1021 (display-fill-column-indicator-mode
1022 (if buffer-face-mode -1 +1)))))
1023
1024(setup view
1025 (:option view-read-only t)
1026
1027 (:hook (defun acdw/read-view-mode ()
1028 (reading-mode (if view-mode +1 -1)))))
1029
1030(setup w32
1031 (:option w32-allow-system-shell t
1032 w32-pass-lwindow-to-system nil
1033 w32-lwindow-modifier 'super
1034 w32-pass-rwindow-to-system nil
1035 w32-rwindow-modifier 'super
1036 w32-pass-apps-to-system nil
1037 w32-apps-modifier 'hyper))
1038
1039(setup whitespace
1040 (:option whitespace-style '(empty
1041 indentation
1042 space-before-tab
1043 space-after-tab)
1044 indent-tabs-mode nil
1045 tab-width 4
1046 backward-delete-char-untabify-method 'hungry)
1047
1048 (:global "M-SPC" #'cycle-spacing))
1049
1050(setup windmove
1051 (:option windmove-wrap-around t)
1052 (:global
1053 ;; moving
1054 "C-x 4 <left>" #'windmove-left
1055 "C-x 4 <right>" #'windmove-right
1056 "C-x 4 <up>" #'windmove-up
1057 "C-x 4 <down>" #'windmove-down
1058 ;; swapping
1059 "C-x 4 S-<left>" #'windmove-swap-states-left
1060 "C-x 4 S-<right>" #'windmove-swap-states-right
1061 "C-x 4 S-<up>" #'windmove-swap-states-up
1062 "C-x 4 S-<down>" #'windmove-swap-states-down)
1063
1064 ;; (when (fboundp 'repeat-mode)
1065 ;; (defvar windmove-repeat-map
1066 ;; (let ((map (make-sparse-keymap)))
1067 ;; ;; moving
1068 ;; (define-key map [left] #'windmove-left)
1069 ;; (define-key map [right] #'windmove-right)
1070 ;; (define-key map [up] #'windmove-up)
1071 ;; (define-key map [down] #'windmove-down)
1072 ;; ;; swapping
1073 ;; (define-key map [S-left] #'windmove-swap-states-left)
1074 ;; (define-key map [S-right] #'windmove-swap-states-right)
1075 ;; (define-key map [S-up] #'windmove-swap-states-up)
1076 ;; (define-key map [S-down] #'windmove-swap-states-down)
1077 ;; map)
1078 ;; "Keymap to repeat various `windmove' sequences. Used in `repeat-mode'.")
1079
1080 ;; (dolist (sym '(windmove-left
1081 ;; windmove-right
1082 ;; windmove-up
1083 ;; windmove-down
1084 ;; windmove-swap-states-left
1085 ;; windmove-swap-states-right
1086 ;; windmove-swap-states-up
1087 ;; windmove-swap-states-down))
1088 ;; (put sym 'repeat-map 'windmove-repeat-map)))
1089 )
1090
1091(setup window
1092 (require 'acdw-bell)
1093 (:option
1094 ;; Man-notify-method 'pushy
1095 ;; display-buffer-alist ; from FrostyX
1096 ;; '(("shell.*" (display-buffer-same-window) ())
1097 ;; (".*" (display-buffer-reuse-window
1098 ;; display-buffer-same-window)
1099 ;; (reusable-frames . t)))
1100 recenter-positions '(top middle bottom)
1101 ring-bell-function (lambda ()
1102 (acdw-bell/flash-mode-line
1103 (acdw/system :home)))
1104 use-dialog-box nil
1105 use-file-dialog nil
1106 visible-bell nil)
1107
1108 (tooltip-mode -1))
1109
1110(setup winner
1111 ;; see https://lists.gnu.org/archive/html/emacs-devel/2021-08/msg00888.html
1112 (:global "C-x 4 C-/" #'winner-undo
1113 "C-x 4 /" #'winner-undo
1114 "C-x 4 C-?" #'winner-redo
1115 "C-x 4 ?" #'winner-redo)
1116
1117 ;; add `winner-undo' and `winner-redo' to `repeat-mode'
1118 ;; (when (fboundp 'repeat-mode)
1119 ;; (defvar winner-mode-repeat-map
1120 ;; (let ((map (make-sparse-keymap)))
1121 ;; (define-key map "/" #'winner-undo)
1122 ;; (define-key map "?" #'winner-redo)
1123 ;; map)
1124 ;; "Keymap to repeat `winner-mode' sequences. Used in `repeat-mode'.")
1125
1126 ;; (put 'winner-undo 'repeat-map 'winner-mode-repeat-map)
1127 ;; (put 'winner-redo 'repeat-map 'winner-mode-repeat-map))
1128
1129 (winner-mode +1))
1130
1131(setup (:straight (0x0
1132 :host gitlab
1133 :repo "willvaughn/emacs-0x0"))
1134 (:option 0x0-default-server 'ttm))
1135
1136(setup (:straight-if affe
1137 (and (or (executable-find "fd")
1138 (executable-find "find"))
1139 (executable-find "rg")))
1140 ;; Keys are bound in `acdw/sensible-grep' and `acdw/sensible-find'
1141 (:option affe-regexp-compiler
1142 (defun affe-orderless-regexp-compiler (input _type)
1143 (setq input (orderless-pattern-compiler input))
1144 (cons input (lambda (str) (orderless--highlight input str))))))
1145
1146(setup (:straight-if ahk-mode
1147 (acdw/system :work)))
1148
1149(setup (:straight alert)
1150 (:option alert-default-style (acdw/system
1151 (:home 'libnotify)
1152 (_ 'message))))
1153
1154(setup (:straight (apheleia
1155 :host github
1156 :repo "raxod502/apheleia"))
1157
1158 (apheleia-global-mode +1)
1159
1160 ;; Use a dumb formatter on modes that `apheleia' doesn't work for.
1161 (add-hook 'before-save-hook
1162 (defun before-save@dumb-auto-format ()
1163 (setq stupid-modes '(makefile-mode
1164 org-mode))
1165 ;; If there's no apheleia formatter for the mode, just indent the
1166 ;; buffer.
1167 (unless (or (apply #'derived-mode-p stupid-modes)
1168 (and (fboundp 'apheleia--get-formatter-command)
1169 (apheleia--get-formatter-command)))
1170 (indent-region (point-min) (point-max))))))
1171
1172(setup (:straight async)
1173 (dired-async-mode +1)
1174
1175 (:with-feature dired
1176 (:hook (defun dired@disable-dired-async-mode-line ()
1177 (autoload 'dired-async--modeline-mode "dired-async" nil t)
1178 (dired-async--modeline-mode -1)))))
1179
1180(setup (:straight avy)
1181 (:global "C-'" #'avy-goto-char-timer
1182 "C-c C-j" #'avy-resume)
1183
1184 (:with-feature isearch
1185 (:bind "C-'" #'avy-isearch)))
1186
1187(setup (:straight circe)
1188 (require 'circe)
1189 (require 'acdw-irc)
1190
1191 (:option acdw-irc/left-margin 12
1192 acdw-irc/post-my-nick "-> "
1193 circe-channel-killed-confirmation nil
1194 circe-color-nicks-everywhere t
1195 circe-default-nick "acdw"
1196 circe-default-part-message "See You, Space Cowpokes . . ."
1197 circe-default-user "acdw"
1198 circe-format-action
1199 (lambda (&rest plist)
1200 (concat
1201 (acdw-irc/margin-format "" "*" "*" t)
1202 " " (plist-get plist :nick) " " (plist-get plist :body)))
1203 circe-format-say
1204 (lambda (&rest plist)
1205 (concat
1206 (acdw-irc/margin-format (plist-get plist :nick) "" " |" t)
1207 " " (plist-get plist :body)))
1208 circe-format-self-action
1209 (lambda (&rest plist)
1210 (concat
1211 (acdw-irc/margin-format "" "-*" " *" t)
1212 " " (plist-get plist :nick) " " (plist-get plist :body)))
1213 circe-format-self-say
1214 (lambda (&rest plist)
1215 (concat
1216 (acdw-irc/margin-format (plist-get plist :nick) "-" " >" t)
1217 " " (plist-get plist :body)))
1218 ;; circe-highlight-nick-type 'message
1219 circe-network-options
1220 `(("Libera Chat"
1221 :channels ("#emacs" "#systemcrafters" "##webpals")
1222 :sasl-username ,circe-default-nick
1223 :sasl-password ,(acdw/make-password-fetcher
1224 :host "libera.chat"))
1225 ("Tilde Chat" :host "irc.tilde.chat" :port 6697 :use-tls t
1226 :channels ("#meta" "#bread" "#dadjokes" "#team"
1227 "#emacs")
1228 :sasl-username ,circe-default-nick
1229 :sasl-password ,(acdw/make-password-fetcher
1230 :host "tilde.chat"))
1231 ("Casa" :host "m455.casa" :port 6697 :use-tls t
1232 :channels ("#basement")
1233 :sasl-username ,circe-default-nick
1234 :sasl-password ,(acdw/make-password-fetcher
1235 :host "m455.casa"))
1236 ("Pissnet" :host "piss.hmm.st" :port 6697 :use-tls t
1237 :channels ("#i-just-peed")
1238 :sasl-username ,circe-default-nick
1239 :sasl-password ,(acdw/make-password-fetcher
1240 :host "piss.hmm.st"))
1241 ;; TODO: irc.chat.twitch.tv
1242 )
1243 circe-reduce-lurker-spam t
1244 circe-server-auto-join-default-type :after-auth)
1245
1246 ;; (:face circe-nick-highlight-face
1247 ;; ((t (:inherit (modus-themes-hl-line)))))
1248
1249 (:bind "C-c C-p" #'circe-command-PART
1250 "C-l" #'lui-track-jump-to-indicator)
1251
1252 (:advise circe-command-PART :after
1253 (defun circe-part@kill-buffer (&rest _)
1254 (let ((circe-channel-killed-confirmation nil))
1255 (kill-buffer)))
1256
1257 circe-command-QUIT :after
1258 (defun circe-quit@kill-buffer (&rest _)
1259 ;; `circe-server-killed-confirmation' set to nil, and manually
1260 ;; deleting all chat buffers, pending Github issue #402
1261 ;; (https://github.com/emacs-circe/circe/issues/402)
1262 (let ((circe-server-killed-confirmation nil))
1263 (with-circe-server-buffer
1264 (dolist (buf (circe-server-chat-buffers))
1265 (let ((circe-channel-killed-confirmation nil))
1266 (kill-buffer buf)))
1267 (kill-buffer))))
1268
1269 circe-command-GQUIT :after
1270 (defun circe-gquit@kill-buffer (&rest _)
1271 ;; `circe-server-killed-confirmation' set to nil, and manually
1272 ;; deleting all chat buffers, pending Github issue #402
1273 ;; (https://github.com/emacs-circe/circe/issues/402)
1274 (let ((circe-server-killed-confirmation nil))
1275 (dolist (buf (circe-server-buffers))
1276 (with-current-buffer buf
1277 (dolist (buf (circe-server-chat-buffers))
1278 (let ((circe-channel-killed-confirmation nil))
1279 (kill-buffer buf)))
1280 (message "%s: %s" buf circe-server-killed-confirmation)
1281 (kill-buffer))))))
1282
1283 (defun circe-command-SHORTEN (url)
1284 "Shorten URL using `0x0-shorten-uri'."
1285 (interactive "sURL to shorten: ")
1286 ;; TODO: enable /shorten URL comment syntax
1287 (let ((short-url (0x0-shorten-uri (0x0--choose-server) url)))
1288 (circe-command-SAY short-url)))
1289
1290 (:with-mode circe-chat-mode
1291 (:hook #'acdw/stop-paren-annoyances
1292 #'enable-circe-color-nicks
1293 #'enable-circe-display-images
1294 #'enable-circe-new-day-notifier
1295 (defun circe-chat@set-prompt ()
1296 (lui-set-prompt
1297 (concat
1298 (propertize
1299 (acdw-irc/margin-format (buffer-name) "" ">")
1300 'face 'circe-prompt-face
1301 'read-only t
1302 'intangible t
1303 'cursor-intangible t)
1304 " ")))))
1305
1306 (autoload 'circe-nick-color-reset "circe-color-nicks")
1307 (add-hook 'modus-themes-after-load-theme-hook
1308 #'circe-nick-color-reset)
1309
1310 (:with-mode lui-mode
1311 (:option lui-fill-column fill-column
1312 lui-fill-type (repeat-string acdw-irc/left-margin " ")
1313 lui-time-stamp-position 'right-margin
1314 lui-time-stamp-format "%H:%M"
1315 lui-track-behavior 'before-switch-to-buffer
1316 lui-track-indicator 'fringe)
1317
1318 (:local-set fringes-outside-margins t
1319 right-margin-width 5
1320 scroll-margin 0
1321 word-wrap t
1322 wrap-prefix (repeat-string acdw-irc/left-margin " ")
1323 line-number-mode nil)
1324
1325 (:hook #'enable-lui-track)))
1326
1327(setup (:straight (consult
1328 :host github
1329 :repo "minad/consult"))
1330
1331 (:require acdw-consult)
1332 (:autoload consult-register-preview)
1333
1334 ;; Bindings
1335 (:global
1336 ;; C-c bindings (`mode-specific-map')
1337 ;; I don't use any of these right now.
1338 ;; "C-c h" #'consult-history
1339 ;; "C-c m" #'consult-mode-command
1340 ;; "C-c b" #'consult-bookmark
1341 ;; "C-c k" #'consult-kmacro
1342 ;; C-x bindings (`ctl-x-map')
1343 "C-x M-:" #'consult-complex-command
1344 "C-x b" #'consult-buffer
1345 "C-x 4 b" #'consult-buffer-other-window
1346 "C-x 5 b" #'consult-buffer-other-frame
1347 ;; Custom M-# bindings for fast register access
1348 "M-#" #'consult-register-load
1349 "M-'" #'consult-register-store
1350 "C-M-#" #'consult-register
1351 ;; M-g bindings (`goto-map')
1352 "M-g e" #'consult-compile-error
1353 "M-g g" #'consult-goto-line
1354 "M-g M-g" #'consult-goto-line
1355 "M-g o" #'consult-outline
1356 "M-g m" #'consult-mark
1357 "M-g k" #'consult-global-mark
1358 "M-g i" #'consult-imenu
1359 "M-g I" #'consult-project-imenu
1360 ;; M-s bindings (`search-map')
1361 "M-s g" #'acdw-consult/sensible-grep
1362 "M-s f" #'acdw-consult/sensible-find
1363 "M-s l" #'consult-line
1364 "M-s m" #'consult-multi-occur
1365 "M-s k" #'consult-keep-lines
1366 "M-s u" #'consult-focus-lines
1367 ;; Other bindings
1368 "M-y" #'consult-yank-pop
1369 "<help> a" #'consult-apropos
1370 ;; Isearch integration
1371 "M-s e" #'consult-isearch)
1372
1373 (:with-map isearch-mode-map
1374 (:bind "M-e" #'consult-isearch
1375 "M-s e" #'consult-isearch
1376 "M-s l" #'consult-line))
1377
1378 (consult-history-to-modes ((minibuffer-local-map . nil)
1379 (shell-mode-map . shell-mode-hook)
1380 (term-mode-map . term-mode-hook)
1381 (term-raw-map . term-mode-hook)
1382 (comint-mode-map . comint-mode-hook)
1383 (sly-mrepl-mode-map . sly-mrepl-hook)))
1384
1385 (:option register-preview-delay 0
1386 register-preview-function #'consult-register-format
1387 xref-show-xrefs-function #'consult-xref
1388 xref-show-definitions-function #'consult-xref
1389 consult-project-root-function #'vc-root-dir
1390 completion-in-region-function #'acdw-consult/complete-in-region
1391 completion-cycle-threshold 3
1392 consult-preview-key (kbd "M-.")
1393 tab-always-indent 'complete)
1394
1395 (:advise register-preview :override #'consult-register-window)
1396
1397 ;; Completing-read-multple
1398 (if (fboundp #'consult-completing-read-multiple)
1399 (:advise completing-read-multple :override
1400 #'consult-completing-read-multiple)
1401 (:advise completing-read-multiple :filter-args
1402 (defun crm-indicator (args)
1403 (cons (concat "[CRM] " (car args)) (cdr args)))))
1404
1405 (with-eval-after-load 'orderless
1406 (:option consult--regexp-compiler
1407 #'consult--orderless-regexp-compiler))
1408
1409 (with-eval-after-loads (vertico consult)
1410 (:with-map consult-crm-map
1411 (:bind "RET" (defun +vertico-crm-exit ()
1412 (interactive)
1413 (run-at-time 0 nil #'vertico-exit)
1414 (funcall #'vertico-exit))
1415 "TAB" #'vertico-exit))))
1416
1417(setup (:straight crux)
1418 (:global "C-o" #'crux-smart-open-line
1419 "M-o" #'crux-smart-open-line-above
1420 "C-M-\\" #'crux-cleanup-buffer-or-region
1421 "C-x 4 t" #'crux-transpose-windows)
1422
1423 (crux-reopen-as-root-mode +1))
1424
1425(setup (:straight-if (define-repeat-map
1426 :host nil
1427 :repo "https://tildegit.org/acdw/define-repeat-map.el")
1428 (acdw/system :home))
1429
1430 (defun acdw/other-window-or-switch-buffer-backward ()
1431 (interactive)
1432 (setq repeat-map 'other-window-repeat-map)
1433 (acdw/other-window-or-switch-buffer -1))
1434
1435 (define-repeat-map other-window
1436 ("o" acdw/other-window-or-switch-buffer
1437 "O" acdw/other-window-or-switch-buffer-backward))
1438
1439 (define-repeat-map case
1440 ("c" capitalize-word
1441 "u" upcase-dwim
1442 "l" downcase-dwim)
1443 (:continue "f" forward-word
1444 "b" backward-word)
1445 (:enter capitalize-dwim
1446 upcase-dwim
1447 downcase-dwim))
1448
1449 (define-repeat-map page-navigation
1450 ("]" forward-page
1451 "[" backward-page))
1452
1453 (define-repeat-map windmove
1454 (;; moving
1455 "<left>" windmove-left
1456 "<right>" windmove-right
1457 "<up>" windmove-up
1458 "<down>" windmove-down
1459 ;; swapping
1460 "<S-left>" windmove-swap-states-left
1461 "<S-right>" windmove-swap-states-right
1462 "<S-up>" windmove-swap-states-up
1463 "<S-down>" windmove-swap-states-down))
1464
1465 (define-repeat-map winner-mode
1466 ("/" winner-undo
1467 "?" winner-redo)))
1468
1469(setup (:straight edit-indirect))
1470
1471;; requires extension:
1472;; https://addons.mozilla.org/en-US/firefox/addon/edit-with-emacs1/
1473(setup (:straight edit-server)
1474 (:require edit-server)
1475 (edit-server-start)
1476
1477 (:option edit-server-default-major-mode 'text-mode
1478 edit-server-url-major-mode-alist
1479 (list (cons (rx (| "reddit.com"
1480 "tildes.net"))
1481 'markdown-mode)
1482 (cons (rx "github.com")
1483 'gfm-mode)))
1484
1485 (:advise edit-server-make-frame :before
1486 (defun edit-server@set-a-variable (&rest _)
1487 (setq-local edit-server-frame-p t))))
1488
1489(setup (:straight (electric-cursor
1490 :host github
1491 :repo "duckwork/electric-cursor"))
1492 (electric-cursor-mode +1))
1493
1494(setup (:straight elfeed
1495 elfeed-protocol)
1496 (:option elfeed-use-curl t
1497 elfeed-feeds `(("fever+https://acdw@mf.acdw.net"
1498 :api-url "https://mf.acdw.net/fever/"
1499 :password ,(acdw/make-password-fetcher
1500 :host "mf.acdw.net"))))
1501
1502 (elfeed-protocol-enable)
1503 (:advise elfeed :after
1504 (defun elfeed@protocol-update (&rest _)
1505 (elfeed-search-fetch nil)))
1506
1507 (:face message-header-subject
1508 ((t (:height 1.5))))
1509
1510 (:with-mode elfeed-show-mode
1511 (:hook #'reading-mode)
1512
1513 ;; see https://irreal.org/blog/?p=8885
1514 (:bind "SPC" (defun elfeed-scroll-up-command (&optional arg)
1515 "Scroll up or go to next feed item in Elfeed"
1516 (interactive "^P")
1517 (let ((scroll-error-top-bottom nil))
1518 (condition-case-unless-debug nil
1519 (scroll-up-command arg)
1520 (error (elfeed-show-next)))))
1521 "S-SPC" (defun elfeed-scroll-down-command (&optional arg)
1522 "Scroll up or go to next feed item in Elfeed"
1523 (interactive "^P")
1524 (let ((scroll-error-top-bottom nil))
1525 (condition-case-unless-debug nil
1526 (scroll-down-command arg)
1527 (error (elfeed-show-prev))))))))
1528
1529(setup (:straight elisp-slime-nav)
1530 (:hook-into emacs-lisp-mode
1531 ielm-mode))
1532
1533(setup (:straight (elpher
1534 :host nil
1535 :repo "git://thelambdalab.xyz/elpher.git"))
1536 (:option elpher-ipv4-always t
1537 elpher-certificate-directory (acdw/dir "elpher/")
1538 elpher-gemini-max-fill-width fill-column)
1539
1540 (:bind "n" #'elpher-next-link
1541 "p" #'elpher-prev-link
1542 "o" #'elpher-follow-current-link
1543 "G" #'elpher-go-current)
1544
1545 (:hook #'reading-mode)
1546
1547 (:autoload (elpher-bookmarks :interactive t)
1548 (elpher-go :interactive t))
1549
1550 ;; Make `eww' gemini/gopher aware. From Emacswiki.
1551 ;; (define-advice eww-browse-url (:around (fn url &rest args) gemini-elpher)
1552 ;; (cond ((string-match-p "\\`\\(gemini\\|gopher\\)://" url)
1553 ;; (require 'elpher)
1554 ;; (elpher-go url))
1555 ;; (t (apply fn url args))))
1556 )
1557
1558(setup (:straight embark)
1559 (:global "C-." #'embark-act)
1560 (:option prefix-help-command #'embark-prefix-help-command
1561 (append display-buffer-alist)
1562 `(,(rx (seq bos "*Embark Collect "
1563 (group (| "Live" "Completions"))
1564 "*"))
1565 nil
1566 (window-parameters (mode-line-format . none)))
1567 embark-prompter #'embark-keymap-prompter
1568 embark-verbose-indicator-display-action
1569 '(display-buffer-at-bottom (window-height . fit-window-to-buffer))
1570 embark-action-indicator
1571 (lambda (map _target)
1572 (which-key--show-keymap "Embark" map nil nil 'no-paging)
1573 #'which-key--hide--ignore-command)
1574 embark-become-indicator embark-action-indicator)
1575
1576 (with-eval-after-loads (embark consult)
1577 (:straight embark-consult)
1578 (add-hook 'embark-collect-mode-hook
1579 #'consult-preview-at-point-mode)))
1580
1581(setup (:straight epithet)
1582 (dolist (hook '(Info-selection-hook
1583 eww-after-render-hook
1584 help-mode-hook
1585 occur-mode-hook))
1586 (add-hook hook #'epithet-rename-buffer)))
1587
1588;; TODO: look into emms or something related for this
1589(setup (:straight-if eradio
1590 (executable-find "mpv"))
1591 (:option
1592 eradio-player '("mpv" "--no-video" "--no-terminal")
1593 eradio-channels `(("KLSU" .
1594 "http://130.39.238.143:8010/stream.mp3")
1595 ("Soma FM Synphaera" .
1596 "https://somafm.com/synphaera256.pls")
1597 ("SomaFM BAGel Radio" .
1598 "https://somafm.com/bagel.pls")
1599 ("SomaFM Boot Liquor" .
1600 "https://somafm.com/bootliquor320.pls")
1601 ("SomaFM Deep Space One" .
1602 "https://somafm.com/deepspaceone.pls")
1603 ("SomaFM Fluid" .
1604 "https://somafm.com/fluid.pls")
1605 ("SomaFM Underground 80s" .
1606 "https://somafm.com/u80s256.pls")
1607 ("WBRH: Jazz & More" .
1608 "http://wbrh.streamguys1.com/wbrh-mp3")
1609 ("KBRH Blues & Rhythm Hits" .
1610 "http://wbrh.streamguys1.com/kbrh-mp3")
1611 ("WRKF HD-2" .
1612 ,(concat "https://playerservices.streamtheworld.com/"
1613 "api/livestream-redirect/WRKFHD2.mp3"))
1614 ("WRKF: NPR for the Capital Region" .
1615 ,(concat "https://playerservices.streamtheworld.com/"
1616 "api/livestream-redirect/WRKFFM.mp3"))
1617 ("BadRadio: 24/7 PHONK" .
1618 "https://s2.radio.co/s2b2b68744/listen")
1619 ("tilderadio" .
1620 "https://azuracast.tilderadio.org/radio/8000/radio.ogg")
1621 ("vantaradio" .
1622 "https://vantaa.black/radio")))
1623 (:global "C-c r r" #'eradio-play ; mnemonic: radio
1624 "C-c r s" #'eradio-stop ; mnemonic: stop
1625 "C-c r p" #'eradio-toggle ; mnemonic: play/pause
1626 ))
1627
1628(setup (:straight eros)
1629 (:hook-into emacs-lisp-mode
1630 lisp-interaction-mode))
1631
1632(setup (:straight-if exec-path-from-shell
1633 (acdw/system :home))
1634 (when (daemonp)
1635 (exec-path-from-shell-initialize)))
1636
1637(setup (:straight expand-region)
1638 (:global "C-=" #'er/expand-region))
1639
1640(setup (:straight-if fennel-mode
1641 (executable-find "fennel"))
1642 (:autoload (fennel-repl :interactive t))
1643 (:file-match (rx ".fnl" eos)))
1644
1057(setup (:straight flyspell-correct) 1645(setup (:straight flyspell-correct)
1058 (:option flyspell-correct-interface #'flyspell-correct-completing-read 1646 (:option flyspell-correct-interface #'flyspell-correct-completing-read
1059 flyspell-correct--cr-key ";") 1647 flyspell-correct--cr-key ";")
@@ -1079,16 +1667,6 @@ specific to most general, they are these:
1079 '("tildegit.org" "tildegit.org/api/v1" "tildegit.org" 1667 '("tildegit.org" "tildegit.org/api/v1" "tildegit.org"
1080 forge-gitea-repository)))) 1668 forge-gitea-repository))))
1081 1669
1082(setup frames
1083 (:option frame-title-format '("%b@"
1084 (:eval
1085 (or (file-remote-p default-directory 'host)
1086 system-name))
1087 " %+%* GNU Emacs"
1088 (:eval (when (frame-parameter nil 'client)
1089 " Client")))
1090 window-resize-pixelwise t))
1091
1092(setup (:straight gcmh) 1670(setup (:straight gcmh)
1093 (:option gcmh-idle-delay 'auto) 1671 (:option gcmh-idle-delay 'auto)
1094 (gcmh-mode +1)) 1672 (gcmh-mode +1))
@@ -1129,23 +1707,12 @@ specific to most general, they are these:
1129 (with-eval-after-load 'elpher 1707 (with-eval-after-load 'elpher
1130 (require 'gemini-write))) 1708 (require 'gemini-write)))
1131 1709
1132(setup (:require gforth)
1133 (:autoload forth-mode
1134 forth-block-mode)
1135 (add-to-list 'auto-mode-alist '("\\.fs\\'" . forth-mode))
1136 (add-to-list 'auto-mode-alist '("\\.fb\\'" . forth-block-mode)))
1137
1138(setup (:straight gitattributes-mode)) 1710(setup (:straight gitattributes-mode))
1139 1711
1140(setup (:straight gitconfig-mode)) 1712(setup (:straight gitconfig-mode))
1141 1713
1142(setup (:straight gitignore-mode)) 1714(setup (:straight gitignore-mode))
1143 1715
1144(setup (:require goto-addr)
1145 (if (fboundp #'global-goto-address-mode)
1146 (global-goto-address-mode)
1147 (add-hook 'after-change-major-mode-hook #'goto-address-mode)))
1148
1149(setup (:straight helpful) 1716(setup (:straight helpful)
1150 (:require-after 3) 1717 (:require-after 3)
1151 1718
@@ -1196,62 +1763,12 @@ specific to most general, they are these:
1196 (hungry-delete-forward (or arg 1)) 1763 (hungry-delete-forward (or arg 1))
1197 (paredit-forward-delete arg)))))) 1764 (paredit-forward-delete arg))))))
1198 1765
1199(setup ibuffer
1200 (:also-load ibuf-ext)
1201 (:option ibuffer-expert t
1202 ibuffer-show-empty-filter-groups nil
1203 ibuffer-saved-filter-groups
1204 '(("default"
1205 ("dired" (mode . dired-mode))
1206 ("customize" (mode . Custom-mode))
1207 ("emacs" (or (name . "^\\*scratch\\*$")
1208 (name . "^\\*Messages\\*$")
1209 (name . "^\\*Warnings\\*$")
1210 (name . "^\\*straight-process\\*$")
1211 (name . "^\\*Calendar\\*$")))
1212 ("git" (or (name . "^\*magit")
1213 (name . "^\magit")))
1214 ("help" (or (mode . help-mode)
1215 (mode . Info-mode)
1216 (mode . helpful-mode)))
1217 ("messaging" (or (mode . message-mode)
1218 (mode . bbdb-mode)
1219 (mode . mail-mode)
1220 (mode . gnus-group-mode)
1221 (mode . gnus-summary-mode)
1222 (mode . gnus-article-mode)
1223 (name . "^\\.bbdb$")
1224 (name . "^\\.newsrc-dribble")
1225 (mode . erc-mode)
1226 (mode . circe-server-mode)
1227 (mode . circe-channel-mode)))
1228 ("shell" (or (mode . eshell-mode)
1229 (mode . shell-mode)
1230 (mode . vterm-mode)))
1231 ("web" (or (mode . elpher-mode)
1232 (mode . gemini-mode)
1233 (mode . eww-mode))))))
1234
1235 (:global "C-x C-b" #'ibuffer)
1236
1237 (:hook (defun ibuffer@filter-to-default ()
1238 (ibuffer-switch-to-saved-filter-groups "default"))))
1239
1240(setup ielm
1241 (:hook #'turn-on-eldoc-mode))
1242
1243(setup imenu
1244 (:option imenu-auto-rescan t))
1245
1246(setup (:straight iscroll) 1766(setup (:straight iscroll)
1247 (define-globalized-minor-mode global-iscroll-mode iscroll-mode 1767 (define-globalized-minor-mode global-iscroll-mode iscroll-mode
1248 (lambda () (iscroll-mode +1))) 1768 (lambda () (iscroll-mode +1)))
1249 1769
1250 (global-iscroll-mode +1)) 1770 (global-iscroll-mode +1))
1251 1771
1252(setup isearch
1253 (:option search-default-mode t))
1254
1255(setup (:straight (kaomoji-insert 1772(setup (:straight (kaomoji-insert
1256 :host nil 1773 :host nil
1257 :repo "https://tildegit.org/acdw/kaomoji-insert")) 1774 :repo "https://tildegit.org/acdw/kaomoji-insert"))
@@ -1271,29 +1788,6 @@ specific to most general, they are these:
1271(setup (:straight-if ledger-mode 1788(setup (:straight-if ledger-mode
1272 (executable-find "ledger"))) 1789 (executable-find "ledger")))
1273 1790
1274(setup lines
1275 (:option fill-column 79
1276 word-wrap t
1277 truncate-lines nil)
1278
1279 (global-display-fill-column-indicator-mode +1)
1280 (global-so-long-mode +1)
1281
1282 (add-hook 'visual-line-mode-hook
1283 (defun acdw/disable-fill-column-indicator ()
1284 (display-fill-column-indicator-mode
1285 (if visual-line-mode -1 +1))))
1286
1287 ;; `acdw/kill-line-and-join-advice' cribs from `crux-kill-and-join-forward'.
1288 ;; I can't simply advise `kill-line' with an override from crux because crux
1289 ;; itself calls `kill-line', leading to a infinite nesting situation.
1290 (advice-add 'kill-line :around
1291 (defun kill-line@join (fn &rest args)
1292 (if (and (eolp)
1293 (not (bolp)))
1294 (delete-indentation 1)
1295 (apply fn args)))))
1296
1297(setup (:straight link-hint) 1791(setup (:straight link-hint)
1298 ;; Browse web URLs with a browser with a prefix argument. 1792 ;; Browse web URLs with a browser with a prefix argument.
1299 (dolist (type '(gnus-w3m-image-url 1793 (dolist (type '(gnus-w3m-image-url
@@ -1395,29 +1889,6 @@ browser defined in `browse-url-secondary-browser-function'."
1395 (:hook #'hl-line-mode 1889 (:hook #'hl-line-mode
1396 #'reading-mode)) 1890 #'reading-mode))
1397 1891
1398(setup minibuffer
1399 (:option enable-recursive-minibuffers t
1400 file-name-shadow-properties '(invisible t intangible t)
1401 minibuffer-eldef-shorten-default t
1402 minibuffer-prompt-properties
1403 '(read-only t cursor-intangible t face minibuffer-prompt)
1404 read-answer-short t
1405 read-extended-command-predicate ; used on >28
1406 #'command-completion-default-include-p)
1407
1408 (add-hook 'minibuffer-setup-hook #'cursor-intangible-mode)
1409
1410 (add-hook 'minibuffer-setup-hook #'acdw/gc-disable)
1411 (add-hook 'minibuffer-exit-hook #'acdw/gc-enable)
1412
1413 (minibuffer-depth-indicate-mode +1)
1414 (file-name-shadow-mode +1)
1415 (minibuffer-electric-default-mode +1)
1416
1417 (if (version< emacs-version "28")
1418 (fset 'yes-or-no-p #'y-or-n-p)
1419 (setq use-short-answers t)))
1420
1421(setup (:straight (modus-themes 1892(setup (:straight (modus-themes
1422 :host gitlab 1893 :host gitlab
1423 :repo "protesilaos/modus-themes")) 1894 :repo "protesilaos/modus-themes"))
@@ -1432,9 +1903,6 @@ browser defined in `browse-url-secondary-browser-function'."
1432 (acdw/sunrise-sunset #'modus-themes-load-operandi 1903 (acdw/sunrise-sunset #'modus-themes-load-operandi
1433 #'modus-themes-load-vivendi)) 1904 #'modus-themes-load-vivendi))
1434 1905
1435(setup mouse-avoidance
1436 (mouse-avoidance-mode 'exile))
1437
1438(setup (:straight mwim) 1906(setup (:straight mwim)
1439 (:global "C-a" #'mwim-beginning 1907 (:global "C-a" #'mwim-beginning
1440 "C-e" #'mwim-end)) 1908 "C-e" #'mwim-end))
@@ -1598,35 +2066,6 @@ browser defined in `browse-url-secondary-browser-function'."
1598 2066
1599(setup (:straight package-lint-flymake)) 2067(setup (:straight package-lint-flymake))
1600 2068
1601(setup page
1602 (:option page-delimiter
1603 (rx bol (or "\f" ";;;")
1604 (not (any "#")) (* not-newline) "\n"
1605 (* (* blank) (opt ";" (* not-newline)) "\n")))
1606
1607 (defun recenter-to-top (&rest _)
1608 "Recenter the cursor to the top of the window."
1609 (when (called-interactively-p 'any)
1610 (recenter (if (or (null scroll-margin)
1611 (zerop scroll-margin))
1612 3
1613 scroll-margin))))
1614
1615 (:advise forward-page :after #'recenter-to-top
1616 backward-page :after #'recenter-to-top)
1617
1618 ;; I'm not sure where this is in /my/ version of Emacs
1619 ;; (defvar page-navigation-repeat-map
1620 ;; (let ((map (make-sparse-keymap)))
1621 ;; (define-key map "]" #'forward-page)
1622 ;; (define-key map "[" #'backward-page)
1623 ;; map)
1624 ;; "Keymap to repeat page navigation key sequences. Used in `repeat-mode'.")
1625
1626 ;; (put 'forward-page 'repeat-map 'page-navigation-repeat-map)
1627 ;; (put 'backward-page 'repeat-map 'page-navigation-repeat-map)
1628 )
1629
1630(setup (:straight page-break-lines) 2069(setup (:straight page-break-lines)
1631 (global-page-break-lines-mode +1)) 2070 (global-page-break-lines-mode +1))
1632 2071
@@ -1699,28 +2138,23 @@ browser defined in `browse-url-secondary-browser-function'."
1699 (setq-local comment-auto-fill-only-comments t) 2138 (setq-local comment-auto-fill-only-comments t)
1700 (turn-on-auto-fill))) 2139 (turn-on-auto-fill)))
1701 2140
1702 (add-hook 'after-save-hook 2141 (mapc (lambda (buf)
1703 #'executable-make-buffer-file-executable-if-script-p)) 2142 (with-current-buffer buf
2143 (when (funcall persistent-scratch-scratch-buffer-p-function)
2144 (persistent-scratch-mode +1))))
1704 2145
1705(setup (:require recentf) 2146 (buffer-list)))
1706 (:option recentf-save-file (acdw/dir "recentf.el")
1707 recentf-max-menu-items 100
1708 recentf-max-saved-items nil
1709 recentf-auto-cleanup 'mode
1710 (append recentf-exclude) (acdw/dir))
1711 2147
1712 (:advise dired-rename-file :after #'rjs/recentf-rename-notify) 2148(setup (:straight-if pkgbuild-mode
1713 2149 (executable-find "makepkg"))
1714 (recentf-mode +1)) 2150 (:file-match "PKGBUILD"))
1715 2151
1716(setup repeat 2152(setup (:straight powerthesaurus)
1717 ;; new for Emacs 28! 2153 (:global "C-c l t" #'powerthesaurus-lookup-word-dwim))
1718 (:only-if (fboundp #'repeat-mode))
1719 2154
1720 (:option repeat-exit-key "g" 2155(setup (:straight prism)
1721 repeat-exit-timeout 5) 2156 (dolist (mode lispy-modes)
1722 2157 (add-hook (intern (format "%s-hook" mode)) #'prism-mode)))
1723 (repeat-mode +1))
1724 2158
1725(setup (:straight restart-emacs) 2159(setup (:straight restart-emacs)
1726 (defun emacs-upgrade (&optional update-packages) 2160 (defun emacs-upgrade (&optional update-packages)
@@ -1732,93 +2166,6 @@ browser defined in `browse-url-secondary-browser-function'."
1732 (straight-x-pull-all)) 2166 (straight-x-pull-all))
1733 (restart-emacs))) 2167 (restart-emacs)))
1734 2168
1735(setup (:require savehist)
1736 (:option history-length t
1737 history-delete-duplicates t
1738 savehist-autosave-interval 60
1739 savehist-file (acdw/dir "savehist.el"))
1740
1741 (dolist (var '(extended-command-history
1742 global-mark-ring
1743 kill-ring
1744 regexp-search-ring
1745 search-ring
1746 mark-ring))
1747 (:option (append savehist-additional-variables) var))
1748
1749 (savehist-mode +1))
1750
1751(setup saveplace
1752 (:option save-place-file (acdw/dir "places.el")
1753 save-place-forget-unreadable-files (acdw/system :home))
1754
1755 (save-place-mode +1))
1756
1757(setup scratch
1758 (:option inhibit-startup-screen t
1759 initial-buffer-choice t
1760 initial-scratch-message ""
1761 ;; (concat ";; Howdy, "
1762 ;; (nth 0 (split-string
1763 ;; user-full-name))
1764 ;; "! "
1765 ;; "Welcome to GNU Emacs.\n\n")
1766 )
1767
1768 (add-hook 'kill-buffer-query-functions
1769 (defun kill-buffer-query@immortal-scratch ()
1770 (if (eq (current-buffer) (get-buffer "*scratch*"))
1771 (progn (bury-buffer)
1772 nil)
1773 t))))
1774
1775(setup scrolling
1776 (:option auto-window-vscroll nil
1777 fast-but-imprecise-scrolling t
1778 scroll-margin 3
1779 scroll-conservatively 101
1780 scroll-preserve-screen-position 1))
1781
1782(setup selection
1783 (:option save-interprogram-paste-before-kill t
1784 yank-pop-change-selection t
1785 x-select-enable-clipboard t
1786 x-select-enable-primary t
1787 mouse-drag-copy-region t
1788 kill-do-not-save-duplicates t)
1789
1790 (delete-selection-mode +1))
1791
1792(setup (:require server)
1793 (unless (server-running-p)
1794 (server-start)))
1795
1796(setup sh-mode
1797 (:option sh-basic-offset tab-width
1798 sh-indent-after-case 0
1799 sh-indent-for-case-alt '+
1800 sh-indent-for-case-label 0)
1801
1802 (:local-set indent-tabs-mode t)
1803
1804 (when (executable-find "shfmt")
1805 (with-eval-after-load 'apheleia
1806 (:option (append apheleia-formatters) '(shfmt . ("shfmt"))
1807 (append apheleia-mode-alist) '(sh-mode . shfmt))))
1808
1809 (when (executable-find "shellcheck")
1810 (:straight flymake-shellcheck)
1811 (:hook flymake-mode
1812 flymake-shellcheck-load)))
1813
1814(setup shell-command
1815 (:option shell-command-switch (acdw/system
1816 ;; I should be testing on some variable
1817 (:home "-csi")
1818 (:work "-c"))
1819 shell-command-prompt-show-cwd t
1820 shell-command-default-error-buffer "*shell-command-errors*"))
1821
1822(setup (:straight (shell-command+ 2169(setup (:straight (shell-command+
1823 :host nil 2170 :host nil
1824 :repo "https://git.sr.ht/~pkal/shell-command-plus")) 2171 :repo "https://git.sr.ht/~pkal/shell-command-plus"))
@@ -1827,14 +2174,6 @@ browser defined in `browse-url-secondary-browser-function'."
1827 (:bind "M-!" shell-command+)) 2174 (:bind "M-!" shell-command+))
1828 (:global "M-!" shell-command+)) 2175 (:global "M-!" shell-command+))
1829 2176
1830(setup shr
1831 (:option shr-width fill-column
1832 shr-max-width fill-column
1833 shr-max-image-proportion 0.6
1834 shr-image-animate t
1835 shr-discard-aria-hidden t
1836 shr-folding-mode t))
1837
1838(setup (:straight simple-modeline 2177(setup (:straight simple-modeline
1839 minions) 2178 minions)
1840 (:also-load acdw-modeline) 2179 (:also-load acdw-modeline)
@@ -1923,11 +2262,6 @@ browser defined in `browse-url-secondary-browser-function'."
1923(setup (:straight-if systemd 2262(setup (:straight-if systemd
1924 (executable-find "systemd"))) 2263 (executable-find "systemd")))
1925 2264
1926(setup text
1927 (:hook turn-on-auto-fill
1928 tildify-mode
1929 acdw/setup-fringes))
1930
1931(setup (:straight (topsy 2265(setup (:straight (topsy
1932 :host github 2266 :host github
1933 :repo "alphapapa/topsy.el")) 2267 :repo "alphapapa/topsy.el"))
@@ -1991,20 +2325,6 @@ If used with a numeric prefix argument N, N backticks will be inserted."
1991 (save-some-buffers t)) 2325 (save-some-buffers t))
1992 #'garbage-collect))) 2326 #'garbage-collect)))
1993 2327
1994(setup uniquify
1995 (:option uniquify-buffer-name-style 'forward
1996 uniquify-separator path-separator
1997 uniquify-after-kill-buffer-p t
1998 uniquify-ignore-buffers-re "^\\*"))
1999
2000(setup variable-pitch-mode
2001 ;; I might want to change this to `buffer-face-mode-hook'...
2002 (:advise variable-pitch-mode :after
2003 (defun variable-pitch-mode@setup (&rest _)
2004 "Set up `variable-pitch-mode' with my customizations."
2005 (display-fill-column-indicator-mode
2006 (if buffer-face-mode -1 +1)))))
2007
2008(setup (:straight (vertico 2328(setup (:straight (vertico
2009 :host github 2329 :host github
2010 :repo "minad/vertico" 2330 :repo "minad/vertico"
@@ -2042,12 +2362,6 @@ If used with a numeric prefix argument N, N backticks will be inserted."
2042 " ") 2362 " ")
2043 cand)))) 2363 cand))))
2044 2364
2045(setup view
2046 (:option view-read-only t)
2047
2048 (:hook (defun acdw/read-view-mode ()
2049 (reading-mode (if view-mode +1 -1)))))
2050
2051(setup (:straight visual-regexp) 2365(setup (:straight visual-regexp)
2052 (:global "M-%" #'vr/query-replace)) 2366 (:global "M-%" #'vr/query-replace))
2053 2367
@@ -2059,15 +2373,6 @@ If used with a numeric prefix argument N, N backticks will be inserted."
2059 (eshell-vterm-mode +1) 2373 (eshell-vterm-mode +1)
2060 (defalias 'eshell/v 'eshell-exec-visual)) 2374 (defalias 'eshell/v 'eshell-exec-visual))
2061 2375
2062(setup w32
2063 (:option w32-allow-system-shell t
2064 w32-pass-lwindow-to-system nil
2065 w32-lwindow-modifier 'super
2066 w32-pass-rwindow-to-system nil
2067 w32-rwindow-modifier 'super
2068 w32-pass-apps-to-system nil
2069 w32-apps-modifier 'hyper))
2070
2071(setup (:straight wc-mode) 2376(setup (:straight wc-mode)
2072 (:option wc-modeline-format "[%tww]" 2377 (:option wc-modeline-format "[%tww]"
2073 wc-idle-wait 2) 2378 wc-idle-wait 2)
@@ -2098,101 +2403,9 @@ If used with a numeric prefix argument N, N backticks will be inserted."
2098 (which-key-setup-side-window-right-bottom) 2403 (which-key-setup-side-window-right-bottom)
2099 (which-key-mode +1)) 2404 (which-key-mode +1))
2100 2405
2101(setup whitespace
2102 (:option whitespace-style '(empty
2103 indentation
2104 space-before-tab
2105 space-after-tab)
2106 indent-tabs-mode nil
2107 tab-width 4
2108 backward-delete-char-untabify-method 'hungry)
2109
2110 (:global "M-SPC" #'cycle-spacing))
2111
2112(setup (:straight whitespace-cleanup-mode) 2406(setup (:straight whitespace-cleanup-mode)
2113 (global-whitespace-cleanup-mode +1)) 2407 (global-whitespace-cleanup-mode +1))
2114 2408
2115(setup windmove
2116 (:option windmove-wrap-around t)
2117 (:global
2118 ;; moving
2119 "C-x 4 <left>" #'windmove-left
2120 "C-x 4 <right>" #'windmove-right
2121 "C-x 4 <up>" #'windmove-up
2122 "C-x 4 <down>" #'windmove-down
2123 ;; swapping
2124 "C-x 4 S-<left>" #'windmove-swap-states-left
2125 "C-x 4 S-<right>" #'windmove-swap-states-right
2126 "C-x 4 S-<up>" #'windmove-swap-states-up
2127 "C-x 4 S-<down>" #'windmove-swap-states-down)
2128
2129 ;; (when (fboundp 'repeat-mode)
2130 ;; (defvar windmove-repeat-map
2131 ;; (let ((map (make-sparse-keymap)))
2132 ;; ;; moving
2133 ;; (define-key map [left] #'windmove-left)
2134 ;; (define-key map [right] #'windmove-right)
2135 ;; (define-key map [up] #'windmove-up)
2136 ;; (define-key map [down] #'windmove-down)
2137 ;; ;; swapping
2138 ;; (define-key map [S-left] #'windmove-swap-states-left)
2139 ;; (define-key map [S-right] #'windmove-swap-states-right)
2140 ;; (define-key map [S-up] #'windmove-swap-states-up)
2141 ;; (define-key map [S-down] #'windmove-swap-states-down)
2142 ;; map)
2143 ;; "Keymap to repeat various `windmove' sequences. Used in `repeat-mode'.")
2144
2145 ;; (dolist (sym '(windmove-left
2146 ;; windmove-right
2147 ;; windmove-up
2148 ;; windmove-down
2149 ;; windmove-swap-states-left
2150 ;; windmove-swap-states-right
2151 ;; windmove-swap-states-up
2152 ;; windmove-swap-states-down))
2153 ;; (put sym 'repeat-map 'windmove-repeat-map)))
2154 )
2155
2156(setup window
2157 (require 'acdw-bell)
2158 (:option
2159 ;; Man-notify-method 'pushy
2160 ;; display-buffer-alist ; from FrostyX
2161 ;; '(("shell.*" (display-buffer-same-window) ())
2162 ;; (".*" (display-buffer-reuse-window
2163 ;; display-buffer-same-window)
2164 ;; (reusable-frames . t)))
2165 recenter-positions '(top middle bottom)
2166 ring-bell-function (lambda ()
2167 (acdw-bell/flash-mode-line
2168 (acdw/system :home)))
2169 use-dialog-box nil
2170 use-file-dialog nil
2171 visible-bell nil)
2172
2173 (tooltip-mode -1))
2174
2175(setup winner
2176 ;; see https://lists.gnu.org/archive/html/emacs-devel/2021-08/msg00888.html
2177 (:global "C-x 4 C-/" #'winner-undo
2178 "C-x 4 /" #'winner-undo
2179 "C-x 4 C-?" #'winner-redo
2180 "C-x 4 ?" #'winner-redo)
2181
2182 ;; add `winner-undo' and `winner-redo' to `repeat-mode'
2183 ;; (when (fboundp 'repeat-mode)
2184 ;; (defvar winner-mode-repeat-map
2185 ;; (let ((map (make-sparse-keymap)))
2186 ;; (define-key map "/" #'winner-undo)
2187 ;; (define-key map "?" #'winner-redo)
2188 ;; map)
2189 ;; "Keymap to repeat `winner-mode' sequences. Used in `repeat-mode'.")
2190
2191 ;; (put 'winner-undo 'repeat-map 'winner-mode-repeat-map)
2192 ;; (put 'winner-redo 'repeat-map 'winner-mode-repeat-map))
2193
2194 (winner-mode +1))
2195
2196(setup (:straight winum) 2409(setup (:straight winum)
2197 (:option winum-scope 'frame-local 2410 (:option winum-scope 'frame-local
2198 winum-auto-setup-mode-line nil 2411 winum-auto-setup-mode-line nil
diff --git a/lisp/acdw.el b/lisp/acdw.el index 40aff5d..dcf7b19 100644 --- a/lisp/acdw.el +++ b/lisp/acdw.el
@@ -265,10 +265,16 @@ With a prefix argument N, (un)comment that many sexps."
265;; from https://github.com/alphapapa/unpackaged.el#sort-sexps 265;; from https://github.com/alphapapa/unpackaged.el#sort-sexps
266;; and https://github.com/alphapapa/unpackaged.el/issues/20 266;; and https://github.com/alphapapa/unpackaged.el/issues/20
267 267
268(defun sort-sexps (beg end &optional key) 268(defun sort-sexps (beg end &optional key-fn sort-fn)
269 "Sort sexps between BEG and END. 269 "Sort sexps between BEG and END.
270Comments stay with the code below. KEY is a function to sort by, 270Comments stay with the code below.
271e.g. (lambda (sexp) (symbol-name (car sexp)))" 271
272Optional argument KEY-FN will determine where in each sexp to
273start sorting. e.g. (lambda (sexp) (symbol-name (car sexp)))
274
275Optional argument SORT-FN will determine how to sort two sexps'
276strings. It's passed to `sort'. By default, it sorts the sexps
277with `string<' starting with the key determined by KEY-FN."
272 (interactive "r") 278 (interactive "r")
273 (cl-flet ((skip-whitespace () (while (looking-at (rx (1+ (or space "\n")))) 279 (cl-flet ((skip-whitespace () (while (looking-at (rx (1+ (or space "\n"))))
274 (goto-char (match-end 0)))) 280 (goto-char (match-end 0))))
@@ -298,8 +304,8 @@ e.g. (lambda (sexp) (symbol-name (car sexp)))"
298 (save-excursion 304 (save-excursion
299 (goto-char (marker-position start)) 305 (goto-char (marker-position start))
300 (skip-both) 306 (skip-both)
301 (if key 307 (if key-fn
302 (funcall key sexp) 308 (funcall key-fn sexp)
303 (buffer-substring 309 (buffer-substring
304 (point) 310 (point)
305 (marker-position end))))) 311 (marker-position end)))))
@@ -307,8 +313,9 @@ e.g. (lambda (sexp) (symbol-name (car sexp)))"
307 collect (cons start end) 313 collect (cons start end)
308 into markers 314 into markers
309 finally return (list sexps markers)) 315 finally return (list sexps markers))
310 (setq sexps (sort sexps (lambda (a b) 316 (setq sexps (sort sexps (if sort-fn sort-fn
311 (string< (cdr a) (cdr b))))) 317 (lambda (a b)
318 (string< (cdr a) (cdr b))))))
312 (cl-loop for (real . sort) in sexps 319 (cl-loop for (real . sort) in sexps
313 for (start . end) in markers 320 for (start . end) in markers
314 do (progn 321 do (progn
@@ -688,5 +695,18 @@ When called with PREFIX, just kill Emacs without confirmation."
688 (ignore-errors 695 (ignore-errors
689 (delete-frame)))) 696 (delete-frame))))
690 697
698
699;;; cribbed
700
701;; https://jao.io/blog/2021-09-08-high-signal-to-noise-emacs-command.html
702(defun jao-buffer-same-mode (&rest modes)
703 "Pop to a buffer with a mode among MODES, or the current one if not given."
704 (interactive)
705 (let* ((modes (or modes (list major-mode)))
706 (pred (lambda (b)
707 (let ((b (get-buffer (if (consp b) (car b) b))))
708 (member (buffer-local-value 'major-mode b) modes)))))
709 (pop-to-buffer (read-buffer "Buffer: " nil t pred))))
710
691(provide 'acdw) 711(provide 'acdw)
692;;; acdw.el ends here 712;;; acdw.el ends here