summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--basics.el315
-rw-r--r--early-init.el15
-rw-r--r--init.el451
-rw-r--r--lisp/acdw.el39
4 files changed, 768 insertions, 52 deletions
diff --git a/basics.el b/basics.el index 06f5ece..4e9e0a9 100644 --- a/basics.el +++ b/basics.el
@@ -8,41 +8,15 @@
8 8
9;;; Code: 9;;; Code:
10 10
11;;; Directories 11(push (locate-user-emacs-file "lisp/") load-path)
12(require 'acdw)
12 13
13(defmacro defdir (name directory &optional docstring makedir) 14;;; Directories
14 "Define a variable and a function NAME expanding to DIRECTORY.
15DOCSTRING is applied to the variable; its default is DIRECTORY's
16path. If MAKEDIR is non-nil, the directory and its parents will
17be created."
18 (declare (indent 2) (doc-string 3))
19 `(progn
20 (defvar ,name (expand-file-name ,directory)
21 ,(concat (or docstring (format "%s" directory)) "\n"
22 "Defined by `defdir'."))
23 (defun ,name (file &optional mkdir)
24 ,(concat "Expand FILE relative to variable `" (symbol-name name) "'.\n"
25 "If MKDIR is non-nil, parent directories are created.\n"
26 "Defined by `defdir'.")
27 (let ((file-name (expand-file-name
28 (convert-standard-filename file) ,name)))
29 (when mkdir
30 (make-directory (file-name-directory file-name) :parents))
31 file-name))
32 ,(if makedir
33 `(make-directory ,directory :parents)
34 `(unless (file-exists-p ,directory)
35 (warn "Directory `%s' doesn't exist." ,directory)))))
36 15
37(defdir etc/ (locate-user-emacs-file "etc/") 16(defdir etc/ (locate-user-emacs-file "etc/")
38 "Where various Emacs files are placed." 17 "Where various Emacs files are placed."
39 :makedir) 18 :makedir)
40 19
41(defdir lisp/ (locate-user-emacs-file "lisp/")
42 "My bespoke elisp files."
43 :makedir)
44(push lisp/ load-path)
45
46(defdir sync/ "~/Sync/" 20(defdir sync/ "~/Sync/"
47 "My Syncthing directory." 21 "My Syncthing directory."
48 :makedir) 22 :makedir)
@@ -50,7 +24,6 @@ be created."
50(defdir private/ (sync/ "emacs/private/") 24(defdir private/ (sync/ "emacs/private/")
51 "Private files and stuff." 25 "Private files and stuff."
52 :makedir) 26 :makedir)
53(push private/ load-path)
54 27
55(use-package no-littering 28(use-package no-littering
56 :ensure t :demand t 29 :ensure t :demand t
@@ -114,6 +87,15 @@ be created."
114(file-name-shadow-mode) 87(file-name-shadow-mode)
115(minibuffer-electric-default-mode) 88(minibuffer-electric-default-mode)
116 89
90(define-minor-mode truncate-lines-local-mode
91 "Truncate lines locally in a buffer."
92 :lighter " ..."
93 :group 'display
94 (setq-local truncate-lines truncate-lines-local-mode))
95
96(add-hook 'minibuffer-setup-hook #'truncate-lines-local-mode)
97
98
117(require 'savehist) 99(require 'savehist)
118(setq-default history-length 1024 100(setq-default history-length 1024
119 history-delete-duplicates t 101 history-delete-duplicates t
@@ -122,13 +104,16 @@ be created."
122 savehist-autosave-interval 30) 104 savehist-autosave-interval 30)
123(savehist-mode) 105(savehist-mode)
124 106
125;; Undo
126(setq-default undo-limit (* 10 1024 1024))
127
128;; Killing and yanking 107;; Killing and yanking
129(setq-default kill-do-not-save-duplicates t 108(setq-default kill-do-not-save-duplicates t
130 kill-read-only-ok t 109 kill-read-only-ok t
131 save-interprogram-paste-before-kill t 110 ;; XXX: This setting causes an error message the first time it's
111 ;; called: "Selection owner couldn't convert: TIMESTAMP". I have
112 ;; absolutely no idea why I get this error, but it's generated in
113 ;; `x_get_foreign_selection'. I also can't inhibit the message or
114 ;; do anything else with it, so for now, I'll just live with the
115 ;; message.
116 save-interprogram-paste-before-kill t
132 yank-pop-change-selection t) 117 yank-pop-change-selection t)
133(delete-selection-mode) 118(delete-selection-mode)
134 119
@@ -147,14 +132,20 @@ be created."
147 initial-buffer-choice t 132 initial-buffer-choice t
148 initial-scratch-message nil) 133 initial-scratch-message nil)
149 134
150;; (menu-bar-mode -1) 135(define-advice startup-echo-area-message (:override ())
136 (if (get-buffer "*Warnings*")
137 ";_;"
138 "^_^"))
139
140(menu-bar-mode -1)
151(tool-bar-mode -1) 141(tool-bar-mode -1)
152(tooltip-mode -1) 142(tooltip-mode -1)
153 143
154;; Text editing 144;; Text editing
155(setq-default fill-column 80 145(setq-default fill-column 80
156 sentence-end-double-space t 146 sentence-end-double-space t
157 tab-width 8) 147 tab-width 8
148 tab-always-indent 'complete)
158(global-so-long-mode) 149(global-so-long-mode)
159 150
160(setq-default show-paren-delay 0.01 151(setq-default show-paren-delay 0.01
@@ -202,7 +193,8 @@ be created."
202 auto-save-interval 1 193 auto-save-interval 1
203 auto-save-no-message t 194 auto-save-no-message t
204 auto-save-timeout 1 195 auto-save-timeout 1
205 auto-save-visited-interval 1) 196 auto-save-visited-interval 1
197 remote-file-name-inhibit-auto-save-visited t)
206(add-to-list 'auto-save-file-name-transforms 198(add-to-list 'auto-save-file-name-transforms
207 `(".*" ,(etc/ "auto-save/" t) t)) 199 `(".*" ,(etc/ "auto-save/" t) t))
208(auto-save-visited-mode) 200(auto-save-visited-mode)
@@ -215,9 +207,9 @@ be created."
215 207
216(require 'recentf) 208(require 'recentf)
217(setq-default ;; recentf-save-file (etc/ "recentf" t) 209(setq-default ;; recentf-save-file (etc/ "recentf" t)
218 recentf-max-menu-items 500 210 recentf-max-menu-items 500
219 recentf-max-saved-items nil ; Save the whole list 211 recentf-max-saved-items nil ; Save the whole list
220 recentf-auto-cleanup 'mode) 212 recentf-auto-cleanup 'mode)
221(add-to-list 'recentf-exclude etc/) 213(add-to-list 'recentf-exclude etc/)
222(add-to-list 'recentf-exclude "-autoloads.el\\'") 214(add-to-list 'recentf-exclude "-autoloads.el\\'")
223(add-hook 'buffer-list-update-hook #'recentf-track-opened-file) 215(add-hook 'buffer-list-update-hook #'recentf-track-opened-file)
@@ -225,8 +217,8 @@ be created."
225 217
226(require 'saveplace) 218(require 'saveplace)
227(setq-default ;; save-place-file (etc/ "places.el") 219(setq-default ;; save-place-file (etc/ "places.el")
228 save-place-forget-unreadable-files (eq system-type 220 save-place-forget-unreadable-files (eq system-type
229 'gnu/linux)) 221 'gnu/linux))
230(save-place-mode) 222(save-place-mode)
231 223
232(require 'uniquify) 224(require 'uniquify)
@@ -247,10 +239,12 @@ be created."
247 (startup-redirect-eln-cache native-compile-target-directory)) 239 (startup-redirect-eln-cache native-compile-target-directory))
248 240
249;; Custom file 241;; Custom file
250(setq-default custom-file (sync/ "emacs/custom.el")) 242(setq-default custom-file (private/ "custom.el"))
251(define-advice package--save-selected-packages (:around (orig &rest args) no-custom) 243(define-advice package--save-selected-packages
244 (:around (orig &rest args) no-custom)
252 "Don't save `package-selected-packages' to `custom-file'." 245 "Don't save `package-selected-packages' to `custom-file'."
253 (let ((custom-file null-device)) 246 (let ((custom-file (expand-file-name "custom.el"
247 temporary-file-directory)))
254 (apply orig args))) 248 (apply orig args)))
255 249
256;; Goto Address 250;; Goto Address
@@ -293,22 +287,56 @@ N spaces."
293(global-set-key (kbd "C-x 0") #'delete-window|bury-buffer) 287(global-set-key (kbd "C-x 0") #'delete-window|bury-buffer)
294(global-set-key (kbd "M-SPC") #'+cycle-spacing) 288(global-set-key (kbd "M-SPC") #'+cycle-spacing)
295(global-set-key (kbd "C-x C-k") #'kill-this-buffer) 289(global-set-key (kbd "C-x C-k") #'kill-this-buffer)
290(global-set-key (kbd "C-/") #'undo-only)
291(global-set-key (kbd "C-?") #'undo-redo)
292
293(define-key emacs-lisp-mode-map (kbd "C-c C-c")
294 #'eval-defun)
295(define-key emacs-lisp-mode-map (kbd "C-c C-k")
296 #'elisp-eval-region-or-buffer)
297(define-key lisp-interaction-mode-map (kbd "C-c C-c")
298 #'eval-defun)
299(define-key lisp-interaction-mode-map (kbd "C-c C-k")
300 #'elisp-eval-region-or-buffer)
301(define-advice eval-region (:around (orig start end &rest args) pulse)
302 (apply orig start end args)
303 (pulse-momentary-highlight-region start end))
304
305(global-set-key (kbd "C-x C-b") #'ibuffer)
296 306
297;;; Hooks 307;;; Hooks
298 308
299(add-hook 'after-save-hook #'executable-make-buffer-file-executable-if-script-p) 309(add-hook 'after-save-hook #'executable-make-buffer-file-executable-if-script-p)
310
300(add-hook 'find-file-not-found-functions 311(add-hook 'find-file-not-found-functions
301 (defun create-missing-directories () 312 (defun create-missing-directories ()
302 "Automatically create missing directories." 313 "Automatically create missing directories."
303 (let ((target-dir (file-name-directory buffer-file-name))) 314 (let ((target-dir (file-name-directory buffer-file-name)))
304 (unless (file-exists-p target-dir) 315 (unless (file-exists-p target-dir)
305 (make-directory target-dir :parents))))) 316 (make-directory target-dir :parents)))))
317
306(add-hook 'find-file-hook 318(add-hook 'find-file-hook
307 (defun vc-remote-off () 319 (defun vc-remote-off ()
308 "Turn VC off when remote." 320 "Turn VC off when remote."
309 (when (file-remote-p (buffer-file-name)) 321 (when (file-remote-p (buffer-file-name))
310 (setq-local vc-handled-backends nil)))) 322 (setq-local vc-handled-backends nil))))
311 323
324(add-hook 'after-init-hook
325 (defun after-init@emoji-font-setup ()
326 "Set up emoji fonts after init."
327 (run-with-idle-timer
328 1 nil (defun emoji-font-setup ()
329 "Set up emoji fonts."
330 (let ((ffl (font-family-list)))
331 (dolist (font '("Noto Emoji" "Noto Color Emoji"
332 "Segoe UI Emoji" "Apple Color Emoji"
333 "FreeSans" "FreeMono" "FreeSerif"
334 "Unifont" "Symbola"))
335 (when (member font (font-family-list))
336 (set-fontset-font t 'symbol
337 (font-spec :family font)
338 nil :add))))))))
339
312;;; Advice 340;;; Advice
313 341
314(define-advice switch-to-buffer (:after (&rest _) normal-mode) 342(define-advice switch-to-buffer (:after (&rest _) normal-mode)
@@ -373,4 +401,201 @@ See also `with-region-or-to-eol'."
373(use-package _acdw 401(use-package _acdw
374 :load-path private/) 402 :load-path private/)
375 403
404(use-package custom-allowed
405 :load-path "/home/case/src/emacs/custom-allowed/"
406 :config
407 (add-to-list 'custom-allowed-variables 'safe-local-variable-values)
408 (add-to-list 'custom-allowed-variables 'ispell-buffer-session-localwords)
409 (add-to-list 'custom-allowed-variables 'warning-suppress-types)
410 (add-to-list 'custom-allowed-variables 'calendar-latitude)
411 (add-to-list 'custom-allowed-variables 'calendar-longitude)
412 (add-to-list 'custom-allowed-variables 'user-full-name)
413 (add-to-list 'custom-allowed-variables 'user-mail-address)
414 :hook
415 (after-init-hook . custom-allowed-load-custom-file))
416
417(use-package sophomore
418 :load-path "/home/case/src/emacs/sophomore/"
419 :config
420 (sophomore-enable-all)
421 (sophomore-disable 'view-hello-file
422 'describe-gnu-project
423 'suspend-frame)
424 (sophomore-mode))
425
426(use-package compat
427 ;; This shouldn't be necessary, but sadly I believe that it is.
428 :ensure t)
429
430(use-package vertico
431 :ensure t :demand t
432 :config
433 (setq vertico-cycle t)
434 (vertico-mode))
435
436(use-package vertico-directory
437 :after vertico
438 :bind (:map vertico-map
439 ("RET" . vertico-directory-enter)
440 ("DEL" . vertico-directory-delete-char)
441 ("M-DEL" . vertico-directory-delete-word))
442 :hook (rfn-shadow-update-overlay-hook . vertico-directory-tidy))
443
444(use-package vertico-mouse
445 :after vertico
446 :config (vertico-mouse-mode))
447
448;; Example configuration for Consult
449(use-package consult
450 :ensure t
451 ;; Replace bindings. Lazily loaded due by `use-package'.
452 :bind (;; C-c bindings (mode-specific-map)
453 ("C-c h" . consult-history)
454 ("C-c m" . consult-mode-command)
455 ("C-c k" . consult-kmacro)
456 ;; C-x bindings (ctl-x-map)
457 ("C-x M-:" . consult-complex-command)
458 ("C-x b" . consult-buffer)
459 ("C-x 4 b" . consult-buffer-other-window)
460 ("C-x 5 b" . consult-buffer-other-frame)
461 ("C-x r b" . consult-bookmark)
462 ("C-x p b" . consult-project-buffer)
463 ;; Custom M-# bindings for fast register access
464 ("M-#" . consult-register-load)
465 ("M-'" . consult-register-store)
466 ("C-M-#" . consult-register)
467 ;; Other custom bindings
468 ("M-y" . consult-yank-pop)
469 ;; M-g bindings (goto-map)
470 ("M-g e" . consult-compile-error)
471 ("M-g f" . consult-flymake)
472 ("M-g g" . consult-goto-line)
473 ("M-g M-g" . consult-goto-line)
474 ("M-g o" . consult-outline)
475 ("M-g m" . consult-mark)
476 ("M-g k" . consult-global-mark)
477 ("M-g i" . consult-imenu)
478 ("M-g I" . consult-imenu-multi)
479 ;; M-s bindings (search-map)
480 ("M-s d" . consult-find)
481 ("M-s D" . consult-locate)
482 ("M-s g" . consult-grep)
483 ("M-s G" . consult-git-grep)
484 ("M-s r" . consult-ripgrep)
485 ("M-s l" . consult-line)
486 ("M-s L" . consult-line-multi)
487 ("M-s k" . consult-keep-lines)
488 ("M-s u" . consult-focus-lines)
489 ;; Isearch integration
490 ("M-s e" . consult-isearch-history)
491 :map isearch-mode-map
492 ("M-e" . consult-isearch-history)
493 ("M-s e" . consult-isearch-history)
494 ("M-s l" . consult-line)
495 ("M-s L" . consult-line-multi)
496 ;; Minibuffer history
497 :map minibuffer-local-map
498 ("M-s" . consult-history)
499 ("M-r" . consult-history))
500
501 ;; Enable automatic preview at point in the *Completions* buffer. This is
502 ;; relevant when you use the default completion UI.
503 :hook (completion-list-mode . consult-preview-at-point-mode)
504
505 ;; The :init configuration is always executed (Not lazy)
506 :init
507
508 ;; Optionally configure the register formatting. This improves the register
509 ;; preview for `consult-register', `consult-register-load',
510 ;; `consult-register-store' and the Emacs built-ins.
511 (setq register-preview-delay 0.5
512 register-preview-function #'consult-register-format)
513
514 ;; Optionally tweak the register preview window.
515 ;; This adds thin lines, sorting and hides the mode line of the window.
516 (advice-add #'register-preview :override #'consult-register-window)
517
518 (define-advice completing-read-multiple (:filter-args (args) indicator)
519 (cons (format "[CRM%s] %s"
520 (replace-regexp-in-string
521 "\\`\\[.*?]\\*\\|\\[.*?]\\*\\'" ""
522 crm-separator)
523 (car args))
524 (cdr args)))
525
526 ;; Use Consult to select xref locations with preview
527 (setq xref-show-xrefs-function #'consult-xref
528 xref-show-definitions-function #'consult-xref)
529
530 (setq completion-in-region-function #'consult-completion-in-region)
531
532 ;; Configure other variables and modes in the :config section,
533 ;; after lazily loading the package.
534 :config
535
536 ;; Optionally configure preview. The default value
537 ;; is 'any, such that any key triggers the preview.
538 ;; (setq consult-preview-key 'any)
539 ;; (setq consult-preview-key (kbd "M-."))
540 ;; (setq consult-preview-key (list (kbd "<S-down>") (kbd "<S-up>")))
541 ;; For some commands and buffer sources it is useful to configure the
542 ;; :preview-key on a per-command basis using the `consult-customize' macro.
543 (consult-customize
544 consult-theme :preview-key '(:debounce 0.2 any)
545 consult-ripgrep consult-git-grep consult-grep
546 consult-bookmark consult-recent-file consult-xref
547 consult--source-bookmark consult--source-file-register
548 consult--source-recent-file consult--source-project-recent-file
549 ;; :preview-key (kbd "M-.")
550 :preview-key '(:debounce 0.4 any))
551
552 ;; Optionally configure the narrowing key.
553 ;; Both < and C-+ work reasonably well.
554 (setq consult-narrow-key "<") ;; (kbd "C-+")
555
556 ;; Optionally make narrowing help available in the minibuffer.
557 ;; You may want to use `embark-prefix-help-command' or which-key instead.
558 (define-key consult-narrow-map (vconcat consult-narrow-key "?")
559 #'consult-narrow-help))
560
561(use-package orderless
562 :ensure t :demand t
563 :init
564 (setopt completion-styles '(substring orderless basic)
565 completion-category-defaults nil
566 completion-category-overrides
567 '((file (styles basic partial-completion)))))
568
569(use-package marginalia
570 :ensure t :demand t
571 :config
572 (marginalia-mode))
573
574(use-package embark
575 :ensure t
576 :bind
577 (("C-." . embark-act)
578 ("M-." . embark-dwim)
579 ("C-h B" . embark-bindings))
580 :init
581 (setopt prefix-help-command #'embark-prefix-help-command)
582 :config
583 (add-to-list 'display-buffer-alist
584 '("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*"
585 nil
586 (window-parameters (mode-line-format . none)))))
587
588(use-package embark-consult
589 :ensure t
590 :hook
591 (embark-collect-mode . consult-preview-at-point-mode))
592
593(use-package undo-fu-session
594 :ensure t
595 :config
596 (setq undo-fu-session-incompatible-files
597 '("/COMMIT_EDITMSG\\'"
598 "/git-rebase-todo\\'"))
599 (global-undo-fu-session-mode))
600
376;;; basics.el ends here 601;;; basics.el ends here
diff --git a/early-init.el b/early-init.el index 3dd74e0..d59fe64 100644 --- a/early-init.el +++ b/early-init.el
@@ -5,10 +5,11 @@
5;; Debugging shit 5;; Debugging shit
6(setq debug-on-error t 6(setq debug-on-error t
7 use-package-verbose t) 7 use-package-verbose t)
8;; (setq debug-on-message "Selection owner couldn’t convert: TIMESTAMP")
8 9
9;; Frames 10;; Frames
10(setq default-frame-alist '((tool-bar-lines . 0) 11(setq default-frame-alist '((tool-bar-lines . 0)
11 ;; (menu-bar-lines . 0) 12 (menu-bar-lines . 0)
12 (vertical-scroll-bars . nil) 13 (vertical-scroll-bars . nil)
13 (horizontal-scroll-bars . nil)) 14 (horizontal-scroll-bars . nil))
14 frame-inhibit-implied-resize t 15 frame-inhibit-implied-resize t
@@ -21,11 +22,13 @@
21;; Packages 22;; Packages
22(require 'package) 23(require 'package)
23(add-to-list 'package-archives 24(add-to-list 'package-archives
24 '("melpa" . "https://melpa.org/packages/") 25 '("melpa" . "https://melpa.org/packages/") :append)
25 :append) 26(add-to-list 'package-archives
26(setq package-priorities '(("melpa" . 2) 27 '("melpa-stable" . "https://stable.melpa.org/packages/") :append)
27 ("nongnu" . 1) 28(setq package-priorities '(("melpa" . 3)
28 ("gnu" . 0))) 29 ("nongnu" . 2)
30 ("gnu" . 1)
31 ("melpa-stable" . 0)))
29(package-initialize) 32(package-initialize)
30(unless package-archive-contents 33(unless package-archive-contents
31 (package-refresh-contents)) 34 (package-refresh-contents))
diff --git a/init.el b/init.el index 369641c..c3c2f49 100644 --- a/init.el +++ b/init.el
@@ -1,7 +1,456 @@
1;;; init.el --- An Emacs of one's own -*- lexical-binding: t -*- 1;;; init.el --- An Emacs of one's own -*- lexical-binding: t -*-
2
3;; Bankruptcy: 9.4 2;; Bankruptcy: 9.4
4 3
5;;; Code: 4;;; Code:
6 5
7(load (locate-user-emacs-file "basics")) ; super basic stuff 6(load (locate-user-emacs-file "basics")) ; super basic stuff
7
8
9;;; Built-ins
10
11(use-package emacs
12 :custom-face
13 (default ((t :family "Comic Code"
14 :height 100)))
15 (variable-pitch ((t :family "Comic Code")))
16 :config
17 (setopt tab-bar-show 1))
18
19(use-package text-mode
20 :config
21 (add-hook 'text-mode-hook #'abbrev-mode))
22
23(use-package prog-mode
24 :config
25 (add-hook 'prog-mode-hook #'auto-fill-mode)
26 (add-hook 'prog-mode-hook
27 (defun prog@indent-tabs-maybe ()
28 (indent-tabs-mode
29 (if (derived-mode-p 'emacs-lisp-mode
30 'python-mode
31 'haskell-mode)
32 -1 1)))))
33
34(use-package eshell
35 :preface
36 ;; TODO: Break this out into its own package (eshell-pop?). This may not work
37 ;; the way I want it to sometimes .. but then, I don't know how I want it to
38 ;; work sometimes either. More testing, clearly, is needed.
39 (defvar eshell-buffer-format "*eshell:%s*"
40 "Format for eshell buffer names.")
41 (defun eshell-rename-pwd ()
42 (rename-buffer (format eshell-buffer-format default-directory) t))
43 (defun eshell-last-dir ()
44 (goto-char (point-max))
45 (insert "cd -")
46 (eshell-send-input))
47 (defun eshellp (buffer-or-name)
48 (with-current-buffer buffer-or-name
49 (derived-mode-p 'eshell-mode)))
50 (defun +eshell (&optional new)
51 (interactive "P")
52 (let ((dir default-directory)
53 (bname (format eshell-buffer-format default-directory))
54 (display-comint-buffer-action 'pop-to-buffer))
55 (if-let ((buf (and (not new)
56 (or (get-buffer bname)
57 (seq-find #'eshellp
58 (reverse (buffer-list)))))))
59 (pop-to-buffer buf)
60 (eshell new))
61 (eshell-rename-pwd)
62 (unless (equal default-directory dir)
63 (goto-char (point-max))
64 (insert (format "cd %s" dir))
65 (eshell-send-input))))
66 (defun +eshell-quit (&optional choose)
67 (interactive "P")
68 (if choose
69 (let* ((bufs (mapcar #'buffer-name
70 (seq-filter #'eshellp
71 (buffer-list))))
72 (buf (get-buffer
73 (completing-read "Eshell: "
74 bufs nil t nil nil (car bufs)))))
75 (quit-window)
76 (pop-to-buffer buf))
77 (quit-window)))
78 :init
79 (add-hook 'eshell-post-command-hook #'eshell-rename-pwd)
80 :commands eshell
81 :bind (("C-z" . +eshell)
82 :map eshell-mode-map
83 ("C-z" . +eshell-quit)
84 ("C-o" . eshell-last-dir))
85 :config
86 (add-hook 'eshell-mode-hook
87 (defun eshell-setup ()
88 (setq-local imenu-generic-expression
89 '(("Prompt" " $ \\(.*\\)" 1))))))
90
91(use-package auth-source
92 :config
93 (setopt auth-sources '(default "secrets:passwords"))
94 (add-hook 'auth-info-hook #'truncate-lines-local-mode))
95
96(use-package fringe
97 :config
98 (fringe-mode '(nil . 0)))
99
100
101;;; Locally-developed packages
102
103(use-package dawn
104 :load-path "~/src/emacs/dawn/"
105 :after custom-allowed
106 :config
107 (add-hook 'custom-allowed-after-load-hook
108 (defun dawn-modus ()
109 (dawn-schedule-themes 'modus-operandi
110 'modus-vivendi))))
111
112(use-package electric-cursor
113 :load-path "~/src/emacs/electric-cursor/"
114 :config
115 (setopt electric-cursor-alist '((overwrite-mode . box)
116 (t . bar)))
117 (electric-cursor-mode))
118
119(use-package mode-line-bell
120 :load-path "~/src/emacs/mode-line-bell/"
121 :config
122 (setopt mode-line-bell-flash-time 0.25)
123 (mode-line-bell-mode))
124
125(use-package titlecase
126 :load-path "~/src/emacs/titlecase.el/"
127 :after scule
128 :bind (:map scule-map
129 ("M-t" . titlecase-dwim)))
130
131(use-package scule
132 :load-path "~/src/emacs/scule/"
133 :config
134 (defvar-keymap scule-map
135 :doc "Keymap to twiddle scules."
136 :repeat t ; TODO: doesn't work
137 "M-u" #'scule-upcase
138 "M-l" #'scule-downcase
139 "M-c" #'scule-capitalize)
140 (keymap-global-set "M-c" scule-map)
141 ;; Use M-u for prefix keys
142 (keymap-global-set "M-u" #'universal-argument)
143 (keymap-set universal-argument-map "M-u" #'universal-argument-more))
144
145(use-package filldent
146 :load-path "~/src/emacs/filldent/"
147 :bind ("M-q" . filldent-dwim))
148
149(use-package frowny
150 :load-path "~/src/emacs/frowny/"
151 :config
152 (global-frowny-mode))
153
154(use-package jabber
155 :load-path "~/src/emacs/emacs-jabber/"
156 :preface
157 (defun jabber-ui-setup ()
158 "Setup the `jabber' user interface."
159 (visual-fill-column-mode)
160 (electric-pair-local-mode -1)
161 (auto-fill-mode -1))
162 :custom-face
163 (jabber-activity-face ((t :inherit jabber-chat-prompt-foreign
164 :foreground unspecified
165 :weight normal)))
166 (jabber-activity-personal-face ((t :inherit font-lock-warning-face
167 :foreground unspecified
168 :weight bold)))
169 (jabber-chat-prompt-local ((t :inherit font-lock-warning-face
170 :foreground unspecified)))
171 (jabber-chat-prompt-foreign ((t :inherit font-lock-constant-face
172 :foreground unspecified)))
173 (jabber-chat-prompt-system ((t :inherit font-lock-doc-face
174 :foreground unspecified)))
175 (jabber-rare-time-face ((t :inherit font-lock-comment-face
176 :foreground unspecified
177 :underline nil)))
178 :bind-keymap ("C-c j" . jabber-global-keymap)
179 :bind (("C-c C-SPC" . jabber-activity-switch-to))
180 :config
181 (setopt jabber-account-list '(("acdw@hmm.st"))
182 jabber-auto-reconnect t
183 jabber-last-read-marker (make-string 40 ?-)
184 jabber-muc-presence-patterns
185 '(("\\( enters the room ([^)]+)\\| has left the chatroom\\)$")
186 ("." . jabber-muc-presence-dim))
187 jabber-activity-make-strings #'jabber-activity-make-strings-shorten)
188 (add-hook 'jabber-chat-mode-hook #'jabber-ui-setup)
189 (keymap-global-set "C-x C-j" #'dired-jump) ; Extremely annoying fix
190 (require 'jabber-httpupload nil t)
191 (add-hook 'jabber-post-connect-hooks #'jabber-enable-carbons)
192 (remove-hook 'jabber-alert-muc-hooks 'jabber-muc-echo)
193 (remove-hook 'jabber-alert-presence-hooks 'jabber-presence-echo)
194 (add-hook 'jabber-alert-muc-hooks
195 (defun jabber@highlight-acdw (&optional _ _ buf _ _)
196 (when buf
197 (with-current-buffer buf
198 (let ((regexp (rx word-boundary
199 "acdw" ; maybe get from the config?
200 word-boundary)))
201 (hi-lock-unface-buffer regexp)
202 (highlight-regexp regexp 'font-lock-warning-face))))))
203 (add-hook 'window-configuration-change-hook #'jabber-chat-update-focus))
204
205(use-package keepassxc-shim
206 :load-path "~/src/emacs/keepassxc-shim/"
207 :config
208 (keepassxc-shim-activate))
209
210
211;;; External packages
212
213(use-package minions
214 :ensure t
215 :config (minions-mode))
216
217(use-package visual-fill-column
218 :ensure t
219 :init
220 (setopt visual-fill-column-center-text t
221 visual-fill-column-extra-text-width '(1 . 1))
222 :config
223 (add-hook 'visual-fill-column-mode-hook #'visual-line-mode)
224 (add-hook 'eww-mode-hook #'visual-fill-column-mode)
225 (advice-add 'text-scale-adjust :after #'visual-fill-column-adjust))
226
227(use-package mlscroll
228 :ensure t :defer 1
229 :after modus-themes
230 :preface
231 (define-advice load-theme (:after (&rest _) mlscroll)
232 (mlscroll-mode -1)
233 (when (seq-intersection '(modus-vivendi modus-operandi)
234 custom-enabled-themes)
235 (modus-themes-with-colors
236 (setq mlscroll-in-color fg-dim
237 mlscroll-out-color bg-inactive)))
238 (run-with-idle-timer 1 nil #'mlscroll-mode))
239 :config
240 (load-theme@mlscroll))
241
242(use-package cape
243 :ensure t
244 :config
245 (add-hook 'completion-at-point-functions #'cape-file 90)
246 (add-hook 'completion-at-point-functions #'cape-dabbrev 91)
247 (advice-add 'emacs-completion-at-point
248 :around #'cape-wrap-nonexclusive))
249
250(use-package ws-butler
251 :ensure t
252 :config
253 (setopt ws-butler-trim-predicate
254 (lambda (begin end)
255 (not (eq 'font-lock-string-face
256 (get-text-property end 'face)))))
257 (ws-butler-global-mode))
258
259(use-package wgrep
260 :ensure t
261 :config
262 (setopt wgrep-enable-key (kbd "C-x C-q"))
263 :bind (:map grep-mode-map
264 ("C-x C-q" . wgrep-change-to-wgrep-mode)))
265
266(use-package avy
267 :ensure t
268 :init
269 (setopt avy-background t
270 avy-keys (string-to-list "asdfghjklqwertyuiopzxcvbnm"))
271 :bind (("M-j" . avy-goto-char-timer)
272 :map isearch-mode-map
273 ("M-j" . avy-isearch)))
274
275(use-package zzz-to-char
276 :ensure t
277 :bind (("M-z" . zzz-to-char)))
278
279(use-package anzu
280 :ensure t
281 :bind (("M-%" . anzu-query-replace-regexp)
282 ("C-M-%" . anzu-query-replace)))
283
284(use-package isearch-mb
285 :ensure t
286 :config
287 (setopt isearch-lazy-count t
288 isearch-regexp-lax-whitespace t
289 search-whitespace-regexp "\\W+"
290 search-default-mode t ; Search regexp by default
291 isearch-wrap-pause 'no)
292 (define-advice isearch-cancel (:before (&rest _) add-search-to-history)
293 "Add search string to history when canceling."
294 (unless (equal "" isearch-string)
295 (isearch-update-ring isearch-string isearch-regexp)))
296 (define-advice perform-replace (:around (orig &rest r) no-anykey-exit)
297 "Don't exit replace for any key that's not in `query-replace-map'."
298 (save-window-excursion
299 (cl-letf* ((lookup-key-orig (symbol-function 'lookup-key))
300 ((symbol-function 'lookup-key)
301 (lambda (map key &optional accept-default)
302 (or (apply lookup-key-orig map key accept-default)
303 (when (eq map query-replace-map) 'help)))))
304 (apply orig r))))
305 ;; Consult
306 (autoload 'consult-line "consult" nil t)
307 (autoload 'consult-isearch-history "consult" nil t)
308 (add-to-list 'isearch-mb--after-exit #'consult-line)
309 (add-to-list 'isearch-mb--with-buffer #'consult-isearch-history)
310 (keymap-set isearch-mb-minibuffer-map "M-s l" #'consult-line)
311 (keymap-set isearch-mb-minibuffer-map "M-r" #'consult-isearch-history)
312 ;; Anzu
313 (autoload 'anzu-isearch-query-replace "anzu" nil t)
314 (autoload 'anzu-isearch-query-replace-regexp "anzu" nil t)
315 (add-to-list 'isearch-mb--after-exit #'anzu-isearch-query-replace)
316 (add-to-list 'isearch-mb--after-exit #'anzu-isearch-query-replace-regexp)
317 (keymap-set isearch-mb-minibuffer-map
318 "M-%" #'anzu-isearch-query-replace-regexp)
319 (keymap-set isearch-mb-minibuffer-map
320 "C-M-%" #'anzu-isearch-query-replace)
321 (isearch-mb-mode))
322
323(use-package paredit
324 :ensure t
325 :hook ( emacs-lisp-mode-hook ielm-mode-hook
326 eval-expression-minibuffer-setup-hook
327 lisp-interaction-mode-hook
328 lisp-mode-hook scheme-mode-hook
329 fennel-mode-hook fennel-repl-mode-hook
330 geiser-mode-hook geiser-repl-mode-hook)
331 :config
332 (keymap-set paredit-mode-map "C-j"
333 (defun +paredit-newline
334 (interactive)
335 (call-interactively
336 (if (derived-mode-p 'lisp-interaction-mode)
337 #'eval-print-last-sexp #'paredit-newline))))
338 (keymap-set paredit-mode-map "RET" nil)
339 (keymap-set paredit-mode-map "M-s" nil)
340 (add-to-list 'paredit-space-for-delimiter-predicates
341 (defun paredit@dont-space-@ (endp delimiter)
342 "Don't add a space after @ in `paredit-mode'."
343 (let ((point (point)))
344 (or endp
345 (seq-every-p
346 (lambda (prefix)
347 (and (> point (length prefix))
348 (let ((start (- point (length prefix)))
349 (end point))
350 (not (string= (buffer-substring start end)
351 prefix)))))
352 ;; Add strings to this list to inhibit adding a space
353 ;; after them.
354 '(",@"))))))
355 (with-eval-after-load 'eldoc
356 (eldoc-add-command #'paredit-backward-delete #'paredit-close-round)))
357
358(use-package hungry-delete
359 :ensure t
360 :config
361 (setopt hungry-delete-chars-to-skip " \t"
362 hungry-delete-skip-regexp (format "[%s]" hungry-delete-chars-to-skip)
363 hungry-delete-join-reluctantly nil)
364 (add-to-list 'hungry-delete-except-modes 'eshell-mode)
365 (add-to-list 'hungry-delete-except-modes 'nim-mode)
366 (add-to-list 'hungry-delete-except-modes 'python-mode)
367 ;; Keys
368 (with-eval-after-load 'paredit
369 (define-key paredit-mode-map [remap paredit-backward-delete]
370 (defun paredit/hungry-delete-backward (arg)
371 (interactive "*p")
372 (if (looking-back hungry-delete-skip-regexp)
373 (hungry-delete-backward (or arg 1))
374 (paredit-backward-delete arg))))
375 (define-key paredit-mode-map [remap paredit-forward-delete]
376 (defun paredit/hungry-delete-forward (arg)
377 (interactive "*p")
378 (if (looking-at hungry-delete-skip-regexp)
379 (hungry-delete-forward (or arg 1))
380 (paredit-forward-delete arg))))
381 ;; Mode
382 (global-hungry-delete-mode)))
383
384(use-package macrostep
385 :ensure t
386 :after elisp-mode
387 :bind ( :map emacs-lisp-mode-map
388 ("C-c e" . macrostep-expand)
389 :map lisp-interaction-mode-map
390 ("C-c e" . macrostep-expand)))
391
392(use-package package-lint
393 :ensure t)
394
395(use-package sly
396 :ensure t
397 :preface
398 (setopt inferior-lisp-program (choose-executable "sbcl"))
399 :when inferior-lisp-program
400 :bind (:map sly-mode-map
401 ("C-c C-z" . sly-mrepl))
402 :config
403 (setopt sly-net-coding-system 'utf-8-unix)
404 (sly-symbol-completion-mode -1))
405
406(use-package eat
407 :ensure t
408 :hook (eshell-load-hook . eat-eshell-mode))
409
410(use-package pdf-tools
411 :ensure t
412 :mode ("\\.[pP][dD][fF]\\'" . pdf-view-mode)
413 :magic ("%PDF" . pdf-view-mode)
414 :config
415 (pdf-tools-install))
416
417(use-package keychain-environment
418 :ensure t
419 :when (executable-find "keychain")
420 :hook (after-init-hook . keychain-refresh-environment))
421
422(use-package web-mode
423 :ensure t
424 :mode ("\\.phtml\\'"
425 "\\.tpl\\.php\\'"
426 "\\.[agj]sp\\'"
427 "\\.as[cp]x\\'"
428 "\\.erb\\'"
429 "\\.mustache\\'"
430 "\\.djhtml\\'"
431 "\\.html?\\'"))
432
433(use-package nginx-mode
434 :ensure t
435 :mode "/nginx/sites-\\(?:available\\|enabled\\)/")
436
437(use-package markdown-mode
438 :ensure t
439 :mode "\\.\\(?:md\\|markdown\\|mkd\\|mdown\\|mkdn\\|mdwn\\)\\'"
440 :config
441 (setopt markdown-command (choose-executable
442 '("pandoc" "--from=markdown" "--to=html5")
443 "markdown"))
444 (add-hook 'markdown-mode-hook #'visual-fill-column-mode))
445
446(use-package transpose-frame
447 :ensure t
448 :bind (("C-x 5 t" . transpose-frame)
449 ("C-x 5 h" . flop-frame) ; horizontal
450 ("C-x 5 v" . flip-frame) ; vertical
451 ))
452
453(use-package magit
454 :pin melpa-stable
455 :ensure t
456 :bind ("C-x g" . magit))
diff --git a/lisp/acdw.el b/lisp/acdw.el new file mode 100644 index 0000000..f16a679 --- /dev/null +++ b/lisp/acdw.el
@@ -0,0 +1,39 @@
1;;; acdw.el --- My Emacs extras -*- lexical-binding: t; -*-
2
3;;; Code:
4
5(defmacro defdir (name directory &optional docstring makedir)
6 "Define a variable and a function NAME expanding to DIRECTORY.
7DOCSTRING is applied to the variable; its default is DIRECTORY's
8path. If MAKEDIR is non-nil, the directory and its parents will
9be created."
10 (declare (indent 2) (doc-string 3))
11 `(progn
12 (defvar ,name (expand-file-name ,directory)
13 ,(concat (or docstring (format "%s" directory)) "\n"
14 "Defined by `defdir'."))
15 (defun ,name (file &optional mkdir)
16 ,(concat "Expand FILE relative to variable `" (symbol-name name) "'.\n"
17 "If MKDIR is non-nil, parent directories are created.\n"
18 "Defined by `defdir'.")
19 (let ((file-name (expand-file-name
20 (convert-standard-filename file) ,name)))
21 (when mkdir
22 (make-directory (file-name-directory file-name) :parents))
23 file-name))
24 ,(if makedir
25 `(make-directory ,directory :parents)
26 `(unless (file-exists-p ,directory)
27 (warn "Directory `%s' doesn't exist." ,directory)))))
28
29(defun choose-executable (&rest programs)
30 "Return the first of PROGRAMS that exists in the system's $PATH.
31Each of PROGRAMS can be a single string, or a list. If it's a list then its car
32will be tested with `executable-find', and the entire list returned. This
33enables passing arguments to a calling function."
34 (seq-find (lambda (x)
35 (executable-find (car (ensure-list x))))
36 programs))
37
38(provide 'acdw)
39;;; acdw.el ends here