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