init.el (18008B)
1 ;; -*- lexical-binding: t; -*- 2 (require 'seq) 3 (require 'xdg) 4 5 (package-initialize) 6 7 (push 8 (let ((lisp-path (expand-file-name "lisp" user-emacs-directory))) 9 (unless (file-exists-p lisp-path) 10 (make-directory lisp-path)) 11 lisp-path) 12 load-path) 13 14 (require 'lh) 15 (require 'lh-insert) 16 (require 'lh-resurrect) 17 (require 'iso-transl) 18 19 (with-eval-after-load 'paredit 20 (require 'paredit-menu)) 21 (with-eval-after-load 'restclient 22 (require 'restclient-capf)) 23 (with-eval-after-load 'elfeed 24 (require 'elfeed-tube) 25 (require 'elfeed-tube-mpv) 26 (elfeed-tube-setup)) 27 28 (setq org-roam-v2-ack t) 29 30 (setq lh/dir-documents 31 (expand-file-name 32 (cond ((eq system-type 'gnu/linux) (or (xdg-user-dir "DOCUMENTS") "~/Documents")) 33 ((eq system-type 'windows-nt) "~/Documents")))) 34 (setq lh/dir-data-home 35 (expand-file-name 36 (cond ((eq system-type 'gnu/linux) (or (xdg-data-home) "~/.local/share")) 37 ((eq system-type 'windows-nt) (getenv "APPDATA"))))) 38 39 (defadvice split-window-below (after lh/split-window-below activate) 40 (other-window 1)) 41 (defadvice split-window-right (after lh/split-window-right activate) 42 (other-window 1)) 43 (defadvice toggle-frame-fullscreen (before lh/toggle-frame-fullscreen-bars activate) 44 (menu-bar-mode (if menu-bar-mode -1 1)) 45 (tool-bar-mode (if tool-bar-mode -1 1)) 46 (scroll-bar-mode (if scroll-bar-mode -1 1))) 47 48 (defun lh/org-capture-skip-below-toplevel () 49 (when (> (org-current-level) 1) 50 (save-excursion (org-end-of-subtree t)))) 51 52 (defun lh/diff-file-changes () 53 (interactive) 54 (let ((file-name (make-temp-file "emacs-diff-")) 55 (original-file-name (buffer-file-name))) 56 (unwind-protect 57 (progn 58 (unwind-protect 59 (progn 60 (set-visited-file-name file-name) 61 (save-buffer)) 62 (set-visited-file-name original-file-name)) 63 (diff original-file-name file-name nil t)) 64 (delete-file file-name)))) 65 66 (defun lh/indent-region-inhibit-message (start end &optional column) 67 (interactive "r\nP") 68 (let ((inhibit-message t)) 69 (indent-region start end column))) 70 71 (defmacro lh/global-set-keys (keys-alist) 72 `(progn 73 ,@(seq-map 74 (lambda (x) 75 `(global-set-key (kbd ,(car x)) #',(cdr x))) 76 keys-alist))) 77 78 (defmacro lh/define-keys (keymap keys-alist &optional after) 79 (let ((defines (seq-map 80 (lambda (x) 81 `(define-key 82 ,keymap 83 ,(let ((key (car x))) 84 (cond 85 ((stringp key) `(kbd ,key)) 86 (t key))) 87 #',(cdr x))) 88 keys-alist))) 89 (if (null after) 90 (cons 'progn defines) 91 `(with-eval-after-load ',after 92 ,@defines)))) 93 94 (lh/global-set-keys 95 (("C-x C-M-t" . transpose-regions) 96 ("C-x K" . kill-this-buffer) 97 ("C-x C-b" . ibuffer) 98 99 ;;;; Consult bindings 100 ;; C-c bindings (mode-specific-map) 101 ("C-c h" . consult-history) 102 ("C-c m" . consult-mode-command) 103 ("C-c b" . consult-bookmark) 104 ("C-c k" . consult-kmacro) 105 ;; C-x bindings (ctl-x-map) 106 ("C-x M-:" . consult-complex-command) ;; orig. repeat-complex-command 107 ("C-x b" . consult-buffer) ;; orig. switch-to-buffer 108 ("C-x 4 b" . consult-buffer-other-window) ;; orig. switch-to-buffer-other-window 109 ("C-x 5 b" . consult-buffer-other-frame) ;; orig. switch-to-buffer-other-frame 110 ;; Custom M-# bindings for fast register access 111 ("M-#" . consult-register-load) 112 ("M-'" . consult-register-store) ;; orig. abbrev-prefix-mark (unrelated) 113 ("C-M-#" . consult-register) 114 ;; Other custom bindings' 115 ("<help> a" . consult-apropos) ;; orig. apropos-command 116 ;; M-g bindings (goto-map) 117 ("M-g e" . consult-compile-error) 118 ("M-g f" . consult-flymake) ;; Alternative: consult-flycheck 119 ("M-g g" . consult-goto-line) ;; orig. goto-line 120 ("M-g M-g" . consult-goto-line) ;; orig. goto-line 121 ("M-g o" . consult-outline) ;; Alternative: consult-org-heading 122 ("M-g m" . consult-mark) 123 ("M-g k" . consult-global-mark) 124 ("M-g i" . consult-imenu) 125 ("M-g I" . consult-imenu-multi) 126 ;; M-s bindings (search-map) 127 ("M-s f" . consult-find) 128 ("M-s L" . consult-locate) 129 ("M-s g" . consult-grep) 130 ("M-s G" . consult-git-grep) 131 ("M-s l" . consult-line) 132 ("M-s m" . consult-multi-occur) 133 ("M-s k" . consult-keep-lines) 134 ("M-s u" . consult-focus-lines) 135 ("M-s s" . consult-eglot-symbols) 136 ;; Isearch integration 137 ("M-s e" . consult-isearch) 138 139 ("C-." . embark-act) 140 ("M-." . embark-dwim) 141 142 ("C-+" . er/expand-region) 143 144 ("M-o" . ace-window) 145 146 ("C-c '" . imenu-list-smart-toggle) 147 148 ("C-c r l" . org-roam-buffer-toggle) 149 ("C-c r f" . org-roam-node-find) 150 ("C-c r i" . org-roam-node-insert) 151 152 ("C-h f" . helpful-callable) 153 ("C-h F" . helpful-function) 154 ("C-h C" . helpful-command) 155 ("C-h v" . helpful-variable) 156 ("C-h k" . helpful-key) 157 ("C-c C-d" . helpful-at-point) 158 159 ("C-S-p" . lh/move-line-up) 160 ("M-<up>" . lh/move-line-up) 161 ("C-S-n" . lh/move-line-down) 162 ("M-<down>" . lh/move-line-down) 163 164 ("M-s r" . deadgrep) 165 166 ("C-c p" . lh/pop-out-buffer) 167 ("C-c n" . lh/buffer-create-new) 168 ("C-c a" . org-agenda) 169 ("C-c c" . org-capture) 170 ("C-c l" . org-store-link) 171 172 ("C-c i j" . lh/insert-json-encoded) 173 ("C-c i i s" . lh/insert-random-sha1) 174 ("C-c i i u" . uuidgen) 175 ("C-c i r f" . lh/insert-number-from-register-format) 176 177 ("C-c e x" . lh/xml-escape-region) 178 179 ("<mouse-8>" . xref-go-back) 180 ("<mouse-9>" . xref-go-forward))) 181 182 (lh/define-keys icomplete-fido-mode-map 183 (("TAB" . icomplete-force-complete) 184 ("<left>" . left-char) 185 ("<right>" . right-char) 186 ("^" . icomplete-fido-backward-updir) 187 ("DEL" . backward-delete-char)) 188 icomplete) 189 (lh/define-keys isearch-mode-map 190 (("M-e" . consult-isearch) 191 ("M-s e" . consult-isearch) 192 ("M-s l" . consult-line))) 193 (lh/define-keys paredit-mode-map 194 (("M-s" . nil) 195 ("M-S" . paredit-splice-sexp)) 196 paredit) 197 (lh/define-keys elfeed-search-mode-map 198 (("G" . elfeed-update)) 199 elfeed) 200 (lh/define-keys json-mode-map 201 (("C-c C-j" . jq-interactively)) 202 json-mode) 203 (lh/define-keys sly-inspector-mode-map 204 (("<mouse-8>" . sly-inspector-pop) 205 ("<mouse-9>" . sly-inspector-next)) 206 sly) 207 208 (with-eval-after-load 'icomplete 209 (define-key icomplete-minibuffer-map (kbd "C-.") nil)) 210 211 (defun lh/elfeed-show-visit () 212 (interactive) 213 (let ((link (elfeed-entry-link elfeed-show-entry))) 214 (if (string-match-p (rx 215 line-start 216 "http" (opt "s") "://" 217 (opt "www.") 218 "youtube.com/") 219 link) 220 (elfeed-tube-mpv (point)) 221 (elfeed-show-visit)))) 222 223 (lh/define-keys elfeed-show-mode-map 224 (("b" . lh/elfeed-show-visit) 225 ("F" . elfeed-tube-fetch) 226 ([remap save-buffer] . elfeed-tube-save) 227 ("C-c C-f" . elfeed-tube-mpv-follow-mode) 228 ("C-c C-w" . elfeed-tube-mpv-where)) 229 elfeed) 230 (lh/define-keys elfeed-search-mode-map 231 (("F" . elfeed-tube-fetch) 232 ([remap save-buffer] . elfeed-tube-save)) 233 elfeed) 234 235 (defun corfu-insert-with-return () 236 (interactive) 237 (let ((idx corfu--index)) 238 (corfu-insert) 239 (when (< idx 0) 240 (funcall (key-binding (kbd "RET"))) 241 (indent-according-to-mode)))) 242 243 (lh/define-keys corfu-map 244 (("RET" . corfu-insert-with-return)) 245 corfu) 246 247 (defun lh/lisp-mode-hook () 248 (paredit-mode 1) 249 (prism-mode 1) 250 (highlight-function-calls-mode 1)) 251 252 (add-hook 'lisp-mode-hook 'lh/lisp-mode-hook) 253 (add-hook 'emacs-lisp-mode-hook 'lh/lisp-mode-hook) 254 ;; Aggressive Intent mode causes 100% CPU for me whenever the sly repl prints warnings 255 (add-hook 'sly-mrepl-mode-hook 256 (lambda () 257 (aggressive-indent-mode -1))) 258 (add-hook 'embark-collect-mode-hook 'consult-preview-at-point-mode) 259 (add-hook 'prog-mode-hook 260 (lambda () 261 (setq-local show-trailing-whitespace t))) 262 263 ;; notmuch's tag selection doesnt work with consult-completing-read-multiple 264 ;; items need to be trimmed 265 (defun lh/notmuch-read-tag-changes-trim (tags) 266 (seq-map (lambda (x) 267 (string-trim-right x)) 268 tags)) 269 270 (advice-add #'notmuch-read-tag-changes :filter-return #'lh/notmuch-read-tag-changes-trim) 271 272 ;; Fixes bug in minibuffer.el that causes consult to not work without any text 273 ;; https://github.com/minad/consult/issues/566 274 ;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=55205 275 (defun lh/advice-fix-minibuffer-consult (func &rest args) 276 (apply func (list (car args) 277 (cadr args) 278 (copy-sequence (caddr args))))) 279 280 (advice-add #'completion--replace :around #'lh/advice-fix-minibuffer-consult) 281 282 ;; file-name-all-completions seems to return file names in whatever order the 283 ;; filesystem feels like returning. This is super annoying with the flex 284 ;; completion style. If the FS returns "barfoo" before "foobar", flex completion 285 ;; will match "barfoo" first. This advice sorts the file name list. 286 (defun lh/advice-sort-file-name-all-completions (files) 287 (sort files #'string<)) 288 289 (advice-add 'file-name-all-completions :filter-return 'lh/advice-sort-file-name-all-completions) 290 291 (setq completion-ignore-case t) 292 293 (custom-set-variables 294 ;; custom-set-variables was added by Custom. 295 ;; If you edit it by hand, you could mess it up, so be careful. 296 ;; Your init file should contain only one such instance. 297 ;; If there is more than one, they won't work right. 298 '(aggressive-indent-region-function 'lh/indent-region-inhibit-message) 299 '(all-the-icons-completion-mode t) 300 '(auth-sources '(default)) 301 '(aw-dispatch-always t) 302 '(aw-keys '(97 115 100 102 103 104 106 107 108)) 303 '(aw-scope 'frame) 304 '(backup-by-copying t) 305 '(before-save-hook '(whitespace-cleanup)) 306 '(bookmark-completion-ignore-case nil) 307 '(calendar-christian-all-holidays-flag nil) 308 '(calendar-mark-holidays-flag t) 309 '(calendar-week-start-day 1) 310 '(column-number-mode t) 311 '(completion-ignore-case t t) 312 '(completion-styles '(basic substring initials)) 313 '(context-menu-mode t) 314 '(corfu-auto t) 315 '(corfu-auto-delay 0.0) 316 '(corfu-auto-prefix 1) 317 '(corfu-popupinfo-delay '(0 . 0)) 318 '(corfu-popupinfo-hide nil) 319 '(corfu-popupinfo-mode t) 320 '(corfu-preselect 'prompt) 321 '(corfu-quit-at-boundary t) 322 '(create-lockfiles nil) 323 '(cursor-type 'bar) 324 '(custom-enabled-themes '(modus-operandi)) 325 '(custom-safe-themes 326 '("1ea82e39d89b526e2266786886d1f0d3a3fa36c87480fad59d8fab3b03ef576e" "3d94d6d1a1c23113a60c8496c9aed094dbc2695f219e8127bb168d17b1e6dab3" "4b026ac68a1aa4d1a91879b64f54c2490b4ecad8b64de5b1865bca0addd053d9" "58264887d7ab17702ef85bbd96e11bd7f613622ff9c63990be860b958c978f09" "611ef0918b8b413badb8055089b5499c1d4ac20f1861efba8f3bfcb36ad0a448" "15604b083d03519b0c2ed7b32da6d7b2dc2f6630bef62608def60cdcf9216184" "88cb0f9c0c11dbb4c26a628d35eb9239d1cf580cfd28e332e654e7f58b4e721b" "69f7e8101867cfac410e88140f8c51b4433b93680901bb0b52014144366a08c8" "21e3d55141186651571241c2ba3c665979d1e886f53b2e52411e9e96659132d4" default)) 327 '(delete-old-versions t) 328 '(delete-selection-mode t) 329 '(denote-modules '(project xref ffap)) 330 '(denote-modules-global-mode t) 331 '(desktop-save-mode t) 332 '(dired-dwim-target 'dired-dwim-target-next) 333 '(dired-kill-when-opening-new-dired-buffer t) 334 '(dired-mode-hook '(all-the-icons-dired-mode)) 335 '(display-buffer-alist 336 '(("\\\\*sly-db for" 337 (display-buffer-reuse-window display-buffer-below-selected) 338 (dedicated . t) 339 (window-height . 0.3)) 340 ("\\\\*Async Shell Command\\\\*" display-buffer-no-window))) 341 '(ediff-split-window-function 'split-window-horizontally) 342 '(ediff-window-setup-function 'ediff-setup-windows-plain) 343 '(editorconfig-mode t) 344 '(elfeed-tube-auto-save-p t) 345 '(fido-mode t) 346 '(fido-vertical-mode t) 347 '(focus-follows-mouse t) 348 '(frame-resize-pixelwise t) 349 '(global-aggressive-indent-mode t) 350 '(global-auto-revert-mode t) 351 '(global-corfu-mode t) 352 '(global-diff-hl-mode t) 353 '(help-window-select t) 354 '(ibuffer-mode-hook '(all-the-icons-ibuffer-mode)) 355 '(ignored-local-variable-values '((sly-load-failed-fasl . ask))) 356 '(indent-tabs-mode nil) 357 '(inferior-lisp-program "sbcl") 358 '(kept-new-versions 10) 359 '(kept-old-versions 5) 360 '(lh/global-resurrect-mode t) 361 '(marginalia-mode t) 362 '(mouse-autoselect-window 0.2) 363 '(mouse-wheel-progressive-speed nil) 364 '(mouse-wheel-scroll-amount '(5 ((shift) . hscroll) ((meta)) ((control) . text-scale))) 365 '(notmuch-archive-tags '("-inbox" "-unread")) 366 '(org-agenda-custom-commands 367 '(("n" "Agenda and all TODOs" 368 ((agenda "" nil) 369 (alltodo "" nil)) 370 nil) 371 ("g" "GTD View" 372 ((agenda "" nil) 373 (tags-todo "+aktion+TODO=\"NEXT\"" 374 ((org-agenda-overriding-header "Nächste Aktionen:"))) 375 (tags "projekt" 376 ((org-agenda-overriding-header "Projekte:") 377 (org-agenda-skip-function 'lh/org-capture-skip-below-toplevel))) 378 (tags-todo "WAITING" 379 ((org-agenda-overriding-header "Warten auf:")))) 380 nil nil))) 381 '(org-agenda-loop-over-headlines-in-active-region nil) 382 '(org-babel-load-languages '((awk . t) (lisp . t) (shell . t) (emacs-lisp . t))) 383 '(org-html-validation-link "") 384 '(org-log-done 'time) 385 '(org-log-done-with-time t) 386 '(org-refile-use-outline-path 'file) 387 '(org-src-window-setup 'other-window) 388 '(org-startup-folded t) 389 '(org-startup-indented t) 390 '(org-startup-truncated nil) 391 '(package-archive-priorities 392 '(("gnu" . 3) 393 ("nongnu" . 2) 394 ("melpa-stable" . 1) 395 ("melpa" . 0))) 396 '(package-archives 397 '(("gnu" . "https://elpa.gnu.org/packages/") 398 ("nongnu" . "https://elpa.nongnu.org/nongnu/") 399 ("melpa-stable" . "https://stable.melpa.org/packages/") 400 ("melpa" . "https://melpa.org/packages/"))) 401 '(package-pinned-packages '((sly . "melpa"))) 402 '(package-selected-packages 403 '(highlight-function-calls prism modus-themes imenu-list diff-hl embark-consult embark all-the-icons-completion all-the-icons-ibuffer all-the-icons-dired sly-named-readtables sly-macrostep denote-refs denote-menu denote ox-epub ob-powershell powershell web-mode lexic editorconfig elfeed-tube-mpv elfeed-tube restclient-jq graphviz-dot-mode consult-eglot jq-mode ob-restclient restclient deadgrep helpful pdf-tools paredit-menu paredit corfu sly eglot aggressive-indent project nov nhexl-mode elfeed magit yaml-mode json-mode lua-mode go-mode org-contrib org ace-window expand-region consult marginalia uuidgen diminish which-key)) 404 '(pcomplete-ignore-case t t) 405 '(pixel-scroll-precision-mode t) 406 '(prism-parens t) 407 '(read-buffer-completion-ignore-case t) 408 '(read-file-name-completion-ignore-case t) 409 '(reb-re-syntax 'string) 410 '(recentf-max-saved-items 200) 411 '(recentf-mode t) 412 '(repeat-mode t) 413 '(ring-bell-function 'ignore) 414 '(save-place-mode t) 415 '(savehist-mode t) 416 '(scroll-conservatively 100) 417 '(show-trailing-whitespace t) 418 '(tab-always-indent 'complete) 419 '(use-short-answers t) 420 '(warning-suppress-types '((comp))) 421 '(which-key-mode t)) 422 (custom-set-faces 423 ;; custom-set-faces was added by Custom. 424 ;; If you edit it by hand, you could mess it up, so be careful. 425 ;; Your init file should contain only one such instance. 426 ;; If there is more than one, they won't work right. 427 '(default ((t (:family "Go Mono")))) 428 '(variable-pitch ((t (:family "IBM Plex Serif"))))) 429 430 ;; This is the place where I override all customize stuff 431 432 (with-eval-after-load 'prism 433 (prism-set-colors 434 :desaturations '(0) 435 :lightens '(0) 436 :colors (modus-themes-with-colors 437 (list fg-main 438 magenta 439 cyan-cooler 440 magenta-cooler 441 blue 442 magenta-warmer 443 cyan-warmer 444 red-cooler 445 green 446 fg-main 447 cyan 448 yellow 449 blue-warmer 450 red-warmer 451 green-cooler 452 yellow-faint)))) 453 454 (let ((feeds (expand-file-name "feeds.el" user-emacs-directory))) 455 (when (file-exists-p feeds) 456 (load feeds))) 457 458 (customize-set-value 459 'elfeed-db-directory 460 (let ((data-dir (expand-file-name "elfeed" lh/dir-data-home))) 461 (unless (file-exists-p data-dir) 462 (make-directory data-dir)) 463 data-dir)) 464 465 (customize-set-value 466 'backup-directory-alist 467 (let ((backup-dir (concat user-emacs-directory "backup"))) 468 (unless (file-exists-p backup-dir) 469 (make-directory backup-dir t)) 470 `(("." . ,backup-dir)))) 471 472 (let* ((dir (expand-file-name "org" lh/dir-documents)) 473 (roam-dir (expand-file-name "notes" dir))) 474 (unless (file-exists-p dir) 475 (make-directory dir t)) 476 (unless (file-exists-p roam-dir) 477 (make-directory roam-dir t)) 478 (customize-set-value 479 'org-directory 480 dir) 481 (customize-set-value 482 'org-agenda-files 483 (list dir)) 484 (customize-set-value 485 'org-roam-directory 486 roam-dir) 487 (with-eval-after-load "org" 488 (setq org-capture-templates 489 `(("g" "GTD Inbox" entry 490 (file ,(expand-file-name "inbox.org" dir)) 491 "* %?"))))) 492 493 (customize-set-value 494 'dired-guess-shell-alist-user 495 (cond 496 ((eq system-type 'gnu/linux) 497 `((,(rx "." (or "png" "jpg" (seq "jp" (? "e") "g"))) "pqiv") 498 (,(rx "." (or "mkv" "mp4" "webm" "ogv" "avi")) "mpv") 499 (,(rx "." (or "flac" "ogg" "mp3" "wav")) "mpv --force-window"))) 500 (t nil))) 501 502 (diminish 'which-key-mode) 503 (diminish 'aggressive-indent-mode) 504 (diminish 'editorconfig-mode) 505 506 (let ((path (expand-file-name "private.el" user-emacs-directory))) 507 (when (file-exists-p path) 508 (load path))) 509 510 (pdf-loader-install) 511 512 (server-start) 513 (put 'narrow-to-region 'disabled nil)