summary refs log tree commit diff stats
path: root/basics.el
diff options
context:
space:
mode:
Diffstat (limited to 'basics.el')
-rw-r--r--basics.el315
1 files changed, 270 insertions, 45 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