diff options
Diffstat (limited to 'init.el')
-rw-r--r-- | init.el | 933 |
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 | |||
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))) | ||