summary refs log tree commit diff stats
path: root/init.el
diff options
context:
space:
mode:
Diffstat (limited to 'init.el')
-rw-r--r--init.el756
1 files changed, 462 insertions, 294 deletions
diff --git a/init.el b/init.el index c73e169..ffe7f81 100644 --- a/init.el +++ b/init.el
@@ -12,13 +12,14 @@
12(yoke +emacs 12(yoke +emacs
13 (require* '+emacs '+window '+lisp) 13 (require* '+emacs '+window '+lisp)
14 ;; Settings 14 ;; Settings
15 (setf truncate-string-ellipsis "…" 15 (setc truncate-string-ellipsis "…"
16 ring-bell-function #'ignore 16 ring-bell-function #'ignore
17 read-file-name-completion-ignore-case t 17 read-file-name-completion-ignore-case t
18 comment-auto-fill-only-comments t 18 comment-auto-fill-only-comments t
19 password-cache t 19 password-cache t
20 eww-use-browse-url "." ; use `browse-url' in every link
21 password-cache-expiry (* 60 60) 20 password-cache-expiry (* 60 60)
21 switch-to-buffer-in-dedicated-window 'pop
22 switch-to-buffer-obey-display-actions t
22 initial-buffer-choice (defun +initial-buffer-choose () 23 initial-buffer-choice (defun +initial-buffer-choose ()
23 (cond 24 (cond
24 ((equal (get-buffer "*Messages*") 25 ((equal (get-buffer "*Messages*")
@@ -40,7 +41,7 @@
40 'custom-type))))))))) 41 'custom-type)))))))))
41 (put (car var+pred) 'safe-local-variable (cdr var+pred))) 42 (put (car var+pred) 'safe-local-variable (cdr var+pred)))
42 ;; Keys 43 ;; Keys
43 (define-key* (current-global-map) 44 (defkeys t
44 "C-x C-k" #'kill-current-buffer 45 "C-x C-k" #'kill-current-buffer
45 "C-/" #'undo-only 46 "C-/" #'undo-only
46 "C-?" #'undo-redo 47 "C-?" #'undo-redo
@@ -68,9 +69,25 @@
68 "M-o" #'other-window|switch-buffer 69 "M-o" #'other-window|switch-buffer
69 "C-M-;" #'+lisp-comment-or-uncomment-sexp 70 "C-M-;" #'+lisp-comment-or-uncomment-sexp
70 "C-x 5 z" #'suspend-frame 71 "C-x 5 z" #'suspend-frame
71 "M-@" #'dictionary-search 72 "C-x f" #'find-file
72 "C-x f" #'find-file) 73 "C-c t" (defmap toggle-map
73 (define-key* text-mode-map 74 "A map for toggling various settings."
75 "d" (defmap toggle-debug-map
76 "Easily toggle debug flavors."
77 "e" #'toggle-debug-on-error
78 "q" #'toggle-debug-on-quit)
79 "w" #'toggle-word-wrap
80 "t" #'toggle-truncate-lines
81 "c" #'column-number-mode
82 "l" #'line-number-mode
83 "v" (defmap toggle-view-map
84 "Easily toggle UI elements' views."
85 "c" #'display-fill-column-indicator-mode
86 "l" #'display-line-numbers-mode
87 "m" #'menu-bar-mode
88 "t" #'tool-bar-mode
89 "s" #'scroll-bar-mode)))
90 (defkeys text-mode-map
74 "C-M-k" #'kill-paragraph 91 "C-M-k" #'kill-paragraph
75 "C-o" (defun open-paragraph (&optional arg) 92 "C-o" (defun open-paragraph (&optional arg)
76 "Open a paragraph after paragraph at point. 93 "Open a paragraph after paragraph at point.
@@ -123,24 +140,63 @@ Called with prefix ARG, open a paragraph before point."
123 (eval-after init 140 (eval-after init
124 (+custom-load-some-customizations :noerror))) 141 (+custom-load-some-customizations :noerror)))
125 142
126(yoke modus-themes 143;; (yoke modus-themes
127 (setf modus-themes-bold-constructs t 144;; (setc modus-themes-bold-constructs t
128 modus-themes-italic-constructs t 145;; modus-themes-italic-constructs t
129 modus-themes-headings '((1 monochrome bold italic) 146;; modus-themes-headings '((1 monochrome bold italic)
130 (2 monochrome bold) 147;; (2 monochrome bold)
131 (3 monochrom italic) 148;; (3 monochrom italic)
132 (t monochrome))) 149;; (t monochrome)))
133 (cond ((require 'dawn nil :noerrer) 150;; (defhook modus-themes-after-load-theme-hook
134 (add-hook* '+custom-after-load-hook 151;; :name modus-monochrome
135 (defun dawn@custom () 152;; (modus-themes-with-colors
136 (load-theme 'modus-operandi :noconfirm :noenable) 153;; (cl-loop for x being the symbols
137 (load-theme 'modus-vivendi :noconfirm :noenable) 154;; if (string-match-p "\\`font-lock-.*-face\\'"
138 (dawn-schedule #'modus-themes-load-operandi 155;; (symbol-name x))
139 #'modus-themes-load-vivendi)))) 156;; do
140 (:else (load-theme 'modus-operandi)))) 157;; (custom-set-faces
158;; `(,x ((,class :foreground
159;; ,(cond
160;; ((memq x '(font-lock-string-face
161;; font-lock-doc-face
162;; font-lock-doc-markup-face))
163;; fg-special-warm)
164;; ((memq x '(font-lock-warning-face))
165;; fg-lang-warning)
166;; ((memq x '(font-lock-comment-face))
167;; fg-alt)
168;; (:else 'unspecified))
169;; :background unspecified
170;; :weight
171;; ,(cond
172;; ((memq x '(font-lock-keyword-face))
173;; 'bold)
174;; (:else 'normal))
175;; :slant
176;; ,(cond
177;; ((memq x '(font-lock-doc-face
178;; font-lock-comment-face))
179;; 'italic)
180;; (:else 'normal))
181;; :underline
182;; ,(cond
183;; ((memq x '(font-lock-warning-face))
184;; t)
185;; (:else nil)))))))))
186;; (when (or (custom-theme-enabled-p 'modus-operandi)
187;; (custom-theme-enabled-p 'modus-vivendi))
188;; (modus-monochrome))
189;; (cond ((require 'dawn nil :noerrer)
190;; (defhook +custom-after-load-hook
191;; :name dawn@custom
192;; (load-theme 'modus-operandi :noconfirm :noenable)
193;; (load-theme 'modus-vivendi :noconfirm :noenable)
194;; (dawn-schedule #'modus-themes-load-operandi
195;; #'modus-themes-load-vivendi)))
196;; (:else (modus-themes-load-operandi))))
141 197
142(yoke time 198(yoke time
143 (setf display-time-mail-function 199 (setc display-time-mail-function
144 (defun +notmuch-new-mail-p () 200 (defun +notmuch-new-mail-p ()
145 (plist-get (cl-find "inbox+unread" 201 (plist-get (cl-find "inbox+unread"
146 (ignore-errors 202 (ignore-errors
@@ -148,13 +204,16 @@ Called with prefix ARG, open a paragraph before point."
148 :key (lambda (l) (plist-get l :name)) 204 :key (lambda (l) (plist-get l :name))
149 :test #'equal) 205 :test #'equal)
150 :count)) 206 :count))
151 display-time-use-mail-icon t 207 display-time-use-mail-icon nil
208 display-time-mail-string (format "⋅ Mail (%s)" (+notmuch-new-mail-p))
152 read-mail-command #'+notmuch-goto 209 read-mail-command #'+notmuch-goto
153 display-time-format " %a %-e, %H:%M" 210 display-time-format " %a %-e, %H:%M"
154 ;; `display-time-format' makes these unnecessary, but I'll keep em 211 ;; `display-time-format' makes these unnecessary, but I'll keep em
155 display-time-24hr-format t 212 display-time-24hr-format t
156 display-time-day-and-date t 213 display-time-day-and-date t
157 display-time-default-load-average nil) 214 display-time-default-load-average nil)
215 (define-advice display-time-update (:after (&rest _) update-mail-count)
216 (setq display-time-mail-string (format "⋅ Mail (%s)" (+notmuch-new-mail-p))))
158 (display-time-mode)) 217 (display-time-mode))
159 218
160(yoke pita 219(yoke pita
@@ -162,7 +221,7 @@ Called with prefix ARG, open a paragraph before point."
162 (advice-add 'indent-region :before #'with-region-or-buffer)) 221 (advice-add 'indent-region :before #'with-region-or-buffer))
163 222
164(yoke (undo-fu-session "https://codeberg.org/ideasman42/emacs-undo-fu-session") 223(yoke (undo-fu-session "https://codeberg.org/ideasman42/emacs-undo-fu-session")
165 (setf undo-fu-session-incompatible-files '("/COMMIT_EDITMSG\\'" 224 (setc undo-fu-session-incompatible-files '("/COMMIT_EDITMSG\\'"
166 "/git-rebase-todo\\'") 225 "/git-rebase-todo\\'")
167 undo-fu-session-directory (.etc "undo/" t) 226 undo-fu-session-directory (.etc "undo/" t)
168 undo-fu-session-compression (cond 227 undo-fu-session-compression (cond
@@ -173,19 +232,16 @@ Called with prefix ARG, open a paragraph before point."
173 (global-undo-fu-session-mode)) 232 (global-undo-fu-session-mode))
174 233
175(yoke whitespace 234(yoke whitespace
176 (setf whitespace-line-column nil 235 (setc whitespace-line-column nil
177 whitespace-style '( face trailing 236 whitespace-style '( face trailing
178 tabs tab-mark 237 tabs tab-mark
179 indentation 238 indentation
180 space-after-tab space-before-tab)) 239 space-after-tab space-before-tab))
181 (defun +whitespace-mode-for-writable-buffers () 240 (defhook (text-mode-hook prog-mode-hook read-only-mode-hook)
182 "Turn on `whitespace-mode' if the buffer is writable, off otherwise." 241 :name +whitespace-mode-for-writable-buffers
242 :doc "Turn on `whitespace-mode' if the buffer is writable, off otherwise."
183 (whitespace-mode (if buffer-read-only -1 t))) 243 (whitespace-mode (if buffer-read-only -1 t)))
184 (add-hook* '(text-mode-hook 244 (defhook before-save-hook #'whitespace-cleanup)
185 prog-mode-hook
186 read-only-mode-hook)
187 #'+whitespace-mode-for-writable-buffers)
188 (add-hook 'before-save-hook #'whitespace-cleanup)
189 (define-advice whitespace-cleanup (:around (fn &rest r) preserve-point) 245 (define-advice whitespace-cleanup (:around (fn &rest r) preserve-point)
190 (let ((col (current-column))) 246 (let ((col (current-column)))
191 (apply fn r) 247 (apply fn r)
@@ -193,9 +249,9 @@ Called with prefix ARG, open a paragraph before point."
193 (set-buffer-modified-p nil)))) 249 (set-buffer-modified-p nil))))
194 250
195(yoke elisp-mode 251(yoke elisp-mode
196 (setf eval-expression-print-length nil ; remove ellipses from `eval-expression' 252 (setc eval-expression-print-length nil ; remove ellipses from `eval-expression'
197 eval-expression-print-level nil) 253 eval-expression-print-level nil)
198 (define-key* '(emacs-lisp-mode-map lisp-interaction-mode-map) 254 (defkeys (emacs-lisp-mode-map lisp-interaction-mode-map)
199 "C-c C-c" #'eval-defun 255 "C-c C-c" #'eval-defun
200 "C-c C-k" (defun +elisp-eval-region-or-buffer () 256 "C-c C-k" (defun +elisp-eval-region-or-buffer ()
201 (interactive) 257 (interactive)
@@ -209,10 +265,10 @@ Called with prefix ARG, open a paragraph before point."
209 "C-c C-z" #'ielm) 265 "C-c C-z" #'ielm)
210 (define-advice eval-region (:around (fn beg end &rest args) pulse) 266 (define-advice eval-region (:around (fn beg end &rest args) pulse)
211 (apply fn beg end args) 267 (apply fn beg end args)
212 (pulse-momentary-highlight-region beg end))) 268 (pulse-momentary-highlight-region beg end)))
213 269
214(yoke isearch 270(yoke isearch
215 (define-key* (current-global-map) 271 (defkeys t
216 "C-s" #'isearch-forward-regexp 272 "C-s" #'isearch-forward-regexp
217 "C-r" #'isearch-backward-regexp 273 "C-r" #'isearch-backward-regexp
218 "C-M-s" #'isearch-forward 274 "C-M-s" #'isearch-forward
@@ -222,7 +278,7 @@ Called with prefix ARG, open a paragraph before point."
222 (require* '+ispell 'ispell) 278 (require* '+ispell 'ispell)
223 (add-hook 'before-save-hook 279 (add-hook 'before-save-hook
224 #'+ispell-move-buffer-words-to-dir-locals-hook) 280 #'+ispell-move-buffer-words-to-dir-locals-hook)
225 (setf ispell-program-name (or (executable-find "ispell") 281 (setc ispell-program-name (or (executable-find "ispell")
226 (executable-find "aspell"))) 282 (executable-find "aspell")))
227 (put 'ispell-buffer-session-localwords 283 (put 'ispell-buffer-session-localwords
228 'safe-local-variable #'+ispell-safe-local-p)) 284 'safe-local-variable #'+ispell-safe-local-p))
@@ -232,7 +288,7 @@ Called with prefix ARG, open a paragraph before point."
232 ;; Brand new for Emacs 28: see https://ruzkuku.com/texts/emacs-mouse.html 288 ;; Brand new for Emacs 28: see https://ruzkuku.com/texts/emacs-mouse.html
233 ;; Actually, look at this as well: https://www.emacswiki.org/emacs/Mouse3 289 ;; Actually, look at this as well: https://www.emacswiki.org/emacs/Mouse3
234 (when (fboundp 'context-menu-mode) 290 (when (fboundp 'context-menu-mode)
235 (setf context-menu-functions '(context-menu-ffap 291 (setc context-menu-functions '(context-menu-ffap
236 context-menu-region 292 context-menu-region
237 context-menu-undo 293 context-menu-undo
238 ;; context-menu-dictionary 294 ;; context-menu-dictionary
@@ -246,7 +302,7 @@ Called with prefix ARG, open a paragraph before point."
246 302
247(yoke dired 303(yoke dired
248 (require 'dired-x) 304 (require 'dired-x)
249 (setf dired-recursive-copies 'always 305 (setc dired-recursive-copies 'always
250 dired-recursive-deletes 'always 306 dired-recursive-deletes 'always
251 dired-create-destination-dirs 'always 307 dired-create-destination-dirs 'always
252 dired-do-revert-buffer t 308 dired-do-revert-buffer t
@@ -265,26 +321,25 @@ Called with prefix ARG, open a paragraph before point."
265 dired-dwim-target t) 321 dired-dwim-target t)
266 (setq-local-hook dired-mode-hook 322 (setq-local-hook dired-mode-hook
267 truncate-lines t) 323 truncate-lines t)
268 (define-key* (current-global-map) 324 (defkeys t
269 "C-x C-j" #'dired-jump 325 "C-x C-j" #'dired-jump
270 [remap list-directory] #'dired) 326 [remap list-directory] #'dired)
271 (eval-after dired 327 (defkeys ((dired-mode-map :after dired))
272 (define-key* dired-mode-map 328 "<backspace>" #'dired-up-directory
273 "<backspace>" #'dired-up-directory 329 "C-j" #'dired-up-directory)
274 "C-j" #'dired-up-directory)) 330 (defhook dired-mode-hook
275 (add-hook* 'dired-mode-hook
276 #'dired-hide-details-mode 331 #'dired-hide-details-mode
277 #'hl-line-mode)) 332 #'hl-line-mode))
278 333
279(yoke (dired-hacks "https://github.com/Fuco1/dired-hacks") 334(yoke (dired-hacks "https://github.com/Fuco1/dired-hacks")
280 (define-key* dired-mode-map 335 (defkeys dired-mode-map
281 "TAB" #'dired-subtree-sycle 336 "TAB" #'dired-subtree-sycle
282 "i" #'dired-subtree-toggle) 337 "i" #'dired-subtree-toggle)
283 (add-hook* 'dired-mode-hook 338 (defhook 'dired-mode-hook
284 #'dired-collapse-mode)) 339 #'dired-collapse-mode))
285 340
286(yoke auth-source 341(yoke auth-source
287 (setf auth-sources `(default "secrets:passwords")) 342 (setc auth-sources `(default "secrets:passwords"))
288 (setq-local-hook authinfo-mode-hook 343 (setq-local-hook authinfo-mode-hook
289 truncate-lines t)) 344 truncate-lines t))
290 345
@@ -299,54 +354,54 @@ Called with prefix ARG, open a paragraph before point."
299 consult--regexp-compiler #'consult--default-regexp-compiler) 354 consult--regexp-compiler #'consult--default-regexp-compiler)
300 (advice-add #'register-preview :override #'consult-register-window) 355 (advice-add #'register-preview :override #'consult-register-window)
301 (define-key* (current-global-map) 356 (define-key* (current-global-map)
302 ;; Etc 357 ;; Etc
303 "M-S-x" #'consult-mode-command 358 "M-S-x" #'consult-mode-command
304 ;; C-c bindings (mode-specific-map) 359 ;; C-c bindings (mode-specific-map)
305 "C-c h" #'consult-history 360 "C-c h" #'consult-history
306 "C-c b" #'consult-bookmark 361 "C-c b" #'consult-bookmark
307 "C-c k" #'consult-kmacro 362 "C-c k" #'consult-kmacro
308 ;; C-x bindings (ctl-x-map) 363 ;; C-x bindings (ctl-x-map)
309 "C-x M-:" #'consult-complex-command 364 "C-x M-:" #'consult-complex-command
310 "C-x b" #'consult-buffer 365 "C-x b" #'consult-buffer
311 "C-x 4 b" #'consult-buffer-other-window 366 "C-x 4 b" #'consult-buffer-other-window
312 "C-x 5 b" #'consult-buffer-other-frame 367 "C-x 5 b" #'consult-buffer-other-frame
313 ;; Custom M-# bindings for fast register access 368 ;; Custom M-# bindings for fast register access
314 "M-#" #'consult-register-load 369 "M-#" #'consult-register-load
315 "M-'" #'consult-register-store 370 "M-'" #'consult-register-store
316 "C-M-#" #'consult-register 371 "C-M-#" #'consult-register
317 ;; Other custom bindings 372 ;; Other custom bindings
318 "M-y" #'consult-yank-pop 373 "M-y" #'consult-yank-pop
319 ;;("<f1> a" . consult-apropos) 374 ;;("<f1> a" . consult-apropos)
320 ;; M-g bindings (goto-map) 375 ;; M-g bindings (goto-map)
321 "M-g e" #'consult-compile-error 376 "M-g e" #'consult-compile-error
322 "M-g f" #'consult-flymake ; or consult-flycheck 377 "M-g f" #'consult-flymake ; or consult-flycheck
323 "M-g g" #'consult-goto-line 378 "M-g g" #'consult-goto-line
324 "M-g M-g" #'consult-goto-line 379 "M-g M-g" #'consult-goto-line
325 "M-g o" #'consult-outline ; or consult-org-heading 380 "M-g o" #'consult-outline ; or consult-org-heading
326 "M-g m" #'consult-mark 381 "M-g m" #'consult-mark
327 "M-g k" #'consult-global-mark 382 "M-g k" #'consult-global-mark
328 "M-g i" #'consult-imenu 383 "M-g i" #'consult-imenu
329 "M-g M-i" #'consult-imenu 384 "M-g M-i" #'consult-imenu
330 "M-g I" #'consult-imenu-multi 385 "M-g I" #'consult-imenu-multi
331 ;; M-s bindings (search-map) 386 ;; M-s bindings (search-map)
332 "M-s f" #'consult-find 387 "M-s f" #'consult-find
333 "M-s F" #'consult-locate 388 "M-s F" #'consult-locate
334 "M-s g" #'consult-grep 389 "M-s g" #'consult-grep
335 "M-s G" #'consult-git-grep 390 "M-s G" #'consult-git-grep
336 "M-s r" #'consult-ripgrep 391 "M-s r" #'consult-ripgrep
337 "M-s l" #'consult-line 392 "M-s l" #'consult-line
338 "M-s L" #'consult-line-multi 393 "M-s L" #'consult-line-multi
339 "M-s m" #'consult-multi-occur 394 "M-s m" #'consult-multi-occur
340 "M-s k" #'consult-keep-lines 395 "M-s k" #'consult-keep-lines
341 "M-s u" #'consult-focus-lines 396 "M-s u" #'consult-focus-lines
342 ;; Isearch integration 397 ;; Isearch integration
343 "M-s e" #'consult-isearch-history) 398 "M-s e" #'consult-isearch-history)
344 (eval-after isearch-mode 399 (eval-after isearch-mode
345 (define-key* isearch-mode-map 400 (define-key* isearch-mode-map
346 "M-e" #'consult-isearch-history 401 "M-e" #'consult-isearch-history
347 "M-s e" #'consult-isearch-history 402 "M-s e" #'consult-isearch-history
348 "M-s l" #'consult-line 403 "M-s l" #'consult-line
349 "M-s L" #'consult-line-multi)) 404 "M-s L" #'consult-line-multi))
350 (eval-after org 405 (eval-after org
351 (define-key org-mode-map (kbd "M-g o") #'consult-org-heading)) 406 (define-key org-mode-map (kbd "M-g o") #'consult-org-heading))
352 (eval-after consult-imenu 407 (eval-after consult-imenu
@@ -368,19 +423,21 @@ Called with prefix ARG, open a paragraph before point."
368 (setf resize-mini-windows 'grow-only 423 (setf resize-mini-windows 'grow-only
369 vertico-count-format nil 424 vertico-count-format nil
370 vertico-cycle t) 425 vertico-cycle t)
371 (vertico-mode)) 426 (vertico-mode)
427 (add-to-list 'load-path (expand-file-name "vertico/extensions" yoke-dir))
428 (require 'vertico-directory)
429 (add-hook 'rfn-eshadow-update-overlay-hook #'vertico-directory-tidy))
372 430
373(yoke (embark "https://github.com/oantolin/embark") 431(yoke (embark "https://github.com/oantolin/embark")
374 (require 'embark) 432 (require 'embark)
375 (setf prefix-help-command #'embark-prefix-help-command 433 (setf prefix-help-command #'embark-prefix-help-command
376 embar-keymap-prompter-key ";") 434 embar-keymap-prompter-key ";")
377 (define-key* (list (current-global-map) 435 (defkeys (t minibuffer-local-map)
378 'minibuffer-local-map)
379 "C-." #'embark-act 436 "C-." #'embark-act
380 "M-." #'embark-dwim 437 "M-." #'embark-dwim
381 "<f1> B" #'embark-bindings) 438 "<f1> B" #'embark-bindings)
382 (define-key* embark-file-map 439 (define-key* embark-file-map
383 "l" #'vlf) 440 "l" #'vlf)
384 (eval-after (embark consult) 441 (eval-after (embark consult)
385 (require 'embark-consult) 442 (require 'embark-consult)
386 (add-hook 'embark-collect-mode-hook #'consult-preview-at-point-mode))) 443 (add-hook 'embark-collect-mode-hook #'consult-preview-at-point-mode)))
@@ -391,18 +448,23 @@ Called with prefix ARG, open a paragraph before point."
391(yoke (wgrep "https://github.com/mhayashi1120/Emacs-wgrep") 448(yoke (wgrep "https://github.com/mhayashi1120/Emacs-wgrep")
392 (require 'wgrep) 449 (require 'wgrep)
393 (define-key* grep-mode-map 450 (define-key* grep-mode-map
394 "C-x C-q" #'wgrep-change-to-wgrep-mode)) 451 "C-x C-q" #'wgrep-change-to-wgrep-mode))
395 452
396(yoke (slime "https://github.com/slime/slime") 453(yoke (slime "https://github.com/slime/slime")
397 :when (executable-find "sbcl") 454 :when (executable-find "sbcl")
398 (setf inferior-lisp-program (executable-find "sbcl")) 455 (setc inferior-lisp-program (executable-find "sbcl"))
456 (defhook lisp-mode-hook
457 :name slime-mode-setup
458 (load (expand-file-name "~/quicklisp/slime-helper.el") :noerror)
459 (slime-mode))
399 (eval-after slime 460 (eval-after slime
400 (setf slime-completion-at-point-functions 461 (setc slime-completion-at-point-functions
401 (delq 'slime-c-p-c-completion-at-point 462 (delq 'slime-c-p-c-completion-at-point
402 slime-completion-at-point-functions)))) 463 slime-completion-at-point-functions))))
403 464
404(yoke (puni "https://github.com/amaikinono/puni") 465(yoke (puni "https://github.com/amaikinono/puni")
405 (define-key* puni-mode-map 466 (electric-pair-mode)
467 (defkeys puni-mode-map
406 "C-)" #'puni-slurp-forward 468 "C-)" #'puni-slurp-forward
407 "C-(" #'puni-slurp-backward 469 "C-(" #'puni-slurp-backward
408 "C-}" #'puni-barf-forward 470 "C-}" #'puni-barf-forward
@@ -411,16 +473,15 @@ Called with prefix ARG, open a paragraph before point."
411 (interactive "p") 473 (interactive "p")
412 (insert "()") 474 (insert "()")
413 (backward-char) 475 (backward-char)
414 (puni-slurp-forward n))) 476 (ignore-errors (puni-slurp-forward n))))
415 (electric-pair-mode) 477 (defhook (prog-mode-hook
416 (add-hook* '(prog-mode-hook 478 lisp-interaction-mode-hook emacs-lisp-mode-hook
417 ielm-mode-hook 479 lisp-mode-hook scheme-mode-hook
418 lisp-interaction-mode-hook 480 ielm-mode-hook eval-expression-minibuffer-setup-hook)
419 lisp-mode-hook scheme-mode-hook)
420 #'puni-mode)) 481 #'puni-mode))
421 482
422(yoke (hungry-delete "https://github.com/nflath/hungry-delete") 483(yoke (hungry-delete "https://github.com/nflath/hungry-delete")
423 (setq hungry-delete-chars-to-skip " \t" 484 (setc hungry-delete-chars-to-skip " \t"
424 hungry-delete-join-reluctantly nil) 485 hungry-delete-join-reluctantly nil)
425 (eval-after hungry-delete 486 (eval-after hungry-delete
426 (add-to-list* 'hungry-delete-except-modes 487 (add-to-list* 'hungry-delete-except-modes
@@ -432,15 +493,15 @@ Called with prefix ARG, open a paragraph before point."
432 hd-fn 493 hd-fn
433 fn) 494 fn)
434 arg)) 495 arg))
435 (define-key* puni-mode-map 496 (defkeys puni-mode-map
436 [remap puni-backward-delete-char] 497 [remap puni-backward-delete-char]
437 (defun puni@hungry-delete-backward (arg) 498 (defun +puni|hungry-delete-backward (arg)
438 (interactive "p") 499 (interactive "p")
439 (+hungry-delete-or #'hungry-delete-backward 500 (+hungry-delete-or #'hungry-delete-backward
440 #'puni-backward-delete-char 501 #'puni-backward-delete-char
441 arg)) 502 arg))
442 [remap puni-forward-delete-char] 503 [remap puni-forward-delete-char]
443 (defun puni@hungry-delete-forward (arg) 504 (defun +puni|hungry-delete-forward (arg)
444 (interactive "p") 505 (interactive "p")
445 (+hungry-delete-or #'hungry-delete-forward 506 (+hungry-delete-or #'hungry-delete-forward
446 #'puni-forward-delete-char 507 #'puni-forward-delete-char
@@ -468,18 +529,18 @@ CAPES defaults to `+capes'. CAPF will be made un-exclusive."
468 :load "lisp") 529 :load "lisp")
469 (dash "https://github.com/magnars/dash.el") 530 (dash "https://github.com/magnars/dash.el")
470 (with-editor "https://github.com/magit/with-editor" 531 (with-editor "https://github.com/magit/with-editor"
471 :load "lisp")) 532 :load "lisp"))
472 (autoload #'transient--with-suspended-override "transient") 533 (autoload #'transient--with-suspended-override "transient")
473 (autoload #'magit "magit" nil :interactive) 534 (autoload #'magit "magit" nil :interactive)
474 (define-key* (current-global-map) 535 (defkeys t
475 "C-x g" #'magit)) 536 "C-x g" #'magit))
476 537
477(yoke (git-modes "https://github.com/magit/git-modes") 538(yoke (git-modes "https://github.com/magit/git-modes")
478 (require 'git-modes)) 539 (require 'git-modes))
479 540
480(yoke (visual-fill-column "https://codeberg.org/joostkremers/visual-fill-column") 541(yoke (visual-fill-column "https://codeberg.org/joostkremers/visual-fill-column")
481 (setq visual-fill-column-center-text t) 542 (setc visual-fill-column-center-text t)
482 (add-hook* 'visual-fill-column-mode-hook #'visual-line-mode) 543 (add-hook 'visual-fill-column-mode-hook #'visual-line-mode)
483 (advice-add 'text-scale-adjust :after #'visual-fill-column-adjust)) 544 (advice-add 'text-scale-adjust :after #'visual-fill-column-adjust))
484 545
485(yoke (org "https://git.savannah.gnu.org/git/emacs/org-mode.git" 546(yoke (org "https://git.savannah.gnu.org/git/emacs/org-mode.git"
@@ -487,10 +548,10 @@ CAPES defaults to `+capes'. CAPF will be made un-exclusive."
487 :depends ((org-contrib "https://git.sr.ht/~bzg/org-contrib" 548 :depends ((org-contrib "https://git.sr.ht/~bzg/org-contrib"
488 :load "lisp")) 549 :load "lisp"))
489 ;; DON'T load system org 550 ;; DON'T load system org
490 (setq load-path 551 (setc load-path
491 (cl-remove-if (lambda (path) (string-match-p "lisp/org\\'" path)) 552 (cl-remove-if (lambda (path) (string-match-p "lisp/org\\'" path))
492 load-path)) 553 load-path))
493 (setq org-adapt-indentation nil 554 (setc org-adapt-indentation nil
494 org-auto-align-tags t 555 org-auto-align-tags t
495 org-archive-mark-done t 556 org-archive-mark-done t
496 org-fold-catch-invisible-edits 'show-and-error 557 org-fold-catch-invisible-edits 'show-and-error
@@ -549,25 +610,27 @@ CAPES defaults to `+capes'. CAPF will be made un-exclusive."
549 ("=" org-verbatim) 610 ("=" org-verbatim)
550 ("~" org-code) 611 ("~" org-code)
551 ("+" org-strikethrough))) 612 ("+" org-strikethrough)))
552 (add-hook* 'org-mode-hook 613 (defhook org-mode-hook
553 #'variable-pitch-mode 614 #'variable-pitch-mode
554 #'visual-fill-column-mode 615 #'visual-fill-column-mode
555 #'turn-off-auto-fill 616 #'turn-off-auto-fill
556 #'org-indent-mode 617 #'org-indent-mode
557 #'prettify-symbols-mode 618 #'prettify-symbols-mode
558 #'abbrev-mode) 619 #'abbrev-mode
559 (define-local-before-save-hook org-mode 620 (defhook ((before-save-hook nil :local))
560 (org-hide-drawer-all) 621 :name before-save@org-mode
561 (org-align-tags 'all)) 622 (+org-hide-drawers-except-point)
623 (org-align-tags 'all)))
562 (eval-after org 624 (eval-after org
563 (require '+org) 625 (require '+org)
564 (define-key* org-mode-map 626 (org-clock-persistence-insinuate)
627 (+org-agenda-inhibit-hooks-mode)
628 (defkeys org-mode-map
565 "C-M-k" #'kill-paragraph 629 "C-M-k" #'kill-paragraph
566 "C-M-t" #'transpose-paragraphs 630 "C-M-t" #'transpose-paragraphs
567 "RET" #'+org-return-dwim 631 "RET" #'+org-return-dwim
568 "S-<return>" #'+org-table-copy-down|+org-return 632 "S-<return>" #'+org-table-copy-down|+org-return
569 "C-c C-o" #'+org-open-at-point-dwim) 633 "C-c C-o" #'+org-open-at-point-dwim))
570 (org-clock-persistence-insinuate))
571 (eval-after ol ; org-link 634 (eval-after ol ; org-link
572 (defmacro define-org-link-type (type args &rest body) 635 (defmacro define-org-link-type (type args &rest body)
573 "Define an org link TYPE with ARGS that does something. 636 "Define an org link TYPE with ARGS that does something.
@@ -583,50 +646,49 @@ CAPES defaults to `+capes'. CAPF will be made un-exclusive."
583 (define-org-link-type sms (number _)) 646 (define-org-link-type sms (number _))
584 (define-org-link-type tel (number _)))) 647 (define-org-link-type tel (number _))))
585 648
586(yoke org-agenda nil 649(yoke org-word-count ; in lisp/
587 (setq org-agenda-skip-deadline-if-done t 650 (eval-after org
588 org-agenda-skip-scheduled-if-done t 651 (require 'org-word-count)
589 org-agenda-span 10 652 (add-hook 'org-mode-hook #'org-word-count-mode)))
590 org-agenda-block-separator ?─ 653
591 org-agenda-time-grid 654(yoke org-agenda
592 '((daily today require-timed) 655 (setq org-agenda-skip-deadline-if-done t
593 (800 1000 1200 1400 1600 1800 2000) 656 org-agenda-skip-scheduled-if-done t
594 " ┄┄┄┄┄ " "┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄") 657 org-agenda-span 10
595 org-agenda-current-time-string 658 org-agenda-block-separator ?─
596 "← now ─────────────────────────────────────────────────" 659 org-agenda-time-grid
597 org-agenda-include-diary nil ; I use the org-diary features 660 '((daily today require-timed)
598 org-agenda-todo-ignore-deadlines 'near 661 (800 1000 1200 1400 1600 1800 2000)
599 org-agenda-todo-ignore-scheduled 'future 662 " ┄┄┄┄┄ " "┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄")
600 org-agenda-include-deadlines t 663 org-agenda-current-time-string
601 org-deadline-warning-days 0 664 "← now ─────────────────────────────────────────────────"
602 org-agenda-show-future-repeats 'next 665 org-agenda-include-diary nil ; I use the org-diary features
603 org-agenda-window-setup 'current-window 666 org-agenda-todo-ignore-deadlines 'near
604 org-agenda-file-skip-regexp "sync-conflict") 667 org-agenda-todo-ignore-scheduled 'future
605 (defcustom org-agenda-file-skip-regexp nil 668 org-agenda-include-deadlines t
606 "Files matching this regexp are removed from `org-agenda-files'." 669 org-deadline-warning-days 0
607 :group 'org-agenda) 670 org-agenda-show-future-repeats 'next
608 (define-advice org-agenda-files (:filter-return (files) skip-regexp) 671 org-agenda-window-setup 'current-window
609 (when org-agenda-file-skip-regexp 672 org-agenda-file-skip-regexp "sync-conflict")
610 (setq files (seq-remove (lambda (file) 673 (defcustom org-agenda-file-skip-regexp nil
611 (string-match-p org-agenda-file-skip-regexp 674 "Files matching this regexp are removed from `org-agenda-files'."
612 file)) 675 :group 'org-agenda)
613 files))) 676 (define-advice org-agenda-files (:filter-return (files) skip-regexp)
614 files) 677 (when org-agenda-file-skip-regexp
615 (setq-local-hook org-agenda-mode-hook 678 (setq files (seq-remove (lambda (file)
616 truncate-lines t 679 (string-match-p org-agenda-file-skip-regexp
617 electric-pair-pairs (append electric-pair-pairs 680 file))
618 (mapcar (lambda (e) 681 files)))
619 (let ((ch (string-to-char (car e)))) 682 files)
620 (cons ch ch))) 683 (setq-local-hook org-agenda-mode-hook
621 org-emphasis-alist))) 684 truncate-lines t)
622 (add-hook* 'org-agenda-mode-hook 685 (add-hook 'org-agenda-mode-hook #'hl-line-mode)
623 #'hl-line-mode) 686 (add-hook 'org-agenda-after-show-hook #'org-narrow-to-subtree)
624 (add-hook 'org-agenda-after-show-hook #'org-narrow-to-subtree) 687 (defkeys t
625 (define-key* (current-global-map) 688 "C-c c" #'org-capture
626 "C-c c" #'org-capture 689 "C-c a" #'org-agenda)
627 "C-c a" #'org-agenda) 690 (eval-after org-capture
628 (eval-after org-capture 691 (require '+org-capture)))
629 '+org-capture))
630 692
631(yoke ox ; org-export 693(yoke ox ; org-export
632 (eval-after org (require 'ox)) 694 (eval-after org (require 'ox))
@@ -650,12 +712,13 @@ CAPES defaults to `+capes'. CAPF will be made un-exclusive."
650 :depends ((bbdb "https://git.savannah.nongnu.org/git/bbdb.git" 712 :depends ((bbdb "https://git.savannah.nongnu.org/git/bbdb.git"
651 :load "lisp") 713 :load "lisp")
652 (bbdb-vcard "https://github.com/tohojo/bbdb-vcard/")) 714 (bbdb-vcard "https://github.com/tohojo/bbdb-vcard/"))
653 (setf bbdb-complete-mail-allow-cycling t) 715 (setf bbdb-complete-mail-allow-cycling t
654 (add-hook* '+custom-after-load-hook 716 bbdb-file (private/ "bbdb"))
655 (defun _work@after-custom () 717 (defhook +custom-after-load-hook
656 (require* 'private '_work) 718 :name _work@after-custom
657 (require* 'bbdb 'bbdb-message) 719 (require* 'private '_work)
658 (bbdb-initialize 'gnus 'message)))) 720 (require* 'bbdb 'bbdb-message)
721 (bbdb-initialize 'gnus 'message)))
659 722
660(yoke (org-taskwise "https://codeberg.org/acdw/org-taskwise.el")) 723(yoke (org-taskwise "https://codeberg.org/acdw/org-taskwise.el"))
661 724
@@ -668,8 +731,8 @@ CAPES defaults to `+capes'. CAPF will be made un-exclusive."
668 map) 731 map)
669 "Keymap for scule twiddling.") 732 "Keymap for scule twiddling.")
670 (define-key* (current-global-map) 733 (define-key* (current-global-map)
671 "M-c" scule-map 734 "M-c" scule-map
672 "M-u" #'universal-argument) 735 "M-u" #'universal-argument)
673 (define-key universal-argument-map (kbd "M-u") #'universal-argument-more)) 736 (define-key universal-argument-map (kbd "M-u") #'universal-argument-more))
674 737
675(yoke (titlecase "https://codeberg.org/acdw/titlecase.el") 738(yoke (titlecase "https://codeberg.org/acdw/titlecase.el")
@@ -680,17 +743,17 @@ CAPES defaults to `+capes'. CAPF will be made un-exclusive."
680 word-boundary))) 743 word-boundary)))
681 (eval-after scule 744 (eval-after scule
682 (define-key* scule-map 745 (define-key* scule-map
683 "M-t" #'titlecase-dwim))) 746 "M-t" #'titlecase-dwim)))
684 747
685(yoke (flyspell-correct "https://github.com/duckwork/flyspell-correct") 748(yoke (flyspell-correct "https://github.com/duckwork/flyspell-correct")
686 (eval-after flyspell 749 (eval-after flyspell
687 (require* 'flyspell-correct 750 (require* 'flyspell-correct
688 `(+flyspell-correct ,(locate-user-emacs-file "lisp/+flyspell-correct"))) 751 `(+flyspell-correct ,(locate-user-emacs-file "lisp/+flyspell-correct")))
689 (define-key* flyspell-mode-map 752 (define-key* flyspell-mode-map
690 "C-;" #'flyspell-correct-wrapper 753 "C-;" #'flyspell-correct-wrapper
691 "<f7>" #'+flyspell-correct-buffer 754 "<f7>" #'+flyspell-correct-buffer
692 "C-," nil 755 "C-," nil
693 "C-." nil)) 756 "C-." nil))
694 (add-hook 'org-mode-hook #'flyspell-mode) 757 (add-hook 'org-mode-hook #'flyspell-mode)
695 (setq flyspell-correct--cr-key ";")) 758 (setq flyspell-correct--cr-key ";"))
696 759
@@ -699,51 +762,54 @@ CAPES defaults to `+capes'. CAPF will be made un-exclusive."
699 (f "https://github.com/rejeep/f.el") 762 (f "https://github.com/rejeep/f.el")
700 (s "https://github.com/magnars/s.el") 763 (s "https://github.com/magnars/s.el")
701 (elisp-refs "https://github.com/Wilfred/elisp-refs")) 764 (elisp-refs "https://github.com/Wilfred/elisp-refs"))
702 (define-key* (current-global-map) 765 (defkeys t
703 "<f1> f" #'helpful-callable 766 "<f1> f" #'helpful-callable
704 "<f1> v" #'helpful-variable 767 "<f1> v" #'helpful-variable
705 "<f1> k" #'helpful-key 768 "<f1> k" #'helpful-key
706 "<f1> ." #'helpful-at-point 769 "<f1> ." #'helpful-at-point
707 "<f1> o" #'helpful-symbol) 770 "<f1> o" #'helpful-symbol)
708 (unless (featurep 'info-look) 771 (unless (featurep 'info-look)
709 (run-with-idle-timer 1 nil (lambda () 772 (run-with-idle-timer 5 nil (lambda ()
710 (require 'info-look) 773 (require 'info-look)
711 (let ((inhibit-message t)) 774 (let ((inhibit-message t))
712 (info-lookup-setup-mode 'symbol 775 (info-lookup-setup-mode 'symbol
713 'emacs-lisp-mode))))) 776 'emacs-lisp-mode)))))
714 (setf (alist-get "\\*helpful" display-buffer-alist nil nil #'string=) 777 (defhook window-configuration-change-hook
715 '((display-buffer-in-side-window) 778 :name side-window-setup
716 (side . bottom) 779 (setf fit-window-to-buffer-horizontally t
717 (window-height . 20)))) 780 (alist-get (rx (or "*helpful" "*Help" "*info"))
781 display-buffer-alist nil nil #'string=)
782 `(display-buffer-in-side-window
783 ,@(if (< (frame-text-width) (frame-text-height))
784 '((side . bottom) (window-height . 24))
785 '((side . right) (window-width . fit-window-to-buffer)))))))
718 786
719(yoke (hippie-completing-read 787(yoke (hippie-completing-read
720 "https://codeberg.org/acdw/hippie-completing-read.el") 788 "https://codeberg.org/acdw/hippie-completing-read.el")
721 (define-key* (current-global-map) 789 (define-key* (current-global-map)
722 "M-/" #'hippie-completing-read)) 790 "M-/" #'hippie-completing-read))
723 791
724(yoke dictionary ; Comes with Emacs 29! 792(yoke dictionary ; Comes with Emacs 29!
725 (setq dictionary-server (if (or (executable-find "dictd") 793 (defkeys (t (org-mode-map :after org))
794 "C-c d" #'dictionary-search)
795 (defkeys ((embark-identifier-map :after embark))
796 "@" #'dictionary-search)
797 (setc dictionary-server (if (or (executable-find "dictd")
726 (file-exists-p "/usr/sbin/dictd")) ; oh debian 798 (file-exists-p "/usr/sbin/dictd")) ; oh debian
727 "localhost" 799 "localhost"
728 "dict.org")) 800 "dict.org"))
729 (setf (alist-get "^\\*Dictionary\\*" display-buffer-alist nil nil #'string=) 801 (setf (alist-get "^\\*Dictionary\\*" display-buffer-alist nil nil #'string=)
730 '((display-buffer-in-side-window) 802 '((display-buffer-in-side-window)
731 (side . bottom) 803 (side . bottom)
732 (window-height . 20))) 804 (window-height . 20))))
733 (eval-after org
734 (define-key* org-mode-map
735 "M-@" #'dictionary-search))
736 (eval-after embark
737 (define-key* embark-identifier-map
738 "@" #'dictionary-search)))
739 805
740(yoke (anzu "https://github.com/emacsorphanage/anzu") 806(yoke (anzu "https://github.com/emacsorphanage/anzu")
741 (require 'anzu) 807 (require 'anzu)
742 (global-anzu-mode) 808 (global-anzu-mode)
743 (define-key* (current-global-map) 809 (defkeys t
744 [remap query-replace] #'anzu-query-replace-regexp 810 [remap query-replace] #'anzu-query-replace-regexp
745 [remap query-replace-regexp] #'anzu-query-replace) 811 [remap query-replace-regexp] #'anzu-query-replace)
746 (define-key* isearch-mode-map 812 (defkeys (isearch-mode-map (isearch-mb-minibuffer-map :after isearch-mb))
747 [remap isearch-query-replace] #'anzu-isearch-query-replace-regexp 813 [remap isearch-query-replace] #'anzu-isearch-query-replace-regexp
748 [remap isearch-query-replace-regexp] #'anzu-isearch-query-replace) 814 [remap isearch-query-replace-regexp] #'anzu-isearch-query-replace)
749 (defun anzu-qr@window (fn &rest r) 815 (defun anzu-qr@window (fn &rest r)
@@ -768,10 +834,13 @@ CAPES defaults to `+capes'. CAPF will be made un-exclusive."
768 (funcall fn server uri)) 834 (funcall fn server uri))
769 (eval-after embark 835 (eval-after embark
770 (define-key* embark-region-map 836 (define-key* embark-region-map
771 "U" #'0x0-dwim))) 837 "U" #'0x0-dwim)))
772 838
773(yoke (filldent "https://codeberg.org/acdw/filldent.el") 839(yoke (filldent "https://codeberg.org/acdw/filldent.el")
774 (define-key* (current-global-map) 840 (define-advice canonically-space-region (:around (orig &rest r) double-space)
841 (let ((sentence-end-double-space t))
842 (apply orig r)))
843 (defkeys t
775 "M-q" #'filldent-unfill-toggle)) 844 "M-q" #'filldent-unfill-toggle))
776 845
777(yoke (avy "https://github.com/abo-abo/avy") 846(yoke (avy "https://github.com/abo-abo/avy")
@@ -787,9 +856,9 @@ CAPES defaults to `+capes'. CAPF will be made un-exclusive."
787 (cdr (ring-ref avy-ring 0)))) 856 (cdr (ring-ref avy-ring 0))))
788 t)) 857 t))
789 (define-key* (current-global-map) 858 (define-key* (current-global-map)
790 "M-j" #'avy-goto-char-timer) 859 "M-j" #'avy-goto-char-timer)
791 (define-key* isearch-mode-map 860 (define-key* isearch-mode-map
792 "M-j" #'avy-isearch)) 861 "M-j" #'avy-isearch))
793 862
794(yoke (frowny "https://codeberg.org/acdw/frowny.el") 863(yoke (frowny "https://codeberg.org/acdw/frowny.el")
795 (setf frowny-eyes (rx (any ":=") (opt "'") (? "-"))) 864 (setf frowny-eyes (rx (any ":=") (opt "'") (? "-")))
@@ -847,23 +916,29 @@ CAPES defaults to `+capes'. CAPF will be made un-exclusive."
847 (eval-after elisp-mode (require 'macrostep)) 916 (eval-after elisp-mode (require 'macrostep))
848 (define-key* '(emacs-lisp-mode-map 917 (define-key* '(emacs-lisp-mode-map
849 lisp-interaction-mode-map) 918 lisp-interaction-mode-map)
850 "C-c e" #'macrostep-expand)) 919 "C-c e" #'macrostep-expand))
920
921(yoke (expand-region "https://github.com/magnars/expand-region.el")
922 (define-advice er/clear-history (:after (&rest _) refold-org)
923 (when (derived-mode-p 'org-mode)
924 (+org-hide-drawers-except-point)
925 (org-link-descriptive-ensure)
926 (font-lock-update)))
927 (defkeys t
928 "C-=" #'er/expand-region))
851 929
852(yoke (embrace "https://github.com/cute-jumper/embrace.el") 930(yoke (embrace "https://github.com/cute-jumper/embrace.el")
853 :depends ((expand-region "https://github.com/magnars/expand-region.el")) 931 :depends ((expand-region "https://github.com/magnars/expand-region.el"))
854 (define-key* (current-global-map) 932 (defkeys t
855 "C-=" #'er/expand-region 933 "C-\"" #'embrace-commander)
856 "C-," #'embrace-commander)
857 (eval-after org
858 (define-key* org-mode-map
859 "C-=" #'er/expand-region
860 "C-," #'embrace-commander))
861 (dolist (fnhook '((org-mode-hook embrace-org-mode-hook) 934 (dolist (fnhook '((org-mode-hook embrace-org-mode-hook)
862 (ruby-mode-hook embrace-ruby-mode-hook) 935 (ruby-mode-hook embrace-ruby-mode-hook)
863 (emacs-lisp-mode-hook embrace-emacs-lisp-mode-hook) 936 (emacs-lisp-mode-hook embrace-emacs-lisp-mode-hook)
864 (latex-mode-hook embrace-LaTeX-mode-hook))) 937 (latex-mode-hook embrace-LaTeX-mode-hook)))
865 (apply #'add-hook fnhook)) 938 (apply #'add-hook fnhook))
866 (eval-after org 939 (eval-after org
940 (defkeys org-mode-map
941 "C-\"" #'embrace-commander)
867 (defmacro org-insert-or-embrace (char) 942 (defmacro org-insert-or-embrace (char)
868 "Define a function to insert CHAR, or `embrace' the region with it." 943 "Define a function to insert CHAR, or `embrace' the region with it."
869 (let* ((fn-name (intern (format "org-insert-or-embrace-%s" char))) 944 (let* ((fn-name (intern (format "org-insert-or-embrace-%s" char)))
@@ -880,12 +955,12 @@ CAPES defaults to `+capes'. CAPF will be made un-exclusive."
880 (forward-char 1)) 955 (forward-char 1))
881 (self-insert-command n ,char))))) 956 (self-insert-command n ,char)))))
882 (define-key* org-mode-map 957 (define-key* org-mode-map
883 "*" (org-insert-or-embrace "*") 958 "*" (org-insert-or-embrace "*")
884 "/" (org-insert-or-embrace "/") 959 "/" (org-insert-or-embrace "/")
885 "_" (org-insert-or-embrace "_") 960 "_" (org-insert-or-embrace "_")
886 "=" (org-insert-or-embrace "=") 961 "=" (org-insert-or-embrace "=")
887 "~" (org-insert-or-embrace "~") 962 "~" (org-insert-or-embrace "~")
888 "+" (org-insert-or-embrace "+")))) 963 "+" (org-insert-or-embrace "+"))))
889 964
890(yoke (notmuch "~/usr/share/emacs/site-lisp") 965(yoke (notmuch "~/usr/share/emacs/site-lisp")
891 (eval-after bbdb 966 (eval-after bbdb
@@ -897,10 +972,13 @@ CAPES defaults to `+capes'. CAPF will be made un-exclusive."
897 notmuch-address-use-company (featurep 'company) 972 notmuch-address-use-company (featurep 'company)
898 notmuch-search-oldest-first nil 973 notmuch-search-oldest-first nil
899 notmuch-archive-tags '("-inbox" "-unread") 974 notmuch-archive-tags '("-inbox" "-unread")
900 notmuch-draft-tags '("+draft" "-inbox" "-unread")) 975 notmuch-draft-tags '("+draft" "-inbox" "-unread")
976 mail-user-agent 'notmuch-user-agent
977 bbdb-mail-user-agent 'notmuch-user-agent
978 message-mail-user-agent t)
901 (define-key* (current-global-map) 979 (define-key* (current-global-map)
902 "C-c m" #'notmuch-mua-new-mail 980 "C-c m" #'notmuch-mua-new-mail
903 "C-c n" #'+notmuch-goto) 981 "C-c n" #'+notmuch-goto)
904 ;; Reading mail 982 ;; Reading mail
905 (setf notmuch-show-indent-content nil) 983 (setf notmuch-show-indent-content nil)
906 (add-hook* '(notmuch-show-mode-hook 984 (add-hook* '(notmuch-show-mode-hook
@@ -908,11 +986,15 @@ CAPES defaults to `+capes'. CAPF will be made un-exclusive."
908 #'visual-fill-column-mode) 986 #'visual-fill-column-mode)
909 (eval-after notmuch 987 (eval-after notmuch
910 (define-key* notmuch-search-mode-map 988 (define-key* notmuch-search-mode-map
911 "RET" #'notmuch-search-show-thread 989 "RET" #'notmuch-search-show-thread
912 "M-RET" #'notmuch-tree-from-search-thread 990 "M-RET" #'notmuch-tree-from-search-thread
913 "!" #'+notmuch-search-mark-spam) 991 "!" #'+notmuch-search-mark-spam)
914 (define-key* notmuch-tree-mode-map 992 (define-key* notmuch-tree-mode-map
915 "!" #'+notmuch-search-mark-spam-then-next)) 993 "!" #'+notmuch-search-mark-spam-then-next
994 "M-<" (notmuch-tree--define-do-in-message-window
995 notmuch-tree-beginning-of-message beginning-of-buffer)
996 "M->" (notmuch-tree--define-do-in-message-window
997 notmuch-tree-end-of-message end-of-buffer)))
916 ;; Writing mail 998 ;; Writing mail
917 (setf message-kill-buffer-on-exit t 999 (setf message-kill-buffer-on-exit t
918 message-auto-save-directory nil) 1000 message-auto-save-directory nil)
@@ -935,7 +1017,24 @@ CAPES defaults to `+capes'. CAPF will be made un-exclusive."
935 (advice-add 'notmuch-bury-or-kill-this-buffer :after 1017 (advice-add 'notmuch-bury-or-kill-this-buffer :after
936 (defun +display-time@notmuch (&rest _) 1018 (defun +display-time@notmuch (&rest _)
937 ;; (display-time-event-handler) 1019 ;; (display-time-event-handler)
938 (display-time-update))) 1020 (setq display-time-mail-string
1021 (replace-regexp-in-string "(.*)"
1022 (format "(%s)" (+notmuch-new-mail-p))
1023 display-time-mail-string))
1024 (display-time-update)
1025 (force-mode-line-update)))
1026 (add-to-list 'notmuch-message-headers "List-Post" :append)
1027 (define-advice notmuch-mua-new-reply (:around (orig &rest r) list-aware)
1028 "Make `notmuch-mua-new-reply' list-aware."
1029 (let ((ml (notmuch-show-get-header :List-Post)))
1030 (apply orig r)
1031 (when ml
1032 (with-buffer-modified-unmodified
1033 (message-remove-header "To")
1034 (message-add-header
1035 (format "To: %s"
1036 (replace-regexp-in-string "<mailto:\\(.*\\)>" "\\1" ml)))
1037 (message-goto-body)))))
939 (setf notmuch-saved-searches (list 1038 (setf notmuch-saved-searches (list
940 (list :name "inbox+unread" 1039 (list :name "inbox+unread"
941 :query (+notmuch-query-concat 1040 :query (+notmuch-query-concat
@@ -1012,8 +1111,8 @@ CAPES defaults to `+capes'. CAPF will be made un-exclusive."
1012 :depends ((frame-cmds "https://github.com/emacsmirror/frame-cmds") 1111 :depends ((frame-cmds "https://github.com/emacsmirror/frame-cmds")
1013 (frame-fns "https://github.com/emacsmirror/frame-fns")) 1112 (frame-fns "https://github.com/emacsmirror/frame-fns"))
1014 (define-key* (current-global-map) 1113 (define-key* (current-global-map)
1015 "M-+" #'zoom-frm-in 1114 "M-+" #'zoom-frm-in
1016 "M-_" #'zoom-frm-out)) 1115 "M-_" #'zoom-frm-out))
1017 1116
1018(yoke (jabber "https://codeberg.org/acdw/emacs-jabber") 1117(yoke (jabber "https://codeberg.org/acdw/emacs-jabber")
1019 :depends ((srv "https://github.com/legoscia/srv.el") 1118 :depends ((srv "https://github.com/legoscia/srv.el")
@@ -1045,21 +1144,23 @@ CAPES defaults to `+capes'. CAPF will be made un-exclusive."
1045 ;; (replace-regexp-in-string "%.*" "" s)) 1144 ;; (replace-regexp-in-string "%.*" "" s))
1046 ;; (:else s))))) 1145 ;; (:else s)))))
1047 ;; jids)) 1146 ;; jids))
1048 jabber-rare-time-format " - - - - - - %H:00 %F") 1147 jabber-rare-time-format " - - - - - - %H:%M %F")
1049 (defun +electric-pair-disable-local-mode () 1148 (defhook (jabber-chat-mode-hook
1050 (electric-pair-local-mode -1)) 1149 jabber-browse-mode-hook
1051 (add-hook* '(jabber-chat-mode-hook 1150 jabber-roster-mode-hook
1052 jabber-browse-mode-hook 1151 jabber-console-mode-hook)
1053 jabber-roster-mode-hook 1152 :name jabber-ui-setup
1054 jabber-console-mode-hook) 1153 (electric-pair-local-mode -1)
1055 #'visual-fill-column-mode 1154 (auto-fill-mode -1)
1056 #'+electric-pair-disable-local-mode) 1155 #'visual-fill-column-mode)
1156 (setq-local-hook jabber-chat-mode-hook
1157 wrap-prefix (format "%13s" " "))
1057 (defun +jabber-fix-keybinds-dammit () 1158 (defun +jabber-fix-keybinds-dammit ()
1058 "Jabber autoloads keybinds which is really annoying." 1159 "Jabber autoloads keybinds which is really annoying."
1059 (define-key* (current-global-map) 1160 (define-key* (current-global-map)
1060 "C-x C-j" #'dired-jump 1161 "C-x C-j" #'dired-jump
1061 "C-c j" jabber-global-keymap 1162 "C-c j" jabber-global-keymap
1062 "C-c C-SPC" #'jabber-activity-switch-to)) 1163 "C-c C-SPC" #'jabber-activity-switch-to))
1063 (eval-after init (+jabber-fix-keybinds-dammit)) 1164 (eval-after init (+jabber-fix-keybinds-dammit))
1064 (eval-after jabber 1165 (eval-after jabber
1065 (require 'jabber-httpupload nil :noerror) 1166 (require 'jabber-httpupload nil :noerror)
@@ -1076,25 +1177,25 @@ CAPES defaults to `+capes'. CAPF will be made un-exclusive."
1076 (hi-lock-unface-buffer regexp) 1177 (hi-lock-unface-buffer regexp)
1077 (highlight-regexp regexp 'hi-blue)))))) 1178 (highlight-regexp regexp 'hi-blue))))))
1078 (add-hook 'window-configuration-change-hook #'jabber-chat-update-focus) 1179 (add-hook 'window-configuration-change-hook #'jabber-chat-update-focus)
1079 (+jabber-fix-keybinds-dammit)) 1180 (+jabber-fix-keybinds-dammit)
1080 ;; (add-hook* 'jabber-activity-mode-hook 1181 (defkeys jabber-chat-mode-map
1081 ;; (defun +jabber-activity-mode@move-to-end-of-mode-line () 1182 "C-l" (defun +jabber-recenter-last-read ()
1082 ;; (setf global-mode-string 1183 (interactive)
1083 ;; (append (delete '(t jabber-activity-mode-string) 1184 (cond
1084 ;; global-mode-string) 1185 ((eq last-command '+jabber-recenter-last-read)
1085 ;; '((t jabber-activity-mode-string)))))) 1186 (setq this-command #'recenter)
1086 (setq-local-hook jabber-chat-mode-hook 1187 (recenter -1))
1087 wrap-prefix (format "%10s " " ") 1188 (:else
1088 mode-line-buffer-identification 1189 (save-excursion
1089 (pcase (buffer-name) 1190 (condition-case e
1090 ((rx "%") ; biboumi irc channel 1191 (re-search-backward jabber-last-read-marker)
1091 ;; xmpp-muc:#scheme%irc.libera.chat@irc.hmm.st 1192 (search-failed nil)
1092 (propertized-buffer-identification 1193 (:success
1093 (replace-regexp-in-string "xmpp-muc:\\([^%]*\\)%\\([^@]*\\)@.*" 1194 (recenter 3)))))))))
1094 "\\1@\\2" 1195 (defun jabber-chat-kill-buffers ()
1095 (buffer-name)))) 1196 "Kill all `jabber-chat-mode' buffers."
1096 (_ ; xmpp channel 1197 (interactive)
1097 (propertized-buffer-identification "%12b")))) 1198 (mapc-buffers (lambda () (message "%S" (buffer-name))) '(jabber-chat-mode)))
1098 (defun jabber-chat@after-modus-themes-load () 1199 (defun jabber-chat@after-modus-themes-load ()
1099 (modus-themes-with-colors 1200 (modus-themes-with-colors
1100 (custom-set-faces 1201 (custom-set-faces
@@ -1147,26 +1248,26 @@ CAPES defaults to `+capes'. CAPF will be made un-exclusive."
1147 link-hint-avy-all-windows t) 1248 link-hint-avy-all-windows t)
1148 (global-set-key (kbd "M-l") +link-hint-map) 1249 (global-set-key (kbd "M-l") +link-hint-map)
1149 (define-key* +link-hint-map 1250 (define-key* +link-hint-map
1150 "M-l" #'+link-hint-open-link "l" #'+link-hint-open-link 1251 "M-l" #'+link-hint-open-link "l" #'+link-hint-open-link
1151 "M-o" #'+link-hint-open-secondary "o" #'+link-hint-open-secondary 1252 "M-o" #'+link-hint-open-secondary "o" #'+link-hint-open-secondary
1152 "M-m" #'+link-hint-open-multiple-links "m" #'+link-hint-open-multiple-links 1253 "M-m" #'+link-hint-open-multiple-links "m" #'+link-hint-open-multiple-links
1153 "M-w" #'link-hint-copy-link "w" #'link-hint-copy-link 1254 "M-w" #'link-hint-copy-link "w" #'link-hint-copy-link
1154 "M-c" #'+link-hint-open-chrome "c" #'+link-hint-open-chrome)) 1255 "M-c" #'+link-hint-open-chrome "c" #'+link-hint-open-chrome))
1155 1256
1156(yoke (elpher "git://thelambdalab.xyz/elpher.git") 1257(yoke (elpher "git://thelambdalab.xyz/elpher.git")
1157 (eval-after elpher 1258 (eval-after elpher
1158 (define-key* elpher-mode-map 1259 (define-key* elpher-mode-map
1159 "l" #'elpher-back))) 1260 "l" #'elpher-back)))
1160 1261
1161(yoke (epithet "https://github.com/oantolin/epithet") 1262(yoke (epithet "https://github.com/oantolin/epithet")
1162 (add-hook* '(Info-selection-hook 1263 (defhook (Info-selection-hook
1163 help-mode-hook 1264 help-mode-hook
1164 occur-mode-hook 1265 occur-mode-hook
1165 shell-mode-hook) 1266 shell-mode-hook)
1166 #'epithet-rename-buffer) 1267 #'epithet-rename-buffer)
1167 (cond ((boundp 'eww-auto-rename-buffer) 1268 (cond ((boundp 'eww-auto-rename-buffer)
1168 (setf eww-auto-rename-buffer 'title)) 1269 (setc eww-auto-rename-buffer 'title))
1169 (:else (add-hook 'eww-after-render-hook #'epithet-rename-buffer)))) 1270 (:else (defhook eww-after-render-hook #'epithet-rename-buffer))))
1170 1271
1171(yoke browse-url 1272(yoke browse-url
1172 (require '+browse-url) 1273 (require '+browse-url)
@@ -1183,7 +1284,12 @@ CAPES defaults to `+capes'. CAPF will be made un-exclusive."
1183 (music-url-p . +browse-url-with-mpv) 1284 (music-url-p . +browse-url-with-mpv)
1184 (image-url-p . +browse-image-with-mpv) 1285 (image-url-p . +browse-image-with-mpv)
1185 (blobp . +browse-url-download) 1286 (blobp . +browse-url-download)
1186 (external-url-p . ,browse-url-secondary-browser-function))) 1287 (external-url-p . ,browse-url-secondary-browser-function)
1288 ;; HERE FOR REFERENCE --- OPEN MASTO URLS SOME WAY
1289 (,(defun mastodon-url-p (url)
1290 "Try to determine whether URL is a mastodon URL."
1291 (string-match-p "/@[^/]+\\(/\\|/[[:digit:]]+\\)?$" url))
1292 . ,browse-url-secondary-browser-function)))
1187 (+browse-url-make-external-viewer-handler "mpv" '("--cache-pause-wait=30" 1293 (+browse-url-make-external-viewer-handler "mpv" '("--cache-pause-wait=30"
1188 "--cache-pause-initial=yes") 1294 "--cache-pause-initial=yes")
1189 "Video URL: " 1295 "Video URL: "
@@ -1197,17 +1303,19 @@ CAPES defaults to `+capes'. CAPF will be made un-exclusive."
1197 url)) 1303 url))
1198 (defun music-url-p (url) "Is URL music?" 1304 (defun music-url-p (url) "Is URL music?"
1199 (string-match-p (rx "soundcloud.com" "bandcamp.com" 1305 (string-match-p (rx "soundcloud.com" "bandcamp.com"
1200 (seq "." (or "ogg" "mp3" "opus" "m4a") eos)) 1306 (seq "." (or "ogg" "mp3" "opus" "m4a" "flac") eos))
1201 url)) 1307 url))
1202 (defun image-url-p (url) "Is URL an image?" 1308 (defun image-url-p (url) "Is URL an image?"
1203 (string-match-p (rx "." (or "jpeg" "jpg" "png" "bmp" "webp") eos) 1309 (string-match-p (rx
1310 (or (: "." (or "jpeg" "jpg" "png" "bmp" "webp") eos)
1311 "pbs.twimg.com"))
1204 url)) 1312 url))
1205 (defun external-url-p (url) "Should URL open in an external browser?" 1313 (defun external-url-p (url) "Should URL open in an external browser?"
1206 (string-match-p (rx (or "github.com" "gitlab.com" "codeberg.org" 1314 (string-match-p (rx (or "github.com" "gitlab.com" "codeberg.org"
1207 "tildegit.org" "git.tilde.town" "google.com" 1315 "tildegit.org" "git.tilde.town" "google.com"
1208 "imgur.com" "twitch.tv" "pixelfed" "instagram.com" 1316 "imgur.com" "twitch.tv" "pixelfed" "instagram.com"
1209 "bibliogram.art" "reddit.com" "teddit.net" 1317 "bibliogram.art" "reddit.com" "teddit.net"
1210 "twitter.com" "nitter" "t.co" 1318 ;; "twitter.com" "nitter" "t.co"
1211 "streamable.com" "spotify.com" 1319 "streamable.com" "spotify.com"
1212 "hetzner.cloud" "melpa.org")) 1320 "hetzner.cloud" "melpa.org"))
1213 url)) 1321 url))
@@ -1216,38 +1324,74 @@ CAPES defaults to `+capes'. CAPF will be made un-exclusive."
1216 eos))) 1324 eos)))
1217 url)) 1325 url))
1218 (eval-after chd 1326 (eval-after chd
1219 (add-to-list 'browse-url-handlers (cons chd/url-regexps #'browse-url-chrome))) 1327 (add-to-list 'browse-url-handlers (cons chd/url-regexps #'chd/browse-url)))
1220 (require 'browse-url-transform) 1328 (require 'browse-url-transform)
1221 (setf browse-url-transform-alist `(("twitter\\.com" . "nitter.net") 1329 (setf browse-url-transform-alist `(;; Privacy-respecting alternatives
1330 ("twitter\\.com" . "nitter.snopyta.org")
1222 ("\\(?:\\(?:old\\.\\)?reddit\\.com\\)" 1331 ("\\(?:\\(?:old\\.\\)?reddit\\.com\\)"
1223 . "libreddit.de") 1332 . "libreddit.de")
1224 ("medium\\.com" . "scribe.rip") 1333 ("medium\\.com" . "scribe.rip")
1225 ("www\\.npr\\.org" . "text.npr.org"))) 1334 ;; Text-mode of non-text-mode sites
1335 ("www\\.npr\\.org" . "text.npr.org")
1336 ;; Ask for raw versions of paste sites
1337 ("^.*dpaste\\.com.*$" . "\\&.txt")
1338 ("bpa\\.st/\\(.*\\)" . "bpa.st/raw/\\1")
1339 ("\\(paste\\.debian\\.net\\)/\\(.*\\)"
1340 . "\\1/plain/\\2")
1341 ("\\(pastebin\\.com\\)/\\\(.*\\)"
1342 . "\\1/raw/\\2")
1343 ("gist\\.github\\.com/\\(.*\\)"
1344 . "gist.githubusercontent.com/\\1/raw/")))
1226 (browse-url-transform-mode)) 1345 (browse-url-transform-mode))
1227 1346
1228(yoke eww 1347(yoke eww
1229 (defun +eww-browse-with-external-browser (&optional url) 1348 (setc eww-use-browse-url ".")
1230 "Browse URL with an external browser and close eww." 1349 (eval-after eww
1231 (interactive nil eww-mode) 1350 (defhook eww-mode-hook
1232 (condition-case e 1351 #'visual-fill-column-mode
1233 ;; This is wrapped in a `condition-case' so that the eww window won't 1352 (defhook ((visual-fill-column-mode-hook nil :local))
1234 ;; close if there's an error calling the browser. 1353 :name eww-mode-refresh@visual-fill-column
1235 (funcall browse-url-secondary-browser-function 1354 (eww-reload t)))
1236 (or url (plist-get eww-data :url))) 1355 (defkeys eww-mode-map
1237 (:success 1356 "&"
1238 (when (null url) ; interactive 1357 (defun +eww-browse-with-external-browser (&optional url)
1239 (quit-window))) 1358 "Browse URL with an external browser and close eww."
1240 (t (signal (car e) (cdr e))))) 1359 (interactive nil eww-mode)
1241 (define-key* eww-mode-map 1360 (condition-case e
1242 "&" #'+eww-browse-with-external-browser)) 1361 ;; This is wrapped in a `condition-case' so that the eww window
1362 ;; won't close if there's an error calling the browser.
1363 (funcall browse-url-secondary-browser-function
1364 (or url (plist-get eww-data :url)))
1365 (:success
1366 (when (null url) ; interactive
1367 (quit-window)))
1368 (t (signal (car e) (cdr e)))))))
1369 (eval-after (eww link-hint)
1370 (defkeys eww-mode-map
1371 "f" #'+link-hint-open-link)))
1243 1372
1244(yoke tab-bar 1373(yoke tab-bar
1245 (setf tab-bar-show t 1374 (setf tab-bar-show t
1246 global-mode-string 1375 global-mode-string
1247 '((jabber-activity-mode jabber-activity-mode-string) 1376 '((jabber-activity-mode
1248 " ⋅" 1377 (:eval
1378 (let ((str (or (bound-and-true-p jabber-activity-mode-string)
1379 "")))
1380 (concat (truncate-string-to-width str 20 nil nil t)
1381 (if (< 0 (length str)) " ⋅" "")))))
1249 display-time-string 1382 display-time-string
1250 "|")) 1383 "|"))
1384 (eval-after jabber
1385 (defhook jabber-activity-mode-hook
1386 (setf global-mode-string
1387 '((jabber-activity-mode
1388 (:eval
1389 (let ((str (or (bound-and-true-p jabber-activity-mode-string)
1390 "")))
1391 (concat (truncate-string-to-width str 20 nil nil t)
1392 (if (< 0 (length str)) " ⋅" "")))))
1393 display-time-string
1394 "|"))))
1251 (add-to-list 'tab-bar-format 'tab-bar-format-align-right :append) 1395 (add-to-list 'tab-bar-format 'tab-bar-format-align-right :append)
1252 (add-to-list 'tab-bar-format 'tab-bar-format-global :append) 1396 (add-to-list 'tab-bar-format 'tab-bar-format-global :append)
1253 (tab-bar-mode)) 1397 (tab-bar-mode))
@@ -1257,3 +1401,27 @@ CAPES defaults to `+capes'. CAPF will be made un-exclusive."
1257 :depends ((tablist "https://github.com/politza/tablist/")) 1401 :depends ((tablist "https://github.com/politza/tablist/"))
1258 :when (executable-find "epdfinfo") ; installed from Debian repos 1402 :when (executable-find "epdfinfo") ; installed from Debian repos
1259 (pdf-tools-install)) 1403 (pdf-tools-install))
1404
1405(yoke which-function
1406 (setf (alist-get 'which-function-mode mode-line-misc-info)
1407 '((which-func-mode ; Only display if buffer supports it
1408 (:eval (when (which-function)
1409 (list "" which-func-format " "))))))
1410 (which-function-mode))
1411
1412(yoke (zzz-to-char "https://github.com/mrkkrp/zzz-to-char")
1413 :depends ((avy "https://github.com/abo-abo/avy"))
1414 (setf zzz-to-char-reach 120)
1415 (defkeys t
1416 [remap zap-to-char]
1417 (defun +zzz-to-char (&optional prefix)
1418 "Run `zzz-up-to-char', or `zzz-to-char' with PREFIX."
1419 (interactive "P")
1420 (call-interactively (cond (prefix #'zzz-to-char)
1421 (:else #'zzz-up-to-char))))))
1422
1423(yoke sh-mode
1424 (defhook sh-mode-hook
1425 :name turn-off-sh-electric-here-document-mode
1426 (sh-electric-here-document-mode -1)))
1427