diff options
Diffstat (limited to 'init.el')
-rw-r--r-- | init.el | 1623 |
1 files changed, 467 insertions, 1156 deletions
diff --git a/init.el b/init.el index 707125e..4648042 100644 --- a/init.el +++ b/init.el | |||
@@ -1,1163 +1,474 @@ | |||
1 | ;;; init.el --- An Emacs of one's own -*- lexical-binding: t -*- | 1 | ;;; Emacs init.el -*- lexical-binding: t; -*- |
2 | ;; by Case Duckworth <acdw@acdw.net> | ||
3 | ;; Bankruptcy 10: "Annoyance" | ||
2 | 4 | ||
3 | ;; Author: Case Duckworth <acdw@acdw.net>, with inspo from many others | 5 | ;;; Commentary: |
4 | ;; Homepage: https://git.acdw.net/emacs | ||
5 | ;; Config-Requires: ((emacs "29.0")) | ||
6 | ;; Bankruptcy: 9.4 | ||
7 | 6 | ||
8 | ;; This configuration is Free Software. Everyone is permitted to do whatever | 7 | ;; This is my Emacs configuration. There are many like it but this |
9 | ;; they want with it, without limitation. This software comes without any | 8 | ;; one is mine. |
10 | ;; warranty whatsoever, but with two pieces of advice: | ||
11 | ;; | 9 | ;; |
12 | ;; - Don't hurt others. | 10 | ;; For the tenth time! |
13 | ;; - Make good choices. | 11 | |
14 | 12 | ;;; Packages | |
15 | ;;; Code: | 13 | |
16 | 14 | (require 'package) | |
17 | (load (locate-user-emacs-file "basics")) ; super basic stuff | 15 | (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t) |
18 | 16 | (package-initialize) | |
19 | 17 | ||
20 | ;;; Built-ins | 18 | (dolist (pkg `(consult |
21 | 19 | marginalia | |
22 | (use-package emacs ; Misc. config | 20 | visual-fill-column |
23 | :config | 21 | adaptive-wrap |
24 | (setq recenter-positions '(top middle bottom) | 22 | geiser |
25 | initial-major-mode 'lisp-interaction-mode | 23 | ,(when (executable-find "csi") 'geiser-chicken) |
26 | initial-scratch-message ";; Emacs!\n\n" | 24 | avy |
27 | ;; (format "%s\n\n" | 25 | zzz-to-char |
28 | ;; (mapconcat (lambda (s) (format ";; %s" s)) | 26 | hungry-delete |
29 | ;; (process-lines "fortune" "-s") | 27 | undohist |
30 | ;; "\n")) | 28 | jinx)) |
31 | eval-expression-print-level nil | 29 | (when (and pkg (not (package-installed-p pkg))) |
32 | eval-expression-print-length nil | 30 | (unless (ignore-errors (package-install pkg)) |
33 | x-select-enable-clipboard-manager nil) | 31 | (package-refresh-contents) |
34 | ;; TODO: move this ... elsewhere | 32 | (package-install pkg)))) |
35 | (setq mode-line-format | 33 | |
36 | '("%e" | 34 | (load (locate-user-emacs-file "definitions")) |
37 | mode-line-front-space | 35 | (load (locate-user-emacs-file "packages")) |
38 | ;; (:propertize ("" mode-line-mule-info | 36 | (load (locate-user-emacs-file "private")) |
39 | ;; mode-line-client | 37 | |
40 | ;; mode-line-modified | 38 | (setopt custom-file (locate-user-emacs-file "custom.el")) |
41 | ;; mode-line-remote) | 39 | (load custom-file :noerror) |
42 | ;; display (min-width (5.0))) | 40 | |
43 | ("" mode-line-mule-info | 41 | ;;; General keybinding changes |
42 | |||
43 | (keymap-global-set "M-o" #'other-window-or-switch-buffer) | ||
44 | |||
45 | (keymap-global-set "M-SPC" #'cycle-spacing@) | ||
46 | |||
47 | (keymap-global-set "M-u" #'universal-argument) | ||
48 | (keymap-set universal-argument-map "M-u" #'universal-argument-more) | ||
49 | |||
50 | ;;; Theme | ||
51 | |||
52 | (if (daemonp) | ||
53 | (add-hook 'server-after-make-frame-hook #'first-frame@set-fonts) | ||
54 | (run-with-idle-timer 1 nil #'first-frame@set-fonts)) | ||
55 | |||
56 | (tool-bar-mode -1) | ||
57 | |||
58 | (load-theme 'modus-vivendi :no-confirm :no-enable) | ||
59 | (load-theme 'modus-operandi :no-confirm) | ||
60 | |||
61 | (add-hook 'text-mode-hook #'visual-line-mode) | ||
62 | |||
63 | ;;; Mode line | ||
64 | |||
65 | (defvar mode-line-position | ||
66 | '("" | ||
67 | (:eval (if line-number-mode "%3l" "")) | ||
68 | (:eval (if column-number-mode | ||
69 | (if column-number-indicator-zero-based | ||
70 | "/%2c" | ||
71 | "/%2C") | ||
72 | "")) | ||
73 | " (" (-3 "%p") ") ")) | ||
74 | |||
75 | (setopt mode-line-format | ||
76 | '(("%e" mode-line-front-space | ||
44 | mode-line-client | 77 | mode-line-client |
45 | mode-line-modified | 78 | mode-line-modified |
46 | mode-line-remote) | 79 | mode-line-remote " " |
47 | mode-line-frame-identification | 80 | mode-line-buffer-identification |
48 | mode-line-buffer-identification | 81 | (vc-mode vc-mode) |
49 | " " | 82 | " " |
50 | mode-line-position | 83 | (mode-line-position mode-line-position) |
51 | (vc-mode vc-mode) | 84 | mode-line-modes |
52 | " " | 85 | mode-line-misc-info |
53 | minions-mode-line-modes | 86 | mode-line-end-spaces))) |
54 | mode-line-misc-info | 87 | |
55 | mode-line-end-spaces)) | 88 | ;; Remove modes from mode-line |
56 | (keymap-global-unset "C-\\") | 89 | (dolist (minor-mode '(frowny-mode |
57 | (keymap-global-unset "<f2>") | 90 | whitespace-mode |
58 | (setf (alist-get "\\*Compile-Log\\*" display-buffer-alist nil nil #'equal) | 91 | hungry-delete-mode)) |
59 | '(display-buffer-no-window)) | 92 | (setf (alist-get minor-mode minor-mode-alist) (list "")) |
60 | ;; (add-hook 'after-init-hook | 93 | (add-hook (intern (format "%s-hook" minor-mode)) |
61 | ;; (defun global-mode-string@setup () | 94 | (lambda () |
62 | ;; (defvar jabber-activity-mode-string) | 95 | (setf (alist-get minor-mode minor-mode-alist) (list ""))))) |
63 | ;; (defvar org-mode-line-string) | 96 | |
64 | ;; (defvar display-time-mode) | 97 | ;;; Completion & minibuffer |
65 | ;; (defvar display-time-string) | 98 | |
66 | ;; (setf global-mode-string | 99 | (setopt icomplete-in-buffer t |
67 | ;; '((t jabber-activity-mode-string) | 100 | icomplete-tidy-shadowed-file-names t) |
68 | ;; org-mode-line-string | 101 | (fido-vertical-mode) |
69 | ;; (display-time-mode display-time-string))))) | 102 | |
70 | (keymap-global-set "C-c t" | 103 | (setopt completion-auto-help (not icomplete-mode) |
71 | (define-keymap | 104 | completion-auto-select 'second-tab |
72 | :prefix 'toggle-map | 105 | completions-header-format nil |
73 | "e" #'toggle-debug-on-error | 106 | completions-max-height 12 |
74 | "q" #'toggle-debug-on-quit | 107 | completions-format 'one-column |
75 | "c" #'column-number-mode | 108 | completion-styles '(basic partial-completion flex) |
76 | "l" #'line-number-mode | 109 | completion-ignore-case t |
77 | "L" #'display-line-numbers-mode))) | 110 | read-buffer-completion-ignore-case t |
78 | 111 | read-file-name-completion-ignore-case t | |
79 | (use-package faces | 112 | completions-detailed t |
80 | :config | 113 | enable-recursive-minibuffers t |
81 | (add-hook 'server-after-make-frame-hook | 114 | file-name-shadow-properties '(invisible t intangible t) |
82 | (defun first-frame@set-fonts () | 115 | minibuffer-eldef-shorten-default t |
83 | (remove-hook 'server-after-make-frame-hook | 116 | minibuffer-prompt-properties '( read-only t |
84 | #'first-frame@set-fonts) | 117 | cursor-intangible t |
85 | (face-spec-set 'default | 118 | face minibuffer-prompt) |
86 | `((t :family ,(find-font | 119 | window-resize-pixelwise t |
87 | "Recursive Mono Casual Static" | 120 | frame-resize-pixelwise t) |
88 | "Comic Code" | 121 | |
89 | "DejaVu Sans Mono") | 122 | (add-hook 'completion-list-mode-hook #'truncate-lines-mode) |
90 | :height 110))) | 123 | (add-hook 'minibuffer-setup-hook #'truncate-lines-mode) |
91 | (face-spec-set 'fixed-pitch | 124 | |
92 | `((t :family ,(find-font | 125 | ;; Up/down when completing in the minibuffer |
93 | "Recursive Mono Linear Static" | 126 | (define-key minibuffer-local-map (kbd "C-p") #'minibuffer-previous-completion) |
94 | "Comic Code" | 127 | (define-key minibuffer-local-map (kbd "C-n") #'minibuffer-next-completion) |
95 | "DejaVu Sans Mono") | 128 | |
96 | :height 1.0))) | 129 | ;; Up/down when competing in a normal buffer |
97 | (face-spec-set 'variable-pitch | 130 | (define-key completion-in-region-mode-map (kbd "C-p") #'minibuffer-previous-completion) |
98 | `((t :family ,(find-font | 131 | (define-key completion-in-region-mode-map (kbd "C-n") #'minibuffer-next-completion) |
99 | "Recursive Sans Casual Static" | 132 | |
100 | "Atkinson Hyperlegible" | 133 | (setopt completions-sort #'renz/sort-multi-category) |
101 | "DejaVu Serif") | 134 | |
102 | :height 1.0))) | 135 | (setopt tab-always-indent 'complete) |
103 | (face-spec-set 'font-lock-comment-face | 136 | |
104 | `((t :slant italic | 137 | (file-name-shadow-mode) |
105 | :inherit variable-pitch))) | 138 | (minibuffer-electric-default-mode) |
106 | ;; Emojis | 139 | |
107 | (cl-loop with ffl = (font-family-list) | 140 | (scroll-bar-mode -1) |
108 | for font in '("Noto Emoji" "Noto Color Emoji" | 141 | (menu-bar-mode -1) |
109 | "Segoe UI Emoji" "Apple Color Emoji" | 142 | |
110 | "FreeSans" "FreeMono" "FreeSerif" | 143 | (add-hook 'prog-mode-hook #'indent-tabs-mode-maybe) |
111 | "Unifont" "Symbola") | 144 | |
112 | if (member font ffl) | 145 | (setopt electric-pair-skip-whitespace 'chomp) |
113 | do (set-fontset-font t 'symbol font)) | 146 | (electric-pair-mode) |
114 | ;; International scripts | 147 | |
115 | (cl-loop with ffl = (font-family-list) | 148 | (setopt sh-basic-offset tab-width) |
116 | for (charset . font) | 149 | |
117 | in '((latin . "Noto Sans") | 150 | (keymap-set emacs-lisp-mode-map "C-c C-c" #'eval-defun) |
118 | (han . "Noto Sans CJK SC Regular") | 151 | (keymap-set emacs-lisp-mode-map "C-c C-k" #'eval-buffer) |
119 | (kana . "Noto Sans CJK JP Regular") | 152 | (keymap-set lisp-interaction-mode-map "C-c C-c" #'eval-defun) |
120 | (hangul . "Noto Sans CJK KR Regular") | 153 | (keymap-set lisp-interaction-mode-map "C-c C-k" #'eval-buffer) |
121 | (cjk-misc . "Noto Sans CJK KR Regular") | 154 | |
122 | (khmer . "Noto Sans Khmer") | 155 | (advice-add 'indent-region :around #'call-with-region-or-buffer) |
123 | (lao . "Noto Sans Lao") | 156 | (advice-add 'tabify :around #'call-with-region-or-buffer) |
124 | (burmese . "Noto Sans Myanmar") | 157 | (advice-add 'untabify :around #'call-with-region-or-buffer) |
125 | (thai . "Noto Sans Thai") | 158 | |
126 | (ethiopic . "Noto Sans Ethiopic") | 159 | (with-eval-after-load 'scheme |
127 | (hebrew . "Noto Sans Hebrew") | 160 | (keymap-unset scheme-mode-map "M-o" t) |
128 | (arabic . "Noto Sans Arabic") | 161 | ;; Comparse "keywords" --- CHICKEN (http://wiki.call-cc.org/eggref/5/comparse) |
129 | (gujarati . "Noto Sans Gujarati") | 162 | (put 'sequence* 'scheme-indent-function 1) |
130 | (devanagari . "Noto Sans Devanagari") | 163 | (put 'satisfies 'scheme-indent-function 1) |
131 | (kannada . "Noto Sans Kannada") | 164 | (add-hook 'scheme-mode-hook #'geiser-mode)) |
132 | (malayalam . "Noto Sans Malayalam") | 165 | (with-eval-after-load 'geiser-mode |
133 | (oriya . "Noto Sans Oriya") | 166 | (keymap-set geiser-mode-map "C-c C-k" #'geiser-eval-buffer-and-go) |
134 | (sinhala . "Noto Sans Sinhala") | 167 | (keymap-unset geiser-mode-map "C-." t)) |
135 | (tamil . "Noto Sans Tamil") | 168 | |
136 | (telugu . "Noto Sans Telugu") | 169 | (setopt visual-fill-column-center-text t |
137 | (tibetan . "Noto Sans Tibetan")) | 170 | visual-fill-column-width (+ fill-column 2)) |
138 | if (member font ffl) | 171 | (advice-add 'text-scale-adjust :after #'visual-fill-column-adjust) |
139 | do (set-fontset-font t charset font)))) | 172 | (add-hook 'visual-line-mode-hook #'visual-fill-column-mode) |
140 | (unless (daemonp) | 173 | (add-hook 'visual-line-mode-hook #'adaptive-wrap-prefix-mode) |
141 | (run-with-idle-timer 1 nil #'first-frame@set-fonts))) | 174 | |
142 | 175 | (setopt major-mode | |
143 | (use-package text-mode | 176 | (lambda () ; guess major mode from buffer name |
144 | :config | 177 | (unless buffer-file-name |
145 | (add-hook 'text-mode-hook #'abbrev-mode)) | 178 | (let ((buffer-file-name (buffer-name))) |
146 | 179 | (set-auto-mode))))) | |
147 | (use-package prog-mode | 180 | |
148 | :config | 181 | ;; Dialogs |
149 | ;;; TABS | 182 | (unless (boundp 'use-short-answers) |
150 | (setq tab-width 8 | 183 | (fset 'yes-or-no-p 'y-or-n-p)) |
151 | sh-indentation tab-width | 184 | |
152 | ) | 185 | (setopt read-answer-short t |
153 | ;;; Hooks | 186 | use-dialog-box nil |
154 | (add-hook 'prog-mode-hook #'auto-fill-mode) | 187 | use-file-dialog nil |
155 | (add-hook 'prog-mode-hook | 188 | use-short-answers t) |
156 | (defun prog@indent-tabs-maybe () | 189 | |
157 | (indent-tabs-mode | 190 | (require 'savehist) |
158 | (if (derived-mode-p 'emacs-lisp-mode | 191 | (setopt history-length 1024 |
159 | 'lisp-mode | 192 | history-delete-duplicates t |
160 | 'scheme-mode | 193 | ;; savehist-file (etc/ "savehist.el") |
161 | 'python-mode | 194 | savehist-save-minibuffer-history t |
162 | 'haskell-mode) | 195 | savehist-autosave-interval 30) |
163 | -1 1)))) | 196 | (savehist-mode) |
164 | (global-prettify-symbols-mode)) | 197 | |
165 | 198 | ;; Killing and yanking | |
166 | (use-package auth-source | 199 | (setopt kill-do-not-save-duplicates t |
167 | :config | 200 | kill-read-only-ok t |
168 | (setq auth-sources '(default "secrets:passwords")) | 201 | ;; XXX: This setting causes an error message the first time it's |
169 | (add-hook 'auth-info-hook #'truncate-lines-local-mode)) | 202 | ;; called: "Selection owner couldn't convert: TIMESTAMP". I have |
170 | 203 | ;; absolutely no idea why I get this error, but it's generated in | |
171 | (use-package fringe | 204 | ;; `x_get_foreign_selection'. I also can't inhibit the message or |
172 | :config | 205 | ;; do anything else with it, so for now, I'll just live with the |
173 | (fringe-mode '(nil . 0))) | 206 | ;; message. |
174 | 207 | save-interprogram-paste-before-kill t | |
175 | (use-package ispell | 208 | yank-pop-change-selection t) |
176 | :config | 209 | (delete-selection-mode) |
177 | (setq ispell-program-name (choose-executable "aspell" "ispell")) | 210 | |
178 | ;; (add-hook 'before-save-hook | 211 | ;; Notifying the user |
179 | ;; #'+ispell-move-buffer-words-to-dir-locals-hook) | 212 | (setopt echo-keystrokes 0.01 |
180 | (put 'ispell-buffer-session-localwords 'safe-local-variable | 213 | ring-bell-function #'ignore) |
181 | '+ispell-safe-local-p)) | 214 | |
182 | 215 | ;; Point and mark | |
183 | (use-package dired | 216 | (setopt set-mark-command-repeat-pop t) |
184 | :bind (("C-x C-j" . dired-jump) | 217 | |
185 | ([remap list-directory] . dired) | 218 | ;; The system |
186 | :map dired-mode-map | 219 | (setopt read-process-output-max (* 10 1024 1024)) |
187 | ("C-j" . dired-up-directory) | 220 | |
188 | ("<backspace>" . dired-up-directory)) | 221 | ;; Startup |
189 | :config | 222 | (setopt inhibit-startup-screen t |
190 | (require 'dired-x) | 223 | initial-buffer-choice t |
191 | (setq dired-recursive-copies 'always | 224 | initial-scratch-message nil) |
192 | dired-recursive-deletes 'always | 225 | |
193 | dired-create-destination-dirs 'always | 226 | (define-advice startup-echo-area-message (:override ()) |
194 | dired-do-revert-buffer t | 227 | (if (get-buffer "*Warnings*") |
195 | dired-hide-details-hide-symlink-targets nil | 228 | ";_;" |
196 | dired-isearch-filenames 'dwim | 229 | "^_^")) |
197 | delete-by-moving-to-trash t | 230 | |
198 | dired-auto-revert-buffer t | 231 | ;; Text editing |
199 | dired-listing-switches "-AlFhv --group-directories-first" | 232 | (setopt fill-column 80 |
200 | ls-lisp-dirs-first t | 233 | sentence-end-double-space nil |
201 | dired-ls-F-marks-symlinks t | 234 | tab-width 8 |
202 | dired-clean-confirm-killing-deleted-buffers nil | 235 | tab-always-indent 'complete) |
203 | dired-no-confirm '(byte-compile | 236 | (global-so-long-mode) |
204 | load chgrp chmod chown | 237 | |
205 | copy move hardlink symlink | 238 | (setopt show-paren-delay 0.01 |
206 | shell touch) | 239 | show-paren-style 'parenthesis |
207 | dired-dwim-target t) | 240 | show-paren-when-point-in-periphery t |
208 | (add-hook 'dired-mode-hook #'dired-hide-details-mode) | 241 | show-paren-when-point-inside-paren t) |
209 | (add-hook 'dired-mode-hook #'hl-line-mode) | 242 | (show-paren-mode) |
210 | (add-hook 'dired-mode-hook #'truncate-lines-local-mode)) | 243 | |
211 | 244 | ||
212 | (use-package dictionary | 245 | ;; Encodings |
213 | :custom | 246 | (set-language-environment "UTF-8") |
214 | (dictionary-server (if (or (executable-find "dictd") | 247 | (setopt buffer-file-coding-system 'utf-8-unix |
215 | (file-exists-p "/usr/sbin/dictd")) ; debian | 248 | coding-system-for-read 'utf-8-unix |
216 | "localhost" | 249 | coding-system-for-write 'utf-8-unix |
217 | "dict.org")) | 250 | default-process-coding-system '(utf-8-unix . utf-8-unix) |
218 | :bind | 251 | locale-coding-system 'utf-8-unix) |
219 | (("C-c w d" . dictionary-search)) | 252 | (set-charset-priority 'unicode) |
220 | :config | 253 | (prefer-coding-system 'utf-8-unix) |
221 | (setf (alist-get "\\*Dictionary\\*" display-buffer-alist nil nil #'equal) | 254 | (set-default-coding-systems 'utf-8-unix) |
222 | '(display-buffer-in-side-window | 255 | (set-terminal-coding-system 'utf-8-unix) |
223 | (window-width . 80) | 256 | (set-keyboard-coding-system 'utf-8-unix) |
224 | (side . right)))) | 257 | (pcase system-type |
225 | 258 | ((or 'ms-dos 'windows-nt) | |
226 | (use-package calendar | 259 | (set-clipboard-coding-system 'utf-16-le) |
227 | :custom | 260 | (set-selection-coding-system 'utf-16-le)) |
228 | (diary-file (private/ "diary"))) | 261 | (_ |
229 | 262 | (set-selection-coding-system 'utf-8) | |
230 | (use-package mouse | 263 | (set-clipboard-coding-system 'utf-8))) |
231 | :config | 264 | |
232 | (setq context-menu-functions '(context-menu-undo | 265 | |
233 | context-menu-region | 266 | ;; Files |
234 | context-menu-middle-separator | 267 | (setopt auto-revert-verbose nil |
235 | context-menu-local | 268 | global-auto-revert-non-file-buffers t |
236 | context-menu-minor)) | 269 | create-lockfiles nil |
237 | (context-menu-mode)) | 270 | find-file-visit-truename t |
238 | 271 | mode-require-final-newline t | |
239 | (use-package password-cache | 272 | view-read-only t |
240 | :config | 273 | save-silently t) |
241 | (setq password-cache t | 274 | (global-auto-revert-mode) |
242 | password-cache-expiry 3600)) | 275 | |
243 | 276 | (setopt auto-save-default nil | |
244 | (use-package time | 277 | auto-save-interval 1 |
245 | :config | 278 | auto-save-no-message t |
246 | (setq display-time-format " %H:%M" | 279 | auto-save-timeout 1 |
247 | display-time-interval 60 | 280 | auto-save-visited-interval 1 |
248 | display-time-use-mail-icon t | 281 | remote-file-name-inhibit-auto-save-visited t) |
249 | display-time-mail-function | 282 | (add-to-list 'auto-save-file-name-transforms |
250 | (defun +notmuch-new-mail-p () | 283 | `(".*" ,(locate-user-emacs-file "auto-save/") t)) |
251 | (plist-get (cl-find "inbox+unread" | 284 | (auto-save-visited-mode) |
252 | (ignore-errors | 285 | |
253 | (notmuch-hello-query-counts notmuch-saved-searches)) | 286 | (setopt backup-by-copying t |
254 | :key (lambda (l) (plist-get l :name)) | 287 | version-control t |
255 | :test #'equal) | 288 | kept-new-versions 8 |
256 | :count)) | 289 | kept-old-versions 8 |
257 | display-time-default-load-average nil) | 290 | delete-old-versions t) |
258 | (with-eval-after-load 'notmuch | 291 | (setq-default backup-directory-alist |
259 | (add-hook 'notmuch-after-tag-hook #'display-time-update)) | 292 | `(("^/dev/shm" . nil) |
260 | ;; (display-time-mode) | 293 | ("^/tmp" . nil) |
261 | ) | 294 | (,(getenv "XDG_RUNTIME_DIR") . nil) |
262 | 295 | ("." . ,(locate-user-emacs-file "backup")))) | |
263 | (use-package tab-bar | 296 | |
264 | :config | 297 | (require 'recentf) |
265 | (setq tab-bar-show t | 298 | (setopt |
266 | tab-bar-close-button-show t) | 299 | recentf-max-menu-items 500 |
267 | (setopt tab-bar-format | 300 | recentf-max-saved-items nil ; Save the whole list |
268 | `(tab-bar-format-history | 301 | recentf-auto-cleanup 'mode |
269 | tab-bar-format-tabs | 302 | recentf-case-fold-search t) |
270 | tab-bar-separator | 303 | ;; (add-to-list 'recentf-exclude etc/) |
271 | tab-bar-format-add-tab | 304 | (add-to-list 'recentf-exclude "-autoloads.el\\'") |
272 | tab-bar-format-align-right | 305 | (add-hook 'buffer-list-update-hook #'recentf-track-opened-file) |
273 | ,(defun tab-bar-extra-info () | 306 | (add-hook 'after-save-hook #'recentf-save-list) |
274 | `((global menu-item | 307 | (recentf-mode) |
275 | ,(format-mode-line | 308 | |
276 | '((jabber-activity-mode jabber-activity-mode-string) | 309 | (require 'saveplace) |
277 | (:eval (when (and (fboundp 'org-clocking-p) | 310 | (setopt |
278 | (org-clocking-p)) | 311 | save-place-forget-unreadable-files (eq system-type |
279 | (format " %s" | 312 | 'gnu/linux)) |
280 | (truncate-string-to-width | 313 | (save-place-mode) |
281 | org-mode-line-string | 314 | |
282 | 16 | 315 | (require 'uniquify) |
283 | nil | 316 | (setq uniquify-after-kill-buffer-p t |
284 | nil | 317 | uniquify-buffer-name-style 'forward |
285 | (truncate-string-ellipsis))))) | 318 | uniquify-ignore-buffers-re "^\\*" |
286 | (:eval (tmr-mode-line)) | 319 | uniquify-separator path-separator) |
287 | (display-time-mode | 320 | |
288 | (:eval (format " %s" (string-trim display-time-string)))) | 321 | (setq-local vc-follow-symlinks t |
289 | ("" " "))) | 322 | vc-make-backup-files t) |
290 | ignore)))) | 323 | |
291 | mode-line-misc-info (cl-delete-if (lambda (x) | 324 | ;; Whitespace |
292 | (eq (car x) 'global-mode-string)) | 325 | (require 'whitespace) |
293 | mode-line-misc-info)) | 326 | (setopt whitespace-style |
294 | (if (daemonp) | 327 | '(face trailing tabs tab-mark)) |
295 | (add-hook 'server-after-make-frame-hook | 328 | (global-whitespace-mode) |
296 | (defun after-frame@tab-bar () | 329 | (add-hook 'before-save-hook #'delete-trailing-whitespace-except-current-line) |
297 | (tab-bar-mode) | 330 | |
298 | (remove-hook 'server-after-make-frame-hook | 331 | ;; Native compilation |
299 | #'after-frame@tab-bar))) | 332 | (setopt native-comp-async-report-warnings-errors 'silent |
300 | (run-with-idle-timer 2 nil #'tab-bar-mode))) | 333 | native-comp-deferred-compilation t |
301 | 334 | native-compile-target-directory | |
302 | (use-package info | 335 | (locate-user-emacs-file "eln")) |
303 | :preface | 336 | (when (boundp 'native-comp-eln-load-path) |
304 | (defun Info-copy-current-node-name-0 () | 337 | (add-to-list 'native-comp-eln-load-path native-compile-target-directory)) |
305 | "Call `Info-copy-current-node-name' with a 0 prefix arg." | 338 | (when (fboundp 'startup-redirect-eln-cache) |
306 | (interactive) | 339 | (startup-redirect-eln-cache native-compile-target-directory)) |
307 | (Info-copy-current-node-name 0)) | 340 | |
308 | :bind (:map Info-mode-map | 341 | (global-goto-address-mode) |
309 | ("w" . Info-copy-current-node-name-0) | 342 | |
310 | ("c" . Info-copy-current-node-name))) | 343 | ;; Winner |
311 | 344 | (winner-mode) | |
312 | (use-package make-mode | 345 | |
313 | :defer t | 346 | ;;; Hooks |
314 | :config | 347 | (add-hook 'after-save-hook #'executable-make-buffer-file-executable-if-script-p) |
315 | (add-hook 'makefile-mode-hook | 348 | (add-hook 'find-file-not-found-functions #'create-missing-directories) |
316 | (defun make-mode@setup () | 349 | (add-hook 'find-file-hook #'vc-remote-off) |
317 | (remove-hook 'write-file-functions | 350 | (add-hook 'dired-mode-hook #'hl-line-mode) |
318 | #'makefile-warn-suspicious-lines t) | 351 | (add-hook 'org-agenda-mode-hook #'hl-line-mode) |
319 | (remove-hook 'write-file-functions | 352 | |
320 | #'makefile-warn-continuations t)))) | 353 | ;;; Tab bar |
321 | 354 | ||
322 | (use-package eglot | 355 | (defun tab-bar-end-space () |
323 | :preface | 356 | `((end menu-item " " ignore))) |
324 | (defun +eglot-eldoc () | 357 | |
325 | ;; https://www.masteringemacs.org/article/seamlessly-merge-multiple-documentation-sources-eldoc | 358 | (setopt tab-bar-show t) |
326 | (setq eldoc-documentation-strategy #'eldoc-documentation-compose-eagerly)) | 359 | (add-to-list 'tab-bar-format 'tab-bar-format-align-right :append) |
327 | :hook | 360 | (add-to-list 'tab-bar-format 'tab-bar-format-global :append) |
328 | ((bash-ts-mode . eglot-ensure) | 361 | (add-to-list 'tab-bar-format 'tab-bar-end-space :append) |
329 | (scheme-mode . eglot-ensure)) | 362 | (tab-bar-mode) |
330 | :config | 363 | |
331 | (add-to-list 'eglot-server-programs | 364 | ;;; Org mode |
332 | '(scheme-mode . ("chicken-lsp-server"))) | 365 | |
333 | (add-hook 'eglot-managed-mode #'+eglot-eldoc)) | 366 | (keymap-global-set "C-c a" #'org-agenda) |
334 | 367 | (setopt org-clock-clocked-in-display 'frame-title | |
335 | (use-package eldoc | 368 | org-clock-frame-title-format |
336 | :config | 369 | '("%b" " - " (t org-mode-line-string))) |
337 | (setq eldoc-documentation-strategy #'eldoc-documentation-compose-eagerly) | 370 | |
338 | (setf (alist-get "^\\*eldoc for" display-buffer-alist nil nil #'equal) | 371 | ;;; Spelling |
339 | '(display-buffer-at-bottom | 372 | |
340 | (window-height . 4))) | 373 | (defun list-of-strings-p (x) |
341 | (eldoc-add-command-completions "paredit-")) | 374 | "Is X a list of strings?" |
342 | 375 | (and x | |
343 | (use-package pulse | 376 | (listp x) |
344 | :config | 377 | (cl-every #'stringp x))) |
345 | (setq pulse-flag nil | 378 | |
346 | pulse-delay 1 | 379 | (put 'ispell-local-words 'safe-local-variable |
347 | pulse-iterations 1)) | 380 | 'list-of-strings-p) |
348 | 381 | ||
349 | (use-package flyspell | 382 | (add-hook 'text-mode-hook #'jinx-mode) |
350 | :hook (org-mode-hook)) | 383 | (with-eval-after-load 'jinx |
351 | 384 | (keymap-set jinx-mode-map "M-$" #'jinx-correct) | |
352 | ;; (use-package display-fill-column-indicator | 385 | (keymap-set jinx-mode-map "C-M-$" #'jinx-languages)) |
353 | ;; :hook (prog-mode-hook)) | 386 | |
354 | 387 | ;;; Copy rich text to the keyboard | |
355 | (use-package package | 388 | |
356 | :config | 389 | ;; Thanks to Oleh Krehel: |
357 | (defun package-update-async-in-progress (&rest _) | 390 | ;; https://emacs.stackexchange.com/questions/54292/copy-results-of-org-export-directly-to-clipboard |
358 | (message "Package async update in progress.")) | 391 | ;; So. Emacs can't do this itself because it doesn't support sending clipboard |
359 | 392 | ;; or selection contents as text/html. We have to use xclip instead. | |
360 | (defun package-update-all-async () | 393 | ;; (defun org-to-html-to-clipboard (&rest org-export-args) |
361 | "Update packages asyncronously." | 394 | ;; "Export current org buffer to HTML, then copy it to the clipboard. |
362 | (interactive) | 395 | ;; ORG-EXPORT-ARGS are passed to `org-export-to-file'." |
363 | (let ((message "Package update (async)...") | 396 | ;; (let ((f (make-temp-file "org-html-export"))) |
364 | (disable-fns '(package-update | 397 | ;; (apply #'org-export-to-file 'html f org-export-args) |
365 | package-update-all | 398 | ;; (start-process "xclip" " *xclip*" |
366 | package-update-all-async))) | 399 | ;; "xclip" "-verbose" "-i" f |
367 | (dolist (fn disable-fns) | 400 | ;; "-t" "text/html" "-selection" "clipboard") |
368 | (advice-add fn :override #'package-update-async-in-progress)) | 401 | ;; (message "HTML pasted to clipboard."))) |
369 | (message "%s" message) | 402 | |
370 | (unwind-protect | 403 | ;; Wayland version.. TODO: make it work for both |
371 | (async-start | 404 | (defun org-to-html-to-clipboard (&rest org-export-args) |
372 | `(lambda () | 405 | "Export current org buffer to HTML, then copy it to the clipboard. |
373 | (package-initialize) | 406 | ORG-EXPORT-ARGS are passed to `org-export-to-file'." |
374 | (package-update-all)) | 407 | (let ((buf (generate-new-buffer "*org-html-clipboard*" t))) |
375 | `(lambda (result) | 408 | (apply #'org-export-to-buffer 'html buf org-export-args) |
376 | (message "%s %s" ,message result))) | 409 | (with-current-buffer buf |
377 | (dolist (fn ',disable-fns) | 410 | (call-process-region (point-min) (point-max) |
378 | (advice-remove fn 'package-update-async-in-progress)))))) | 411 | "wl-copy" nil nil nil |
379 | 412 | "-t" "text/html") | |
380 | (use-package ielm | 413 | (kill-buffer-and-window)) |
381 | ;; https://www.n16f.net/blog/making-ielm-more-comfortable/ | 414 | (message "HTML copied to clipboard."))) |
382 | :preface | 415 | |
383 | (defun +ielm-init-history () | 416 | (defun org-subtree-to-html-to-clipboard () |
384 | (let ((path (etc/ "ielm/history" t))) | 417 | "Export current subtree to HTML." |
385 | (setq-local comint-input-ring-file-name path)) | 418 | (interactive) |
386 | (setq-local comint-input-ring-size 10000) | 419 | (org-to-html-to-clipboard nil :subtree)) |
387 | (setq-local comint-input-ignoredups t) | 420 | |
388 | (ignore-errors (comint-read-input-ring))) | 421 | (undohist-initialize) |
389 | (defun +ielm-write-history (&rest _args) | 422 | |
390 | (with-file-modes #o600 | 423 | (require 'hungry-delete) |
391 | (comint-write-input-ring))) | 424 | (setopt hungry-delete-chars-to-skip " \t" |
392 | (defun +ielm (&optional buf-name) | ||
393 | "Interactively evaluate Emacs Lisp expressions. | ||
394 | Switches to the buffer named BUF-NAME if provided (`*ielm*' by default), | ||
395 | or creates it if it does not exist. | ||
396 | See `inferior-emacs-lisp-mode' for details." | ||
397 | (interactive) | ||
398 | (let (old-point | ||
399 | (buf-name (or buf-name "*ielm*"))) | ||
400 | (unless (comint-check-proc buf-name) | ||
401 | (with-current-buffer (get-buffer-create buf-name) | ||
402 | (unless (zerop (buffer-size)) (setq old-point (point))) | ||
403 | (inferior-emacs-lisp-mode))) | ||
404 | (pop-to-buffer buf-name) | ||
405 | (when old-point (push-mark old-point)))) | ||
406 | :bind (:map emacs-lisp-mode-map | ||
407 | ("C-c C-z" . +ielm)) | ||
408 | :config | ||
409 | (add-hook 'ielm-mode-hook #'eldoc-mode) | ||
410 | (add-hook 'ielm-mode-hook #'+ielm-init-history) | ||
411 | (advice-add 'ielm-send-input :after #'+ielm-write-history)) | ||
412 | |||
413 | (use-package elec-pair | ||
414 | :config | ||
415 | (setopt electric-pair-skip-whitespace 'chomp) | ||
416 | (electric-pair-mode)) | ||
417 | |||
418 | (use-package bookmark | ||
419 | :config | ||
420 | (setopt bookmark-save-flag 1)) | ||
421 | |||
422 | (use-package sh-script | ||
423 | :config | ||
424 | (sh-electric-here-document-mode -1)) | ||
425 | |||
426 | (use-package cc-mode | ||
427 | :config | ||
428 | (setopt c-basic-offset 8)) | ||
429 | |||
430 | |||
431 | ;;; Applications | ||
432 | |||
433 | (use-package acdw-mail | ||
434 | :load-path "lisp/" | ||
435 | :demand t | ||
436 | :bind (("C-c n" . +notmuch-goto))) | ||
437 | |||
438 | (use-package acdw-org | ||
439 | :load-path "lisp/" | ||
440 | :config | ||
441 | (global-set-key [f8] #'org-clock-out)) | ||
442 | |||
443 | (use-package acdw-shell | ||
444 | :load-path "lisp/") | ||
445 | |||
446 | (use-package acdw-web | ||
447 | :load-path "lisp/") | ||
448 | |||
449 | (use-package acdw-chat | ||
450 | :load-path "lisp/") | ||
451 | |||
452 | (use-package _work | ||
453 | :load-path "~/sync/emacs/private/") | ||
454 | |||
455 | |||
456 | ;;; Locally-developed packages | ||
457 | |||
458 | (use-package +scratch | ||
459 | :load-path "lisp/" | ||
460 | :config | ||
461 | (setq +scratch-save-dir (sync/ "emacs/scratch.d/" t)) | ||
462 | (add-hook 'kill-buffer-query-functions #'+scratch@immortal) | ||
463 | (add-hook 'kill-emacs-hook #'+scratch-save-on-exit) | ||
464 | (with-current-buffer (get-scratch-buffer-create) | ||
465 | (local-set-key (kbd "C-x C-s") #'+scratch-save)) | ||
466 | ;; Save *scratch* every hour | ||
467 | (run-at-time t (* 60 60) #'+scratch-save "%FT%H%z") | ||
468 | ;; Clean old *scratch* saves every day | ||
469 | (run-at-time t (* 60 60 24) #'+scratch-clean)) | ||
470 | |||
471 | (use-package pulse-location | ||
472 | :load-path "~/src/pulse-location.el/" | ||
473 | :config | ||
474 | (pulse-location-mode)) | ||
475 | |||
476 | (use-package emacs ; `modus-themes' isn't a package ... | ||
477 | :config | ||
478 | (setopt modus-themes-mixed-fonts t) | ||
479 | (add-hook 'modus-themes-after-load-theme-hook | ||
480 | (defun +reset-faces () | ||
481 | (dolist (face '(font-lock-regexp-face | ||
482 | font-lock-variable-name-face | ||
483 | font-lock-preprocessor-face | ||
484 | font-lock-remove-face | ||
485 | font-lock-delimiter-face | ||
486 | font-lock-label-face | ||
487 | font-lock-operator-face | ||
488 | font-lock-property-face | ||
489 | font-lock-builtin-face | ||
490 | font-lock-number-face | ||
491 | font-lock-set-face | ||
492 | font-lock-warning-face | ||
493 | font-lock-punctuation-face | ||
494 | font-lock-constant-face | ||
495 | font-lock-type-face | ||
496 | font-lock-function-name-face | ||
497 | font-lock-reference-face | ||
498 | font-lock-negation-char-face | ||
499 | font-lock-misc-punctuation-face | ||
500 | font-lock-escape-face | ||
501 | font-lock-bracket-face)) | ||
502 | (face-spec-set face '((t :foreground unspecified | ||
503 | :background unspecified)))) | ||
504 | (face-spec-set 'font-lock-keyword-face | ||
505 | '((t :foreground unspecified | ||
506 | :background unspecified | ||
507 | :weight bold))) | ||
508 | (face-spec-set 'font-lock-doc-face | ||
509 | '((t :slant italic))))) | ||
510 | (add-hook 'after-init-hook | ||
511 | (defun modus@load () | ||
512 | (+reset-faces) | ||
513 | (pcase (string-trim (shell-command-to-string "darkman get")) | ||
514 | ("light" (load-theme 'modus-operandi t)) | ||
515 | ("dark" (load-theme 'modus-vivendi t)))))) | ||
516 | |||
517 | (use-package electric-cursor | ||
518 | :load-path "~/src/electric-cursor.el/" | ||
519 | :config | ||
520 | (setq electric-cursor-alist '((overwrite-mode . box) | ||
521 | (t . bar))) | ||
522 | (electric-cursor-mode)) | ||
523 | |||
524 | (use-package mode-line-bell | ||
525 | :load-path "~/src/mode-line-bell.el/" | ||
526 | :config | ||
527 | (setq mode-line-bell-flash-time 0.25) | ||
528 | (mode-line-bell-mode)) | ||
529 | |||
530 | (use-package titlecase | ||
531 | :load-path "~/src/titlecase.el/" | ||
532 | :preface | ||
533 | (defun +titlecase-sentence-style-dwim (&optional arg) | ||
534 | "Titlecase a sentence. | ||
535 | With prefix ARG, toggle the value of | ||
536 | `titlecase-downcase-sentences' before sentence-casing." | ||
537 | (interactive "P") | ||
538 | (let ((titlecase-downcase-sentences (if arg (not titlecase-downcase-sentences) | ||
539 | titlecase-downcase-sentences))) | ||
540 | (titlecase-dwim 'sentence))) | ||
541 | (defun +titlecase-org-headings () | ||
542 | (interactive) | ||
543 | (require 'org) | ||
544 | (save-excursion | ||
545 | (goto-char (point-min)) | ||
546 | ;; See also `org-map-tree'. I'm not using that function because I want to | ||
547 | ;; skip the first headline. A better solution would be to patch | ||
548 | ;; `titlecase-line' to ignore org-mode metadata (TODO cookies, tags, etc). | ||
549 | (let ((level (funcall outline-level)) | ||
550 | (org-special-ctrl-a/e t)) | ||
551 | (while (and (progn (outline-next-heading) | ||
552 | (> (funcall outline-level) level)) | ||
553 | (not (eobp))) | ||
554 | (titlecase-region (progn (org-beginning-of-line) (point)) | ||
555 | (progn (org-end-of-line) (point))))))) | ||
556 | :config | ||
557 | (with-eval-after-load 'scule | ||
558 | (keymap-set scule-map "M-t" #'titlecase-dwim))) | ||
559 | |||
560 | (use-package scule | ||
561 | :load-path "~/src/scule.el/" | ||
562 | :bind-keymap ("M-c" . scule-map) | ||
563 | :init | ||
564 | ;; Use M-u for prefix keys | ||
565 | (keymap-global-set "M-u" #'universal-argument) | ||
566 | (keymap-set universal-argument-map "M-u" #'universal-argument-more)) | ||
567 | |||
568 | (use-package filldent | ||
569 | :load-path "~/src/filldent.el/" | ||
570 | :bind ("M-q" . filldent-dwim) | ||
571 | :config | ||
572 | (setq filldent-fill-modes '(web-mode))) | ||
573 | |||
574 | (use-package frowny | ||
575 | :load-path "~/src/frowny.el/" | ||
576 | :config | ||
577 | (global-frowny-mode)) | ||
578 | |||
579 | (use-package keepassxc-shim | ||
580 | :load-path "~/src/keepassxc-shim.el/" | ||
581 | :config | ||
582 | (keepassxc-shim-activate)) | ||
583 | |||
584 | (use-package hippie-completing-read | ||
585 | :load-path "~/src/hippie-completing-read.el/" | ||
586 | :bind (("M-/" . hippie-completing-read))) | ||
587 | |||
588 | |||
589 | ;;; External packages | ||
590 | |||
591 | (use-package async | ||
592 | :ensure t | ||
593 | :config | ||
594 | ;; https://github.com/jwiegley/emacs-async/issues/64 | ||
595 | ;; (setq message-send-mail-function #'async-smtpmail-send-it) | ||
596 | (dired-async-mode) | ||
597 | (async-bytecomp-package-mode)) | ||
598 | |||
599 | (use-package trashed | ||
600 | :ensure t) | ||
601 | |||
602 | (use-package form-feed | ||
603 | :ensure t | ||
604 | :hook (prog-mode-hook)) | ||
605 | |||
606 | ;; (use-package clean-kill-ring | ||
607 | ;; :vc (:url "https://github.com/NicholasBHubbard/clean-kill-ring.el") | ||
608 | ;; :config | ||
609 | ;; (setq clean-kill-ring-prevent-duplicates t) | ||
610 | ;; (clean-kill-ring-mode)) | ||
611 | |||
612 | (use-package minions | ||
613 | :ensure t | ||
614 | :config (minions-mode)) | ||
615 | |||
616 | (use-package visual-fill-column | ||
617 | :preface | ||
618 | (defcustom visual-fill-column-widen-amount 4 | ||
619 | "Amount to widen `fill-column' by in `visual-fill-column-mode'." | ||
620 | :type 'natnum | ||
621 | :group 'visual-fill-column) | ||
622 | (defun visual-fill-column--widen/narrow-handle-arg (cols) | ||
623 | (cond | ||
624 | ((null cols) visual-fill-column-widen-amount) | ||
625 | ((listp cols) (* visual-fill-column-widen-amount | ||
626 | (1+ (/ (car cols) 4)))) | ||
627 | ((eq '- cols) (- visual-fill-column-widen-amount)) | ||
628 | (:else cols))) | ||
629 | (defun visual-fill-column-widen (&optional cols) | ||
630 | "Widen `fill-column' by COLS, and re-display. | ||
631 | If COLS is missing or nil, widen by | ||
632 | `visual-fill-column-widen-amount'. When called with a plain | ||
633 | \\[universal-argument], multiply that amount by 1 + the amount of | ||
634 | \\[universal-argument]s. If called with a numerical prefix | ||
635 | argument, widen by that number of columns." | ||
636 | (interactive "P") | ||
637 | (let ((cols (visual-fill-column--widen/narrow-handle-arg cols))) | ||
638 | (cl-incf fill-column cols) | ||
639 | (visual-fill-column-adjust) | ||
640 | (message "Fill-column: %s" fill-column))) | ||
641 | (defun visual-fill-column-narrow (&optional cols) | ||
642 | "Narrow `fill-column' by COLS, then redisplay. | ||
643 | The prefix argument is as in `visual-fill-column-widen' but negated." | ||
644 | (interactive "P") | ||
645 | (let ((cols (visual-fill-column--widen/narrow-handle-arg cols))) | ||
646 | (cl-decf fill-column cols) | ||
647 | (visual-fill-column-adjust) | ||
648 | (message "Fill-column: %s" fill-column))) | ||
649 | :ensure t | ||
650 | :config | ||
651 | (setopt visual-fill-column-center-text t | ||
652 | visual-fill-column-extra-text-width '(3 . 3) | ||
653 | visual-fill-column-width (+ fill-column 4)) | ||
654 | (keymap-set toggle-map "v" #'visual-fill-column-mode) | ||
655 | (keymap-set visual-fill-column-mode-map "C-x C->" #'visual-fill-column-widen) | ||
656 | (keymap-set visual-fill-column-mode-map "C-x C-<" #'visual-fill-column-narrow) | ||
657 | (add-hook 'visual-fill-column-mode-hook #'visual-line-mode) | ||
658 | (add-hook 'eww-mode-hook #'visual-fill-column-mode) | ||
659 | (advice-add 'text-scale-adjust :after #'visual-fill-column-adjust)) | ||
660 | |||
661 | (use-package mlscroll | ||
662 | :ensure t :defer 1 | ||
663 | :after modus-themes | ||
664 | :preface | ||
665 | (define-advice load-theme (:after (&rest _) mlscroll) | ||
666 | (mlscroll-mode -1) | ||
667 | (when (seq-intersection '(modus-vivendi modus-operandi) | ||
668 | custom-enabled-themes) | ||
669 | (modus-themes-with-colors | ||
670 | (setq mlscroll-in-color fg-dim | ||
671 | mlscroll-out-color bg-inactive))) | ||
672 | (run-with-idle-timer 1 nil #'mlscroll-mode)) | ||
673 | :config | ||
674 | (load-theme@mlscroll)) | ||
675 | |||
676 | (use-package cape | ||
677 | :ensure t | ||
678 | :config | ||
679 | (add-hook 'completion-at-point-functions #'cape-file 90) | ||
680 | (add-hook 'completion-at-point-functions #'cape-dabbrev 91) | ||
681 | (advice-add 'emacs-completion-at-point | ||
682 | :around #'cape-wrap-nonexclusive)) | ||
683 | |||
684 | (use-package wgrep | ||
685 | :ensure t | ||
686 | :config | ||
687 | (setq wgrep-enable-key (kbd "C-x C-q")) | ||
688 | :bind (:map grep-mode-map | ||
689 | ("C-x C-q" . wgrep-change-to-wgrep-mode))) | ||
690 | |||
691 | (use-package avy | ||
692 | :ensure t | ||
693 | :bind (("M-j" . avy-goto-char-timer) | ||
694 | :map isearch-mode-map | ||
695 | ("M-j" . avy-isearch)) | ||
696 | :config | ||
697 | (setq avy-background t | ||
698 | avy-keys (string-to-list "asdfghjklqwertyuiopzxcvbnm"))) | ||
699 | |||
700 | (use-package zzz-to-char | ||
701 | :ensure t | ||
702 | :bind (("M-z" . zzz-to-char))) | ||
703 | |||
704 | (use-package anzu | ||
705 | :ensure t | ||
706 | :bind (("M-%" . anzu-query-replace-regexp) | ||
707 | ("C-M-%" . anzu-query-replace))) | ||
708 | |||
709 | (use-package isearch-mb | ||
710 | :ensure t | ||
711 | :config | ||
712 | (setq isearch-lazy-count t | ||
713 | isearch-regexp-lax-whitespace t | ||
714 | search-whitespace-regexp "\\W+" | ||
715 | search-default-mode t ; Search regexp by default | ||
716 | isearch-wrap-pause 'no) | ||
717 | (define-advice isearch-cancel (:before (&rest _) add-search-to-history) | ||
718 | "Add search string to history when canceling." | ||
719 | (unless (equal "" isearch-string) | ||
720 | (isearch-update-ring isearch-string isearch-regexp))) | ||
721 | (define-advice perform-replace (:around (orig &rest r) no-anykey-exit) | ||
722 | "Don't exit replace for any key that's not in `query-replace-map'." | ||
723 | (save-window-excursion | ||
724 | (cl-letf* ((lookup-key-orig (symbol-function 'lookup-key)) | ||
725 | ((symbol-function 'lookup-key) | ||
726 | (lambda (map key &optional accept-default) | ||
727 | (or (apply lookup-key-orig map key accept-default) | ||
728 | (when (eq map query-replace-map) 'help))))) | ||
729 | (apply orig r)))) | ||
730 | ;; Consult | ||
731 | (autoload 'consult-line "consult" nil t) | ||
732 | (autoload 'consult-isearch-history "consult" nil t) | ||
733 | (add-to-list 'isearch-mb--after-exit #'consult-line) | ||
734 | (add-to-list 'isearch-mb--with-buffer #'consult-isearch-history) | ||
735 | (keymap-set isearch-mb-minibuffer-map "M-s l" #'consult-line) | ||
736 | (keymap-set isearch-mb-minibuffer-map "M-r" #'consult-isearch-history) | ||
737 | ;; Anzu | ||
738 | (autoload 'anzu-isearch-query-replace "anzu" nil t) | ||
739 | (autoload 'anzu-isearch-query-replace-regexp "anzu" nil t) | ||
740 | (add-to-list 'isearch-mb--after-exit #'anzu-isearch-query-replace) | ||
741 | (add-to-list 'isearch-mb--after-exit #'anzu-isearch-query-replace-regexp) | ||
742 | (keymap-set isearch-mb-minibuffer-map | ||
743 | "M-%" #'anzu-isearch-query-replace-regexp) | ||
744 | (keymap-set isearch-mb-minibuffer-map | ||
745 | "C-M-%" #'anzu-isearch-query-replace) | ||
746 | (isearch-mb-mode)) | ||
747 | |||
748 | ;; (use-package paredit | ||
749 | ;; :ensure t | ||
750 | ;; :hook ( emacs-lisp-mode-hook ielm-mode-hook | ||
751 | ;; eval-expression-minibuffer-setup-hook | ||
752 | ;; lisp-interaction-mode-hook | ||
753 | ;; lisp-mode-hook scheme-mode-hook | ||
754 | ;; fennel-mode-hook fennel-repl-mode-hook | ||
755 | ;; geiser-mode-hook geiser-repl-mode-hook) | ||
756 | ;; :config | ||
757 | ;; (keymap-set paredit-mode-map "C-j" | ||
758 | ;; (defun +paredit-newline () | ||
759 | ;; (interactive) | ||
760 | ;; (call-interactively | ||
761 | ;; (if (derived-mode-p 'lisp-interaction-mode) | ||
762 | ;; #'eval-print-last-sexp #'paredit-newline)))) | ||
763 | ;; (keymap-unset paredit-mode-map "RET" t) | ||
764 | ;; (keymap-unset paredit-mode-map "M-s" t) | ||
765 | ;; (keymap-unset paredit-mode-map "M-r" t) | ||
766 | ;; (add-to-list 'paredit-space-for-delimiter-predicates | ||
767 | ;; (defun paredit@dont-space-@ (endp delimiter) | ||
768 | ;; "Don't add a space after @ in `paredit-mode'." | ||
769 | ;; (let ((point (point))) | ||
770 | ;; (or endp | ||
771 | ;; (seq-every-p | ||
772 | ;; (lambda (prefix) | ||
773 | ;; (and (> point (length prefix)) | ||
774 | ;; (let ((start (- point (length prefix))) | ||
775 | ;; (end point)) | ||
776 | ;; (not (string= (buffer-substring start end) | ||
777 | ;; prefix))))) | ||
778 | ;; ;; Add strings to this list to inhibit adding a space | ||
779 | ;; ;; after them. | ||
780 | ;; '(",@"))))))) | ||
781 | |||
782 | (use-package hungry-delete | ||
783 | :ensure t | ||
784 | :config | ||
785 | (setq hungry-delete-chars-to-skip " \t" | ||
786 | hungry-delete-skip-regexp (format "[%s]" hungry-delete-chars-to-skip) | 425 | hungry-delete-skip-regexp (format "[%s]" hungry-delete-chars-to-skip) |
787 | hungry-delete-join-reluctantly nil) | 426 | hungry-delete-join-reluctantly nil) |
788 | (add-to-list 'hungry-delete-except-modes 'eshell-mode) | 427 | (add-to-list 'hungry-delete-except-modes 'eshell-mode) |
789 | (add-to-list 'hungry-delete-except-modes 'nim-mode) | 428 | (add-to-list 'hungry-delete-except-modes 'nim-mode) |
790 | (add-to-list 'hungry-delete-except-modes 'python-mode) | 429 | (add-to-list 'hungry-delete-except-modes 'python-mode) |
791 | ;; Keys | 430 | (global-hungry-delete-mode) |
792 | (with-eval-after-load 'paredit | 431 | |
793 | (define-key paredit-mode-map [remap paredit-backward-delete] | 432 | (setopt avy-background t |
794 | (defun paredit/hungry-delete-backward (arg) | 433 | avy-keys (string-to-list "asdfghjklqwertyuiopzxcvbnm")) |
795 | (interactive "*p") | 434 | (keymap-global-set "M-j" #'avy-goto-char-timer) |
796 | (if (looking-back hungry-delete-skip-regexp) | 435 | (keymap-set isearch-mode-map "M-j" #'avy-isearch) |
797 | (hungry-delete-backward (or arg 1)) | 436 | (keymap-global-set "M-z" #'zzz-to-char) |
798 | (paredit-backward-delete arg)))) | 437 | |
799 | (define-key paredit-mode-map [remap paredit-forward-delete] | 438 | (marginalia-mode) |
800 | (defun paredit/hungry-delete-forward (arg) | 439 | |
801 | (interactive "*p") | 440 | (keymap-global-set "C-x b" #'consult-buffer) |
802 | (if (looking-at hungry-delete-skip-regexp) | 441 | (keymap-global-set "C-x 4 b" #'consult-buffer-other-window) |
803 | (hungry-delete-forward (or arg 1)) | 442 | (keymap-global-set "C-x 5 b" #'consult-buffer-other-frame) |
804 | (paredit-forward-delete arg))))) | 443 | (keymap-global-set "C-x r b" #'consult-bookmark) |
805 | ;; Mode | 444 | (keymap-global-set "M-y" #'consult-yank-pop) |
806 | (global-hungry-delete-mode)) | 445 | (keymap-global-set "M-g g" #'consult-goto-line) |
807 | 446 | (keymap-global-set "M-g M-g" #'consult-goto-line) | |
808 | (use-package macrostep | 447 | (keymap-global-set "M-g o" #'consult-outline) |
809 | :ensure t | 448 | (keymap-global-set "M-g m" #'consult-mark) |
810 | :after elisp-mode | 449 | (keymap-global-set "M-g i" #'consult-imenu) |
811 | :bind ( :map emacs-lisp-mode-map | 450 | (keymap-global-set "M-s d" #'consult-find) |
812 | ("C-c e" . macrostep-expand) | 451 | (keymap-global-set "M-s D" #'consult-locate) |
813 | :map lisp-interaction-mode-map | 452 | (keymap-global-set "M-s g" #'consult-grep) |
814 | ("C-c e" . macrostep-expand))) | 453 | (keymap-global-set "M-s G" #'consult-git-grep) |
815 | 454 | (keymap-global-set "M-s r" #'consult-ripgrep) | |
816 | (use-package package-lint | 455 | (keymap-global-set "M-s l" #'consult-line) |
817 | :ensure t) | 456 | (keymap-global-set "M-s k" #'consult-keep-lines) |
818 | 457 | (keymap-global-set "M-s u" #'consult-focus-lines) | |
819 | (use-package sly | 458 | |
820 | :ensure t | 459 | (keymap-global-set "M-s e" #'consult-isearch-history) |
821 | :when inferior-lisp-program | 460 | (keymap-set isearch-mode-map "M-e" #'consult-isearch-history) |
822 | :preface | 461 | (keymap-set isearch-mode-map "M-s e" #'consult-isearch-history) |
823 | (setq inferior-lisp-program (choose-executable "sbcl")) | 462 | (keymap-set isearch-mode-map "M-s l" #'consult-line) |
824 | (defun +sly-start-or-mrepl () | 463 | |
825 | (interactive) | 464 | (keymap-set minibuffer-local-map "M-n" #'consult-history) |
826 | (if (ignore-errors (sly-connection)) | 465 | (keymap-set minibuffer-local-map "M-p" #'consult-history) |
827 | (sly-mrepl (lambda (buf) | 466 | |
828 | (display-buffer-pop-up-window buf nil))) | 467 | (setopt completion-in-region-function #'consult-completion-in-region |
829 | (call-interactively #'sly))) | 468 | xref-show-xrefs-function #'consult-xref |
830 | :config | 469 | xref-show-definitions-function #'consult-xref) |
831 | (autoload 'sly-mrepl "sly-mrepl" nil t) | 470 | |
832 | (keymap-set sly-mode-map "C-c C-z" #'+sly-start-or-mrepl) | 471 | (setopt initial-scratch-message ";;; Emacs!\n\n") |
833 | (setq sly-net-coding-system 'utf-8-unix) | 472 | |
834 | (sly-symbol-completion-mode -1)) | 473 | (keymap-global-set "C-x C-b" #'ibuffer) |
835 | 474 | (add-hook 'ibuffer-hook #'hl-line-mode) | |
836 | (use-package pdf-tools | ||
837 | :ensure t | ||
838 | :mode ("\\.[pP][dD][fF]\\'" . pdf-view-mode) | ||
839 | :magic ("%PDF" . pdf-view-mode) | ||
840 | :config | ||
841 | (pdf-tools-install)) | ||
842 | |||
843 | (use-package keychain-environment | ||
844 | :ensure t | ||
845 | :when (executable-find "keychain") | ||
846 | :hook (after-init-hook . keychain-refresh-environment)) | ||
847 | |||
848 | (use-package web-mode | ||
849 | :ensure t | ||
850 | :mode ("\\.phtml\\'" | ||
851 | "\\.tpl\\.php\\'" | ||
852 | "\\.[agj]sp\\'" | ||
853 | "\\.as[cp]x\\'" | ||
854 | "\\.erb\\'" | ||
855 | "\\.mustache\\'" | ||
856 | "\\.djhtml\\'" | ||
857 | "\\.html?\\'") | ||
858 | :config | ||
859 | (add-hook 'web-mode-hook | ||
860 | (defun web-mode@setup () | ||
861 | (indent-tabs-mode -1)))) | ||
862 | |||
863 | (use-package nginx-mode | ||
864 | :ensure t | ||
865 | :mode "/nginx/sites-\\(?:available\\|enabled\\)/") | ||
866 | |||
867 | (use-package markdown-mode | ||
868 | :ensure t | ||
869 | :mode "\\.\\(?:md\\|markdown\\|mkd\\|mdown\\|mkdn\\|mdwn\\)\\'" | ||
870 | :config | ||
871 | (setq markdown-command (choose-executable | ||
872 | '("pandoc" "--from=markdown" "--to=html5") | ||
873 | "markdown")) | ||
874 | (add-hook 'markdown-mode-hook #'visual-fill-column-mode)) | ||
875 | |||
876 | (use-package pandoc-mode | ||
877 | :ensure t | ||
878 | :hook ((markdown-mode-hook . pandoc-mode) | ||
879 | (pandoc-mode-hook . pandoc-load-default-settings))) | ||
880 | |||
881 | (use-package edit-indirect | ||
882 | :ensure | ||
883 | :bind (("C-c '" . edit-indirect-region))) | ||
884 | |||
885 | (use-package transpose-frame | ||
886 | :ensure t | ||
887 | :bind (("C-x 5 t" . transpose-frame) | ||
888 | ("C-x 5 h" . flop-frame) ; horizontal | ||
889 | ("C-x 5 v" . flip-frame) ; vertical | ||
890 | )) | ||
891 | |||
892 | (use-package magit | ||
893 | :pin melpa-stable | ||
894 | :ensure t | ||
895 | :bind ("C-x g" . magit)) | ||
896 | |||
897 | (use-package git-modes | ||
898 | :ensure t) | ||
899 | |||
900 | (use-package eradio | ||
901 | :ensure t | ||
902 | :preface | ||
903 | (defun eradio-toggle|play (&optional arg) | ||
904 | "Run `eradio-toggle', or `eradio-play' with prefix ARG." | ||
905 | (interactive "P") | ||
906 | (if arg (eradio-play) (eradio-toggle))) | ||
907 | :bind (("C-c r p" . eradio-toggle|play) | ||
908 | ("C-c r s" . eradio-stop)) | ||
909 | :config | ||
910 | (setq eradio-player '("mpv" "--no-video" "--no-terminal") | ||
911 | eradio-channels | ||
912 | ;; (name . url) | ||
913 | '(("Nightwave Plaza" . "http://radio.plaza.one/ogg") | ||
914 | ("Radio Paradise - Main Mix" . | ||
915 | "http://stream.radioparadise.com/rp_192m.ogg") | ||
916 | ("Radio Paradise - Mellow Mix" . | ||
917 | "http://stream.radioparadise.com/mellow-96m.ogg") | ||
918 | ("Radio Paradise - Rock Mix" . | ||
919 | "http://stream.radioparadise.com/rock-96m.ogg") | ||
920 | ("Radio Paradise - Global Mix" . | ||
921 | "http://stream.radioparadise.com/global-96m.ogg") | ||
922 | ("KLSU" . "http://130.39.238.143:8010/stream.mp3")) | ||
923 | ;; At some point I should actually ... write this in to this file or | ||
924 | ;; something. But until I decide to quit using radish altogether, this | ||
925 | ;; what I got. | ||
926 | ;; (with-current-buffer (find-file-noselect "~/etc/radish/stations") | ||
927 | ;; (let (chans) | ||
928 | ;; (dolist (line (string-split (buffer-substring-no-properties | ||
929 | ;; (point-min) (point-max)) | ||
930 | ;; "\n") | ||
931 | ;; chans) | ||
932 | ;; (unless (string-match-p "^#" line) | ||
933 | ;; (let* ((ll (string-split line "\t")) | ||
934 | ;; (url (cl-first ll)) | ||
935 | ;; (name (cl-second ll)) | ||
936 | ;; (tags (cl-third ll))) | ||
937 | ;; (when (and name | ||
938 | ;; (string-match-p "[^ \n\t]*://[^ \n\t]*" url)) | ||
939 | ;; (push (cons (format "%s - %s" name tags) url) | ||
940 | ;; chans))))))) | ||
941 | )) | ||
942 | |||
943 | (use-package wiki-abbrev | ||
944 | :after org ; Don't need abbrevs til I load org. | ||
945 | :load-path "~/src/wiki-abbrev.el/" | ||
946 | :config | ||
947 | (setq wiki-abbrev-file (etc/ "wiki-abbrevs")) | ||
948 | (wiki-abbrev-insinuate)) | ||
949 | |||
950 | (use-package flyspell-correct | ||
951 | :ensure t | ||
952 | :preface | ||
953 | (defun +flyspell-correct-buffer (&optional prefix) | ||
954 | "Run `flyspell-correct-wrapper' on all misspelled words in the buffer. | ||
955 | With PREFIX, prompt to change the current dictionary." | ||
956 | (interactive "P") | ||
957 | (flyspell-buffer) | ||
958 | (when prefix | ||
959 | (let ((current-prefix-arg nil)) | ||
960 | (call-interactively #'ispell-change-dictionary))) | ||
961 | (flyspell-correct-move (point-min) :forward :rapid)) | ||
962 | :after flyspell | ||
963 | :bind (("<f7>" . +flyspell-correct-buffer) | ||
964 | (:map flyspell-mode-map | ||
965 | ("C-;" . flyspell-correct-wrapper))) | ||
966 | :config | ||
967 | (setq flyspell-correct--cr-key ";") | ||
968 | (keymap-unset flyspell-mode-map "C-," t) | ||
969 | (keymap-unset flyspell-mode-map "C-." t)) | ||
970 | |||
971 | (use-package dired-subtree | ||
972 | :ensure t | ||
973 | :after dired | ||
974 | :bind (:map dired-mode-map | ||
975 | (("TAB" . dired-subtree-cycle) | ||
976 | ("i" . dired-subtree-toggle)))) | ||
977 | |||
978 | (use-package dired-hide-dotfiles | ||
979 | ;; I could maybe use a more general package for this ... see | ||
980 | ;; https://emacs.grym.io/#orgbbda609 | ||
981 | :ensure t | ||
982 | :bind (:map dired-mode-map | ||
983 | ("." . dired-hide-dotfiles-mode))) | ||
984 | |||
985 | (use-package dired-git-info | ||
986 | :ensure t | ||
987 | :bind (:map dired-mode-map | ||
988 | (")" . dired-git-info-mode)) | ||
989 | :config | ||
990 | (setq dgi-auto-hide-details-p nil)) | ||
991 | |||
992 | (use-package expand-region ; needed for embrace anyway | ||
993 | :ensure t | ||
994 | :bind (("C-=" . er/expand-region))) | ||
995 | |||
996 | (use-package embrace | ||
997 | :ensure t | ||
998 | :preface | ||
999 | (defmacro org-insert-or-embrace (char) | ||
1000 | "Define a function to insert CHAR, or `embrace' the region with it." | ||
1001 | (let* ((fn-name (intern (format "org-insert-or-embrace-%s" char))) | ||
1002 | (char (cond ((characterp char) char) | ||
1003 | ((stringp char) (string-to-char char)) | ||
1004 | (t (user-error "Bad format for char: %S" char))))) | ||
1005 | `(defun ,fn-name (n) | ||
1006 | ,(format "Insert N %ss, or surround the region with them." | ||
1007 | (char-to-string char)) | ||
1008 | (interactive "p") | ||
1009 | (if (region-active-p) | ||
1010 | (dotimes (_ n) | ||
1011 | (embrace--add-internal (region-beginning) (region-end) ,char) | ||
1012 | (forward-char 1)) | ||
1013 | (self-insert-command n ,char))))) | ||
1014 | (with-eval-after-load 'org | ||
1015 | (require 'embrace) | ||
1016 | (keymap-set org-mode-map "*" (org-insert-or-embrace "*")) | ||
1017 | (keymap-set org-mode-map "/" (org-insert-or-embrace "/")) | ||
1018 | (keymap-set org-mode-map "_" (org-insert-or-embrace "_")) | ||
1019 | (keymap-set org-mode-map "=" (org-insert-or-embrace "=")) | ||
1020 | (keymap-set org-mode-map "~" (org-insert-or-embrace "~")) | ||
1021 | (keymap-set org-mode-map "+" (org-insert-or-embrace "+"))) | ||
1022 | :bind (("C-'" . embrace-commander)) | ||
1023 | :hook ((org-mode-hook . embrace-org-mode-hook) | ||
1024 | (ruby-mode-hook . embrace-ruby-mode-hook) | ||
1025 | (emacs-lisp-mode-hook . embrace-emacs-lisp-mode-hook) | ||
1026 | (latex-mode-hook . embrace-LaTeX-mode-hook))) | ||
1027 | |||
1028 | (use-package apheleia | ||
1029 | :ensure t | ||
1030 | :config | ||
1031 | (setq apheleia-hide-log-buffers t) | ||
1032 | (setf (alist-get 'shfmt apheleia-formatters) | ||
1033 | '("shfmt" "--case-indent")) | ||
1034 | (global-set-key (kbd "M-C-\\") | ||
1035 | (defun +apheleia-format|indent-buffer () | ||
1036 | (interactive) | ||
1037 | (if-let ((formatters (apheleia--get-formatters))) | ||
1038 | (apheleia-format-buffer | ||
1039 | formatters | ||
1040 | (lambda () | ||
1041 | (with-demoted-errors "Apheleia: %s" | ||
1042 | (when buffer-file-name | ||
1043 | (let ((apheleia--format-after-save-in-progress t)) | ||
1044 | (apheleia--save-buffer-silently))) | ||
1045 | (run-hooks 'apheleia-post-format-hook)))) | ||
1046 | (indent-region (point-min) (point-max)) | ||
1047 | (when buffer-file-name | ||
1048 | (save-buffer)))))) | ||
1049 | |||
1050 | (use-package php-mode | ||
1051 | :ensure t) | ||
1052 | |||
1053 | (use-package rec-mode | ||
1054 | :ensure t) | ||
1055 | |||
1056 | |||
1057 | (use-package geiser | ||
1058 | :ensure t | ||
1059 | :config | ||
1060 | (when (executable-find "guile") | ||
1061 | (use-package geiser-guile :ensure t)) | ||
1062 | (when (executable-find "chicken") | ||
1063 | (use-package geiser-chicken :ensure t)) | ||
1064 | (when (or (prog1 (executable-find "chez") | ||
1065 | (setopt geiser-chez-binary | ||
1066 | (executable-find "chez"))) | ||
1067 | (executable-find "petite") | ||
1068 | (executable-find "scheme")) | ||
1069 | (use-package geiser-chez :ensure t)) | ||
1070 | (when (executable-find "gambit") | ||
1071 | (use-package geiser-gambit :ensure t)) | ||
1072 | (when (executable-find "chibi-scheme") | ||
1073 | (use-package geiser-chibi :ensure t)) | ||
1074 | (use-package macrostep-geiser | ||
1075 | :ensure t | ||
1076 | :config | ||
1077 | (eval-after-load 'geiser-mode | ||
1078 | '(add-hook 'geiser-mode-hook #'macrostep-geiser-setup)) | ||
1079 | (eval-after-load 'geiser-repl | ||
1080 | '(add-hook 'geiser-repl-mode-hook #'macrostep-geiser-setup))) | ||
1081 | (with-eval-after-load 'geiser-mode | ||
1082 | (keymap-set geiser-mode-map "C-c C-k" #'geiser-eval-buffer-and-go) | ||
1083 | (keymap-unset geiser-mode-map "C-." t) | ||
1084 | (keymap-unset scheme-mode-map "M-o" t))) | ||
1085 | |||
1086 | (use-package detached | ||
1087 | :when (executable-find "dtach") | ||
1088 | :ensure t | ||
1089 | :init | ||
1090 | (add-hook 'after-init-hook #'detached-init) | ||
1091 | :bind (([remap async-shell-command] . detached-shell-command) | ||
1092 | ([remap compile] . detached-compile) | ||
1093 | ([remap recompile] . detached-compile-recompile)) | ||
1094 | :config | ||
1095 | (setf detached-terminal-data-command system-type) | ||
1096 | (with-eval-after-load 'consult | ||
1097 | (global-set-key [remap detached-open-session] #'detached-consult-session))) | ||
1098 | |||
1099 | (use-package lin | ||
1100 | :ensure t | ||
1101 | :config | ||
1102 | (setq lin-face 'lin-cyan | ||
1103 | lin-mode-hooks | ||
1104 | '(dired-mode-hook | ||
1105 | ;; bongo-mode-hook | ||
1106 | ;; elfeed-search-mode-hook | ||
1107 | git-rebase-mode-hook | ||
1108 | grep-mode-hook | ||
1109 | ibuffer-mode-hook | ||
1110 | ilist-mode-hook | ||
1111 | ;; ledger-report-mode-hook | ||
1112 | log-view-mode-hook | ||
1113 | magit-log-mode-hook | ||
1114 | ;; mu4e-headers-mode-hook | ||
1115 | notmuch-search-mode-hook | ||
1116 | notmuch-tree-mode-hook | ||
1117 | occur-mode-hook | ||
1118 | org-agenda-mode-hook | ||
1119 | pdf-outline-buffer-mode-hook | ||
1120 | proced-mode-hook | ||
1121 | tabulated-list-mode-hook)) | ||
1122 | (lin-global-mode)) | ||
1123 | |||
1124 | (use-package gcmh | ||
1125 | :ensure t | ||
1126 | :config | ||
1127 | (setq gcmh-idle-delay 'auto | ||
1128 | gcmh-verbose nil) | ||
1129 | (gcmh-mode)) | ||
1130 | |||
1131 | (use-package tmr | ||
1132 | :ensure t | ||
1133 | :preface | ||
1134 | (defun tmr-mode-line () | ||
1135 | (if (seq-find (lambda (tmr) | ||
1136 | (not (tmr--timer-finishedp tmr))) | ||
1137 | tmr--timers) | ||
1138 | (propertize "⏲" 'face 'font-lock-warning-face) | ||
1139 | "")) | ||
1140 | ;; (add-to-list 'global-mode-string | ||
1141 | ;; '("" (:eval (tmr-mode-line))) | ||
1142 | ;; 'append) | ||
1143 | ) | ||
1144 | |||
1145 | (use-package dumb-jump | ||
1146 | :ensure t | ||
1147 | :hook ((xref-backend-functions . dumb-jump-xref-activate))) | ||
1148 | |||
1149 | (use-package le-thesaurus | ||
1150 | :ensure t | ||
1151 | :bind (("C-c w s" . le-thesaurus-get-synonyms) | ||
1152 | ("C-c w a" . le-thesaurus-get-antonyms))) | ||
1153 | |||
1154 | (use-package devdocs | ||
1155 | :ensure t | ||
1156 | ;; not sure what to bind anything to yet ... so M-x it is | ||
1157 | ) | ||
1158 | |||
1159 | (use-package comment-dwim-2 | ||
1160 | :ensure t | ||
1161 | :bind (("M-;" . comment-dwim-2) | ||
1162 | :map org-mode-map | ||
1163 | ("M-;" . org-comment-dwim-2))) | ||