summary refs log tree commit diff stats
path: root/init.el
diff options
context:
space:
mode:
Diffstat (limited to 'init.el')
-rw-r--r--init.el933
1 files changed, 4 insertions, 929 deletions
diff --git a/init.el b/init.el index 0ef669f..369641c 100644 --- a/init.el +++ b/init.el
@@ -1,932 +1,7 @@
1;;; init.el --- a config of one's own -*- lexical-binding: t; -*- 1;;; init.el --- An Emacs of one's own -*- lexical-binding: t -*-
2;; by C. Duckworth <acdw@acdw.net>
3;; Bankruptcy: 9.3
4 2
5;;; Code: 3;; Bankruptcy: 9.4
6
7;;; My extras
8
9(push (expand-file-name (locate-user-emacs-file "lisp")) load-path)
10(require 'acdw) ; Omnibus fun stuff
11
12;;; Remove when done bankrupting
13
14(defkeys t "C-x C-c" #'restart-emacs)
15
16;;; Basic defaults
17
18(use-package no-littering
19 :ensure t :demand t
20 :preface
21 (setq no-littering-etc-directory etc/
22 no-littering-var-directory var/)
23 :custom
24 (auto-save-file-name-transforms `(("." ,(var/ "auto-save/") t)))
25 (auto-save-list-file-prefix (var/ "auto-save/.saves-" t))
26 (backup-directory-alist `(("." . ,(var/ "backup/" t)))))
27
28(use-package custom-allowed
29 :load-path "~/src/emacs/custom-allowed/"
30 :custom
31 (custom-file (private/ "custom.el"))
32 :config
33 (dolist (var '(safe-local-variable-values
34 warning-suppress-types
35 ispell-buffer-session-localwords
36 calendar-latitude
37 calendar-longitude
38 user-full-name
39 user-mail-address))
40 (add-to-list 'custom-allowed-variables var))
41 :hook
42 (after-init-hook . custom-allowed-load-custom-file))
43
44(use-package modus-themes
45 :load-path "~/usr/share/emacs/30.0.50/etc/themes/"
46 :custom
47 (modus-themes-bold-constructs t)
48 (modus-themes-italic-constructs t)
49 (modus-themes-variable-pitch-ui nil))
50
51(use-package dawn
52 :load-path "~/src/emacs/dawn/"
53 :after modus-themes
54 :config
55 (load-theme 'modus-operandi :noconfirm :noenable)
56 (load-theme 'modus-vivendi :noconfirm :noenable)
57 (defhook custom-allowed-after-load-hook
58 (dawn-schedule-themes 'modus-operandi
59 'modus-vivendi)
60 (set-face-attribute 'default nil
61 :family "IBM Plex Mono"
62 :height 100)
63 (set-face-attribute 'variable-pitch nil
64 :family "Georgia"
65 :height 1.2)))
66
67(use-package midnight
68 :config
69 (add-hook 'midnight-mode-hook #'recentf-cleanup)
70 (midnight-mode))
71
72(use-package sophomore
73 :load-path "~/src/emacs/sophomore/"
74 :config
75 (sophomore-enable-all)
76 (sophomore-disable 'view-hello-file
77 'describe-gnu-project
78 'suspend-frame)
79 (sophomore-mode))
80
81;;; Completions
82
83(use-package vertico
84 :ensure t :demand t
85 :custom
86 (resize-mini-windows 'grow-only)
87 (vertico-cycle t)
88 :config
89 (use-package vertico-directory
90 :after vertico
91 :hook (rfn-eshadow-update-overlay-hook . vertico-directory-tidy))
92 (vertico-mode))
93
94(use-package marginalia
95 :ensure t :demand t
96 :config
97 (add-hook 'minibuffer-setup-hook #'truncate-lines-local-mode)
98 (marginalia-mode))
99
100(use-package orderless
101 :ensure t :demand t
102 :config
103 (setc completion-styles '(orderless basic)
104 completion-category-overrides
105 '((file (styles basic partial-completion)))))
106
107(use-package consult
108 :ensure t
109 :custom
110 (register-preview-delay 0.01)
111 (register-preview-function #'consult-register-format)
112 (xref-show-xrefs-function #'consult-xref)
113 (tab-always-indent 'complete)
114 (completion-in-region-function #'consult-completion-in-region)
115 (consult-narrow-key "<")
116 (consult--regexp-compiler #'consult--default-regexp-compiler)
117 :config
118 (advice-add #'register-preview :override #'consult-register-window)
119 (define-advice completing-read-multiple (:filter-args (args) indicator)
120 (cons (format "[CRM%s] %s"
121 (replace-regexp-in-string
122 "\\`\\[.*?]\\*\\|\\[.*?]\\*\\'" ""
123 crm-separator)
124 (car args))
125 (cdr args)))
126 :bind
127 (([remap switch-to-buffer] . consult-buffer)
128 ([remap switch-to-buffer-other-window] . consult-buffer-other-window)
129 ([remap switch-to-buffer-other-frame] . consult-buffer-other-frame)
130 ([remap yank-pop] . consult-yank-pop)
131 ("M-g g" . consult-goto-line)
132 ("M-g M-g" . consult-goto-line)
133 ("M-g i" . consult-imenu)
134 ("M-g M-i" . consult-imenu)
135 ("M-s l" . consult-line)
136 ("M-s f" . consult-find)
137 ("M-s M-f" . consult-find)
138 ("M-s g" . consult-grep)
139 ("M-s M-g" . consult-grep)))
140
141;;; General enhancements
142
143(use-package embark
144 :ensure t
145 :custom
146 (prefix-help-command #'embark-prefix-help-command)
147 :bind
148 (("C-." . embark-act)
149 ("M-." . embark-dwim)
150 ("C-h b" . embark-bindings))
151 :custom
152 (add-to-list 'display-buffer-alist
153 '("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*"
154 nil
155 (window-parameters (mode-line-format . none)))))
156
157(use-package embark-consult
158 :ensure t :demand t
159 :after (embark consult)
160 :hook (embark-collect-mode-hook . consult-preview-at-point-mode))
161
162(use-package undo-fu-session
163 :ensure t
164 :custom
165 (undo-fu-session-directory (etc/ "undo/" t))
166 (undo-fu-session-incompatible-files
167 '("/COMMIT_EDITMSG\\'"
168 "/git-rebase-todo\\'"))
169 (undo-fu-session-compression
170 (cl-loop for (exe . sym) in '(("gzip" . gz)
171 ("bzip2" . bz2)
172 ("xz" . xz))
173 if (executable-find exe)
174 return sym))
175 :config
176 (global-undo-fu-session-mode))
177
178(use-package ws-butler
179 :ensure t
180 :custom
181 (ws-butler-trim-predicate (lambda (begin end)
182 (not (eq 'font-lock-string-face
183 (get-text-property end 'face)))))
184 :config
185 (ws-butler-global-mode))
186
187(use-package minions
188 :ensure t
189 :config
190 (minions-mode))
191
192(use-package mode-line-bell
193 :vc ( :url "https://github.com/duckwork/mode-line-bell"
194 :rev "remap-face")
195 :custom
196 (mode-line-bell-flash-time 0.25)
197 :config
198 (mode-line-bell-mode))
199
200(use-package electric-cursor
201 :load-path "~/src/emacs/electric-cursor/"
202 :custom
203 (electric-cursor-alist '((overwrite-mode . box)
204 (t . bar)))
205 (electric-cursor-mode))
206
207(use-package visual-fill-column
208 :ensure t
209 :custom
210 (visual-fill-column-center-text t)
211 :hook ((visual-fill-column-mode-hook . visual-line-mode)
212 (eww-mode-hook . visual-fill-column-mode))
213 :config
214 (advice-add 'text-scale-adjust :after #'visual-fill-column-adjust))
215
216(use-package cape
217 :ensure t :demand t
218 :init
219 (dolist (fn '(cape-file cape-dabbrev))
220 (add-hook 'completion-at-point-functions fn 90))
221 :config
222 (require '+cape)
223 (advice-add 'emacs-completion-at-point :around #'cape-wrap-nonexclusive)
224 (+cape-insinuate text-mode-hook ( cape-dict cape-ispell
225 cape-file cape-dabbrev)))
226
227(use-package wgrep
228 :ensure t
229 :custom
230 (wgrep-enable-key (kbd "C-x C-q"))
231 :bind (:map grep-mode-map
232 ("C-x C-q" . wgrep-change-to-wgrep-mode)))
233
234(use-package mlscroll
235 :ensure t :defer 1
236 :preface
237 (defhook modus-themes-after-load-theme-hook
238 :name modus-themes-load@mlscroll
239 (mlscroll-mode -1)
240 (when
241 (or
242 (memq 'modus-vivendi custom-enabled-themes)
243 (memq 'modus-operandi custom-enabled-themes))
244 (modus-themes-with-colors
245 (setf mlscroll-in-color fg-dim mlscroll-out-color bg-inactive)))
246 (eval-after 1
247 (mlscroll-mode 1)))
248 :init
249 (when (daemonp)
250 (add-hook 'server-after-make-frame #'modus-themes-load@mlscroll))
251 :config (modus-themes-load@mlscroll))
252
253(use-package avy
254 :ensure t :demand t
255 :custom
256 (avy-background t)
257 (avy-keys (string-to-list "asdfghjklqwertyuiopzxcvbnm"))
258 :bind (("M-j" . avy-goto-char-timer)
259 :map isearch-mode-map
260 ("M-j" . avy-isearch)))
261
262(use-package zzz-to-char
263 :ensure t
264 :bind (("M-z" . zzz-to-char)))
265
266;;; Searching
267
268(use-package isearch-mb
269 :ensure t
270 :custom
271 (isearch-lazy-count t)
272 (isearch-regexp-lax-whitespace t)
273 ;; Space matches whitespace, newlines, punctuation
274 (search-whitespace-regexp "\\W+")
275 (search-default-mode t "Search using regexp by default.")
276 ;; Space matches any sequence of characters in a line
277 ;; search-whitespace-regexp ".*?"
278 (isearch-wrap-pause 'no)
279 :config
280 (require '+isearch)
281 (advice-add 'isearch-cancel :before
282 #'+isearch-cancel@add-search-to-history)
283 (advice-add 'perform-replace :around
284 #'+perform-replace-dont-exit-on-anykey)
285 (eval-after (isearch-mb consult)
286 (add-to-list 'isearch-mb--after-exit #'consult-line)
287 (add-to-list 'isearch-mb--with-buffer #'consult-isearch-history)
288 (defkeys isearch-mb-minibuffer-map
289 "M-s l" #'consult-line
290 "M-r" #'consult-isearch-history))
291 (eval-after (isearch-mb anzu)
292 (add-to-list 'isearch-mb--after-exit #'anzu-isearch-query-replace)
293 (defkeys isearch-mb-minibuffer-map
294 "M-%" #'anzu-isearch-query-replace-regexp
295 "C-M-%" #'anzu-isearch-query-replace))
296 (isearch-mb-mode))
297
298(use-package anzu
299 :ensure t
300 :bind
301 (("M-%" . anzu-query-replace-regexp)
302 ("C-M-%" . anzu-query-replace)))
303
304(use-package frowny
305 :load-path "~/src/emacs/frowny/"
306 :config
307 (global-frowny-mode))
308
309(use-package transpose-frame
310 :ensure t
311 :bind
312 (("C-x 5 t" . transpose-frame)))
313
314;;; Text editing
315
316(use-package org
317 :defer t
318 :after derived
319 :init
320 (require 'init-org)
321 (require '_work))
322
323(use-package ispell
324 :custom
325 (ispell-program-name (choose-executable "ispell" "aspell"))
326 :config
327 (require '+ispell)
328 (add-hook 'before-save-hook
329 #'+ispell-move-buffer-words-to-dir-locals-hook)
330 (put 'ispell-buffer-session-localwords 'safe-local-variable
331 #'+ispell-safe-local-p))
332
333(use-package flyspell
334 :hook org-mode-hook)
335
336(use-package flyspell-correct
337 :ensure t
338 :after flyspell
339 :custom
340 (flyspell-correct--cr-key ";")
341 :bind
342 (:map flyspell-mode-map
343 (("C-;" . flyspell-correct-wrapper)
344 ("<f7>" . +flyspell-correct-buffer)))
345 :config
346 (require '+flyspell-correct)
347 (defkeys flyspell-mode-map
348 "C-," nil
349 "C-." nil))
350 4
351(use-package text-mode 5;;; Code:
352 :config
353 (defhook text-mode-hook
354 #'abbrev-mode))
355
356(use-package filldent
357 :load-path "~/src/emacs/filldent/"
358 :bind
359 ("M-q" . filldent-dwim))
360
361(use-package scule
362 :load-path "~/src/emacs/scule/"
363 :config
364 (defkeys t
365 "M-c" (defmap scule-map
366 "Keymap for twiddling scules."
367 "M-u" #'scule-upcase
368 "M-l" #'scule-downcase
369 "M-c" #'scule-capitalize)))
370
371(use-package titlecase
372 :load-path "~/src/emacs/titlecase.el/"
373 :after org
374 :bind (:map scule-map
375 ("M-t" . titlecase-dwim))
376 :config
377 (require '+titlecase))
378
379;;; Programming
380
381(use-package prog-mode
382 :config
383 (defhook prog-mode-hook
384 #'auto-fill-mode
385 ;; Use `indent-tabs-mode' unless one of the following modes
386 (indent-tabs-mode (if (derived-mode-p 'emacs-lisp-mode
387 'python-mode
388 'haskell-mode)
389 -1 1))))
390
391(use-package paredit
392 :ensure t
393 :preface
394 (defun +paredit-newline ()
395 (interactive)
396 (call-interactively
397 (if (derived-mode-p 'lisp-interaction-mode)
398 #'eval-print-last-sexp
399 #'paredit-newline)))
400 :hook ((emacs-lisp-mode-hook
401 eval-expression-minibuffer-setup-hook
402 ielm-mode-hook lisp-interaction-mode-hook
403 lisp-mode-hook scheme-mode-hook
404 fennel-repl-mode-hook fennel-mode-hook
405 geiser-mode-hook geiser-repl-mode-hook
406 ielm-mode-hook)
407 . enable-paredit-mode)
408 :bind
409 (("C-j" . +paredit-newline))
410 :config
411 (defkeys paredit-mode-map
412 "RET" nil
413 "M-s" nil)
414 (require '+paredit)
415 (add-to-list 'paredit-space-for-delimiter-predicates
416 #'+paredit-space-for-delimiter)
417 (eval-after (paredit eldoc)
418 (eldoc-add-command #'paredit-backward-delete #'paredit-close-round)))
419
420(use-package hungry-delete
421 :ensure t
422 :custom
423 (hungry-delete-chars-to-skip " \t")
424 (hungry-delete-join-reluctantly nil)
425 :config
426 (dolist (m '(eshell-mode
427 nim-mode
428 python-mode))
429 (add-to-list 'hungry-delete-except-modes m))
430 (require '+hungry-delete)
431 (eval-after paredit
432 (defkeys paredit-mode-map
433 [remap paredit-backward-delete]
434 (+hungry-delete-define-alternative
435 paredit-backward-delete hungry-delete-backward)
436 [remap paredit-forward-delete]
437 (+hungry-delete-define-alternative
438 paredit-forward-delete hungry-delete-forward)))
439 (global-hungry-delete-mode))
440
441(use-package ediff
442 :custom
443 (ediff-keep-variants nil)
444 (ediff-split-window-function #'split-window-horizontally)
445 (ediff-window-setup-function #'ediff-setup-windows-plain))
446
447;;; Lisps
448
449(use-package elisp-mode
450 :custom
451 (eval-expression-print-length nil)
452 (eval-expression-print-level nil)
453 :preface
454 (defun elisp-eval-region|eval-buffer ()
455 (interactive)
456 (if (region-active-p)
457 (let ((start (region-beginning))
458 (end (region-end)))
459 (eval-region start end)
460 (message "Region from %s to %s evaluated."
461 start end))
462 (eval-buffer)
463 (message "Buffer `%s' evaluated." (buffer-name))))
464 (defkeys (emacs-lisp-mode-map lisp-interaction-mode-map)
465 "C-c C-c" #'eval-defun
466 "C-c C-k" #'elisp-eval-region|eval-buffer
467 "C-c C-z" #'ielm)
468 :config
469 (define-advice eval-region (:around (orig start end &rest args) pulse)
470 (apply orig start end args)
471 (pulse-momentary-highlight-region start end))
472 (defhook emacs-lisp-mode-hook
473 (setq-local page-delimiter "^\\( \\|;;;+\\).*")))
474
475(use-package macrostep
476 :ensure t
477 :after elisp-mode
478 :bind ( :map emacs-lisp-mode-map
479 ("C-c e" . macrostep-expand)
480 :map lisp-interaction-mode-map
481 ("C-c e" . macrostep-expand)))
482
483(use-package eros
484 :ensure t
485 :after elisp-mode
486 :custom (eros-eval-result-prefix "; ")
487 :hook emacs-lisp-mode-hook)
488
489(use-package package-lint
490 :ensure t)
491
492(use-package sly
493 :ensure t
494 :when (executable-find "sbcl")
495 :custom
496 (inferior-lisp-program (executable-find "sbcl"))
497 (sly-net-coding-system 'utf-8-unix)
498 :bind (:map sly-mode-map
499 (("C-c C-z" . sly-mrepl)))
500 :config
501 (sly-symbol-completion-mode -1))
502
503(use-package edebug
504 :preface
505 (defun turn-off-eldoc-mode ()
506 (eldoc-mode -1))
507 :config
508 (add-hook 'edebug-mode-hook #'turn-off-eldoc-mode))
509
510;;; Web languages
511
512(use-package web-mode
513 :ensure t
514 :mode ("\\.phtml\\'"
515 "\\.tpl\\.php\\'"
516 "\\.[agj]sp\\'"
517 "\\.as[cp]x\\'"
518 "\\.erb\\'"
519 "\\.mustache\\'"
520 "\\.djhtml\\'"
521 "\\.html?\\'"))
522
523;;; Applications
524
525(use-package dired
526 :init (require 'dired-x)
527 :custom
528 (dired-recursive-copies 'always)
529 (dired-recursive-deletes 'always)
530 (dired-create-destination-dirs 'always)
531 (dired-do-revert-buffer t)
532 (dired-hide-details-hide-symlink-targets nil)
533 (dired-isearch-filenames 'dwim)
534 (delete-by-moving-to-trash t)
535 (dired-auto-revert-buffer t)
536 (dired-listing-switches "-AlF")
537 (ls-lisp-dirs-first t)
538 (dired-ls-F-marks-symlinks t)
539 (dired-clean-confirm-killing-deleted-buffers nil)
540 (dired-no-confirm '(byte-compile
541 load chgrp chmod chown
542 copy move hardlink symlink
543 shell touch))
544 (dired-dwim-target t)
545 :bind
546 (("C-x C-j" . dired-jump)
547 ([remap list-directory] . dired)
548 :map dired-mode-map
549 ("C-j" . dired-up-directory)
550 ("<backspace>" . dired-up-directory))
551 :init
552 (defhook dired-mode-hook
553 #'dired-hide-details-mode
554 #'hl-line-mode
555 #'truncate-lines-local-mode))
556
557(use-package dired-subtree
558 :ensure t
559 :after dired
560 :bind (:map dired-mode-map
561 (("TAB" . dired-subtree-cycle)
562 ("i" . dired-subtree-toggle))))
563
564(use-package dired-collapse
565 :ensure t
566 :hook dired-mode-hook)
567
568(use-package dired-hide-dotfiles
569 :ensure t
570 :bind (:map dired-mode-map
571 ("." . dired-hide-dotfiles-mode)))
572
573(use-package magit
574 :ensure t
575 :bind
576 ("C-x g" . magit))
577
578(use-package auth-source
579 :custom
580 (auth-sources '(default "secrets:passwords"))
581 :config
582 (defhook authinfo-mode-hook
583 #'truncate-lines-local-mode))
584
585(use-package keychain-environment
586 :ensure t
587 :when (executable-find "keychain")
588 :hook (after-init-hook . keychain-refresh-environment))
589
590(use-package keepassxc-shim
591 :load-path "~/src/emacs/keepassxc-shim/"
592 :config
593 (keepassxc-shim-activate))
594
595(use-package eat
596 :ensure t
597 :commands eat-eshell-mode
598 :hook (eshell-load-hook . eat-eshell-mode))
599
600(use-package dictionary
601 :custom
602 (dictionary-server (if (or (executable-find "dictd")
603 (file-exists-p "/usr/sbin/dictd")) ; debian
604 "localhost"
605 "dict.org"))
606 :bind
607 (("C-c d" . dictionary-search)))
608
609(use-package pdf-tools
610 :ensure t
611 :mode ("\\.[pP][dD][fF]\\'" . pdf-view-mode)
612 :magic ("%PDF" . pdf-view-mode)
613 :config
614 (pdf-tools-install))
615
616;;; Mail
617
618(use-package bbdb
619 :ensure t
620 :custom
621 (bbdb-complete-mail-allow-cycling t)
622 (bbdb-file (private/ "bbdb"))
623 :init
624 (defhook custom-allowed-after-load-hook
625 :name bbdb@after-custom
626 (require 'bbdb)
627 (require 'bbdb-message)
628 (bbdb-initialize 'message)))
629
630(use-package bbdb-vcard
631 :ensure t)
632
633(use-package notmuch
634 :load-path "~/usr/share/emacs/site-lisp/"
635 :preface
636 (defdir notmuch/ (sync/ "emacs/notmuch"))
637 :init
638 (use-package +notmuch
639 :after notmuch
640 :load-path "lisp/"
641 :bind (("C-c n" . +notmuch-goto)
642 :map notmuch-search-mode-map
643 ("!" . +notmuch-search-mark-spam)
644 :map notmuch-tree-mode-map
645 ("!" . +notmuch-search-mark-spam-then-next)
646 ("M-<" . +notmuch-tree-beginning)
647 ("M->" . +notmuch-tree-end))
648 :hook (message-send-hook . +send-mail-dispatch)
649 :config
650 ;; Saved searches
651 (+notmuch-make-saved-search "inbox+unread" "m" 'tree "tag:inbox" "tag:unread" "NOT tag:Spam")
652 (+notmuch-make-saved-search "inbox" "i" 'tree "tag:inbox" "NOT tag:Spam")
653 (+notmuch-make-saved-search "lists+unread" "l" 'tree "tag:/List/" "tag:unread")
654 (+notmuch-make-saved-search "lists" "L" 'tree "tag:/List/")
655 (+notmuch-make-saved-search "unread" "u" 'tree "tag:unread" "NOT tag:Spam")
656 (+notmuch-make-saved-search "flagged" "f" 'tree "tag:flagged")
657 (+notmuch-make-saved-search "sent" "t" 'tree "tag:sent")
658 (+notmuch-make-saved-search "drafts" "d" 'tree "tag:draft")
659 (+notmuch-make-saved-search "all mail" "a" 'tree "*"))
660 (use-package message
661 :after notmuch
662 :hook (message-setup-hook . message-signature-setup)
663 :config (require '+message))
664 (defhook (notmuch-show-mode-hook notmuch-message-mode-hook)
665 #'visual-fill-column-mode)
666 :custom
667 (notmuch-init-file (notmuch/ "notmuch-init.el" t))
668 (notmuch-address-save-filename (notmuch/ "addresses" t))
669 (notmuch-address-use-company (featurep 'company))
670 (notmuch-search-oldest-first nil)
671 (notmuch-archive-tags '("-inbox" "-unread"))
672 (notmuch-draft-tags '("+draft" "-inbox" "-unread"))
673 (mail-user-agent 'notmuch-user-agent)
674 (bbdb-mail-user-agent 'notmuch-user-agent)
675 (message-mail-user-agent t)
676 (notmuch-show-indent-content nil)
677 (message-kill-buffer-on-exit t)
678 (message-auto-save-directory nil)
679 (send-mail-function #'sendmail-send-it)
680 (mail-specify-envelope-from t)
681 (message-sendmail-envelope-from 'header)
682 (message-envelope-from 'header)
683 (notmuch-saved-searches nil)
684 :bind
685 (("C-c m" . notmuch-mua-new-mail)
686 :map notmuch-search-mode-map
687 ("RET" . notmuch-search-show-thread)
688 ("M-RET" . notmuch-tree-from-search-thread))
689 :config
690 (load notmuch-init-file :noerror)
691 (advice-add 'notmuch-tag :filter-args #'+notmuch-correct-tags)
692 ;; Mailing lists
693 (add-to-list 'notmuch-message-headers "List-Post" :append)
694 (define-advice notmuch-mua-new-reply (:around (orig &rest r) list-aware)
695 "Make `notmuch-mua-new-reply' list-aware."
696 (let ((ml (notmuch-show-get-header :List-Post)))
697 (apply orig r)
698 (when ml
699 (with-buffer-modified-unmodified
700 (message-remove-header "To")
701 (message-add-header
702 (format "To: %s"
703 (replace-regexp-in-string "<mailto:\\(.*\\)>" "\\1" ml)))
704 (message-goto-body))))))
705
706;;; The INTERNET
707
708(use-package link-hint
709 :ensure t :demand t
710 :preface
711 (global-set-key (kbd "M-l") nil)
712 :custom
713 (link-hint-avy-style 'at-full)
714 (link-hint-avy-all-windows t)
715 :config
716 (require '+link-hint)
717 (+link-hint-open-secondary-setup)
718 (+link-hint-open-chrome-setup)
719 :bind
720 (("M-l M-l" . +link-hint-open-link)
721 ("M-l l" . +link-hint-open-link)
722 ("M-l M-o" . +link-hint-open-secondary)
723 ("M-l o" . +link-hint-open-secondary)
724 ("M-l M-m" . +link-hint-open-multiple-links)
725 ("M-l m" . +link-hint-open-multiple-links)
726 ("M-l M-w" . link-hint-copy-link)
727 ("M-l w" . link-hint-copy-link)
728 ("M-l M-c" . +link-hint-open-chrome)
729 ("M-l c" . +link-hint-open-chrome)))
730
731(use-package browse-url
732 :demand t
733 :preface
734 (require '+browse-url)
735 :config
736 (eval-after chd
737 (add-to-list 'browse-url-handlers (cons chd/url-regexps
738 #'browse-url-chrome))
739 (add-to-list '+browse-url-other-safe-browser-functions
740 #'chd/browse-url))
741 (put 'browse-url-browser-function 'safe-local-variable
742 #'+browse-url-browser-function-safe-p)
743 :custom
744 (browse-url-browser-function #'eww-browse-url)
745 (browse-url-chromium-program (choose-executable "chromium"))
746 (browse-url-chrome-program (choose-executable "chrome" "google-chrome-stable"))
747 (browse-url-firefox-program (choose-executable "firefox" "firefox-esr"))
748 (browse-url-firefox-new-window-is-tab t)
749 (browse-url-firefox-arguments '("--new-tab"))
750 (browse-url-generic-program (or browse-url-firefox-program
751 browse-url
752 browse-url-chrome-program))
753 (browse-url-generic-args
754 (cl-loop for prog in '(firefox chromium chrome)
755 for progfn = (intern (format "browse-url-%s-program"
756 prog))
757 for progargs = (intern (format "browse-url-%s-arguments"
758 prog))
759 if (equal browse-url-generic-program
760 (symbol-value progfn))
761 return (symbol-value progargs)
762 finally return nil))
763 (browse-url-handlers
764 `(;; Videos
765 (,(+browse-url-matches "youtube\\.com" "youtu\\.be"
766 "invidious" "yewtu\\.be"
767 (rx "." (or "mp4" "gif" "mov" "MOV" "webm")
768 eos))
769 . +browse-url-with-mpv)
770 ;; Music
771 (,(+browse-url-matches "soundcloud\\.com" "bandcamp\\.com"
772 (rx "." (or "ogg" "mp3" "opus" "m4a") eos))
773 . +browse-url-with-mpv)
774 ;; Images
775 (,(+browse-url-matches "pbs\\.twimg\\.com"
776 (rx "." (or "jpeg" "jpg" "png" "bmp" "webp")
777 eos))
778 . +browse-url-with-mpv-image)
779 ;; Blobs (binary files)
780 (,(+browse-url-matches (rx "." (or ".tar.gz" ".pdf") eos))
781 . +browse-url-download)
782 ;; External URLs --- these are URLs that don't open in EWW very well,
783 ;; so I want to open them in the external browser.
784 (+browse-url-external-url-p . ,(if (featurep 'xwidget-internal)
785 #'xwidget-webkit-browse-url
786 browse-url-secondary-browser-function))))
787 (+browse-url-external-domains '("github.com" "gitlab.com" "codeberg.org"
788 "tildegit.org" "git.tilde.town"
789 "google.com" "imgur.com" "twitch.tv"
790 "pixelfed" "instagram.com"
791 "bibliogram.art" "reddit.com"
792 "teddit.net" "libreddit.de"
793 "streamable.com" "spotify.com"
794 "hetzner.cloud" "melpa.org"
795 "twitter.com" ("^t\\.co$")
796 "nitter.snopyta.org" "nitter.net")))
797
798(use-package browse-url-transform
799 :after browse-url
800 :load-path "~/src/emacs/browse-url-transform/"
801 :custom
802 (browse-url-transform-alist
803 `(;; Privacy-respecting alternatives
804 ("twitter\\.com" . "nitter.snopyta.org")
805 ("\\(?:\\(?:old\\.\\)?reddit\\.com\\)" . "libreddit.de")
806 ("medium\\.com" . "scribe.rip")
807 (".*substack\\.com.*" . ,substack-proxy)
808 ;; Text-mode of non-text-mode sites
809 ("www\\.npr\\.org" . "text.npr.org")
810 ;; Ask for raw versions of paste sites
811 ("^.*dpaste\\.com.*$" . "\\&.txt")
812 ("bpa\\.st/\\(.*\\)" . "bpa.st/raw/\\1")
813 ("\\(paste\\.debian\\.net\\)/\\(.*\\)" . "\\1/plain/\\2")
814 ("\\(pastebin\\.com\\)/\\\(.*\\)" . "\\1/raw/\\2")
815 ("\\(paste\\.centos\\.org/view\\)/\\(.*\\)" . "\\1/raw/\\2")))
816 :config
817 (browse-url-transform-mode))
818
819(use-package eww
820 :custom
821 (eww-use-browse-url ".")
822 :config
823 (defhook eww-mode-hook
824 (defhook ((visual-fill-column-mode nil :local))
825 :name visual-fill-column@eww-mode-refresh
826 (eww-reload t)))
827 (defkeys eww-mode-map
828 "&" (+browse-url-switch-external-browser eww-mode
829 (plist-get eww-data :url))))
830
831(use-package xwidget
832 :when (featurep 'xwidget-internal)
833 :preface
834 (setenv "WEBKIT_FORCE_SANDBOX" "0") ; This is probably a bad idea
835 :custom
836 (xwidget-webkit-cookie-file (cache/ "xwidget-cookies"))
837 (xwidget-webkit-download-dir (expand-file-name "~/var/download"))
838 :config
839 (defkeys xwidget-webkit-mode-map
840 "&" (+browse-url-switch-external-browser xwidget-webkit-mode
841 (xwidget-webkit-uri (xwidget-webkit-current-session)))))
842
843(use-package xwwp
844 :load-path "~/src/emacs/xwwp/"
845 :when (featurep 'xwidget-internal)
846 :custom
847 (xwwp-search-prefix "https://duckduckgo.com/?q=")
848 :bind (:map xwidget-webkit-mode-map
849 ("f" . xwwp-follow-link)))
850 6
851(use-package jabber 7(load (locate-user-emacs-file "basics")) ; super basic stuff
852 :load-path "~/src/emacs/emacs-jabber"
853 :custom
854 (jabber-account-list '(("acdw@hmm.st")))
855 (jabber-auto-reconnect t)
856 (jabber-chat-buffer-format "xmpp:%n")
857 (jabber-browse-buffer-format "xmpp-browse:%n")
858 (jabber-groupchat-buffer-format "xmpp-muc:%n")
859 (jabber-muc-private-buffer-format "xmpp-muc-private:%n")
860 (jabber-groupchat-prompt-format "%>10n │ ")
861 (jabber-chat-local-prompt-format "%>10n │ ")
862 (jabber-chat-system-prompt-format " * * * * * *")
863 (jabber-chat-foreign-prompt-format "%>10n │ ")
864 (jabber-muc-private-foreign-prompt-format "%g/%n ")
865 (jabber-last-read-marker "----------------------------------------")
866 (jabber-muc-header-line-format '("" jabber-muc-topic))
867 (jabber-muc-decorate-presence-patterns
868 '(("\\( enters the room ([^)]+)\\| has left the chatroom\\)$")
869 ("." . jabber-muc-presence-dim)))
870 (jabber-activity-make-strings
871 #'jabber-activity-make-strings-shorten)
872 (jabber-rare-time-format " - - - - - - %H:%M %F")
873 :custom-face
874 (jabber-chat-prompt-local ((t :inherit font-lock-keyword-face
875 :foreground unspecified)))
876 (jabber-activity-face ((t :inherit jabber-chat-prompt-foreign
877 :foreground unspecified
878 :weight normal)))
879 (jabber-activity-personal-face ((t :inherit font-lock-warning-face
880 :foreground unspecified
881 :weight bold)))
882 (jabber-chat-prompt-foreign ((t :inherit font-lock-constant-face
883 :foreground unspecified)))
884 (jabber-chat-prompt-system ((t :inherit font-lock-doc-face
885 :foreground unspecified)))
886 (jabber-rare-time-face ((t :inherit font-lock-comment-face
887 :foreground unspecified
888 :underline nil)))
889 :init
890 (defhook (jabber-chat-mode-hook
891 jabber-browse-mode-hook
892 jabber-roster-mode-hook
893 jabber-console-mode-hook)
894 :name jabber-ui-setup
895 (visual-fill-column-mode)
896 (electric-pair-local-mode -1)
897 (auto-fill-mode -1)
898 (setq-local wrap-prefix (format "%13s" " ")))
899 :bind-keymap ("C-c j" . jabber-global-keymap)
900 :bind (("C-c C-SPC" . jabber-activity-switch-to))
901 :config
902 (global-set-key (kbd "C-x C-j") #'dired-jump) ; Extremely annoying fix
903 (require 'jabber-httpupload nil :noerror)
904 (add-hook 'jabber-post-connect-hooks #'jabber-enable-carbons)
905 (remove-hook 'jabber-alert-muc-hooks 'jabber-muc-echo)
906 (remove-hook 'jabber-alert-presence-hooks 'jabber-presence-echo)
907 (add-hook 'jabber-alert-muc-hooks
908 (defun jabber@highlight-acdw (&optional _nick _group buf _text _title)
909 (when buf
910 (with-current-buffer buf
911 (let ((regexp (rx word-boundary
912 "acdw" ; maybe get from the config?
913 word-boundary)))
914 (hi-lock-unface-buffer regexp)
915 (highlight-regexp regexp 'hi-blue))))))
916 (add-hook 'window-configuration-change-hook #'jabber-chat-update-focus)
917 (eval-after consult
918 (defvar jabber-chat-buffer-source
919 `( :name "Jabber"
920 :hidden nil
921 :narrow ?j
922 :category buffer
923 :state ,#'consult--buffer-state
924 :items ,(lambda ()
925 (mapcar #'buffer-name
926 (seq-filter (lambda (buf)
927 (with-current-buffer buf
928 (eq major-mode 'jabber-chat-mode)))
929 (buffer-list))))))
930 (add-to-list 'consult-buffer-sources 'jabber-chat-buffer-source :append)
931 ;; Also hide xmpp buffers from regular buffer list
932 (add-to-list 'consult-buffer-filter "\\`xmpp" nil #'string-equal)))