emacs: accept the wisdom of minimal-emacs.d
1 file changed, 147 insertions(+), 124 deletions(-)
changed files
M user/settings/emacs/init.el → user/settings/emacs/post-init.el
@@ -1,23 +1,4 @@ -;;; init --- user init file -*- lexical-binding: t; -*- -(eval '(setq inhibit-startup-echo-area-message "alan")) -(defvar default-file-name-handler-alist file-name-handler-alist) -(setq file-name-handler-alist nil - gc-cons-threshold most-positive-fixnum - gc-cons-percentage 0.6 - read-process-output-max (* 4 1024 1024)) -(defun set-max-gc-cons () - (setq gc-cons-threshold most-positive-fixnum)) -(defun set-default-gc-cons () - (setq gc-cons-threshold (* 16 1024 1024) - gc-cons-percentage 0.1)) -(add-hook 'minibuffer-setup-hook #'set-max-gc-cons) -(add-hook 'minibuffer-exit-hook #'set-default-gc-cons) -(add-hook 'after-init-hook #'set-default-gc-cons) - -(defun restore-file-name-handler-alist () - (setq file-name-handler-alist default-file-name-handler-alist)) -(add-hook 'emacs-startup-hook #'restore-file-name-handler-alist) - +;;; post-init --- user init file -*- lexical-binding: t; -*- (defun maybe-start-server () (require 'server) (unless (server-running-p)@@ -34,10 +15,11 @@ (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t) (run-with-idle-timer 300 nil #'package-refresh-contents) -(setq use-package-enable-imenu-support t) -(require 'use-package) +(eval-when-compile + (require 'use-package)) + (setq use-package-always-demand (daemonp) - use-package-compute-statistics nil) + use-package-always-ensure nil) (defmacro quietly (&rest body) `(let ((inhibit-message t))@@ -62,14 +44,6 @@ (general-unbind "s-x")))) ;;; Styles -;; I prefer an always-visible cursor. Feels less distracting. -(blink-cursor-mode -1) - -(setq-default truncate-lines t) - -;; Don't ring the bell -(setq ring-bell-function #'ignore) - (use-package exec-path-from-shell :if (eq system-type 'darwin) :config (progn@@ -78,16 +52,8 @@ (global-set-key (kbd "<pinch>") 'ignore) (global-set-key (kbd "<C-wheel-up>") 'ignore) (global-set-key (kbd "<C-wheel-down>") 'ignore) - -(setq font-lock-maximum-decoration '((t . 1)) - jit-lock-stealth-time 1.25 - jit-lock-stealth-nice 0.5 - jit-lock-chunk-size 4096) - -(context-menu-mode +1) ;;; Chrome -(column-number-mode -1) (line-number-mode -1) (use-package nerd-icons@@ -113,14 +79,11 @@ (when (eq system-type 'darwin) (add-to-list 'default-frame-alist '(undecorated . t)) (add-to-list 'default-frame-alist '(ns-transparent-titlebar . t)) - (add-to-list 'default-frame-alist '(ns-appearance . 'light)) - (setq ns-use-srgb-colorspace nil)) + (add-to-list 'default-frame-alist '(ns-appearance . 'light))) (add-to-list 'default-frame-alist '(width . 100)) (add-to-list 'default-frame-alist '(height . 40)) -(setq-default display-line-numbers 'relative - display-line-numbers-widen t - display-line-numbers-width 3) +(setq-default display-line-numbers 'relative) (defun turn-off-display-line-numbers-mode () (interactive)@@ -131,7 +94,6 @@ (interactive) (display-line-numbers-mode (default-value 'display-line-numbers))) (setq frame-resize-pixelwise t - window-resize-pixelwise t display-buffer-alist `(("\\*\\(?:shell\\|compilation\\)\\*" display-buffer-in-side-window (side . bottom) (slot . 0) (preserve-size . (nil . t)) (no-other-window . t) (no-delete-other-windows . t))))@@ -175,19 +137,20 @@ (add-hook 'evil-insert-state-entry-hook #'noct-absolute) (add-hook 'evil-insert-state-exit-hook #'noct-relative) -(use-package ultra-scroll - :defer 1 +(use-package pixel-scroll + :ensure nil + :if (not ;; i.e. not emacs-macport + (or (eq window-system 'mac) + (bound-and-true-p mac-carbon-version-string))) :config (progn - (setq scroll-margin 0 - scroll-conservatively 101) - (ultra-scroll-mode +1))) + (setq pixel-scroll-precision-use-momentum t) + (pixel-scroll-precision-mode 1) )) ;;; Encoding (setq-default bidi-paragraph-direction 'left-to-right bidi-display-reordering 'left-to-right) -(setq bidi-inhibit-bpa t - require-final-newline t) +(setq bidi-inhibit-bpa t) (add-to-list 'auto-coding-alist '("prescient-save\\.el\\'" . utf-8-emacs)) ;;; Dates & Times@@ -255,6 +218,10 @@ (define-key global-map (kbd "s-k") #'kill-current-buffer :remove)) (use-package avy :defer 2 + :commands (avy-goto-char + avy-goto-char-2 + avy-next) + :general ("C-'" #'avy-goto-char-2) :config (setq avy-all-windows nil)) (use-package link-hint@@ -264,32 +231,56 @@ ;; Popup keybindings following a prefix automatically. (use-package which-key :defer 5 + :custom + (which-key-idle-delay 1.5) + (which-key-idle-secondary-delay 0.25) + (which-key-add-column-padding 1) + (which-key-max-description-length 40) :config (progn (which-key-mode +1) (which-key-setup-side-window-right-bottom))) ;;; Minibuffer -(setq enable-recursive-minibuffers t - save-silently t - uniquify-buffer-name-style 'forward - read-extended-command-predicate #'command-completion-default-include-p) +(setq save-silently t) (minibuffer-depth-indicate-mode t) (use-package hydra :defer 2) (use-package recentf - :defer 1 - :custom (recentf-auto-cleanup 1800) + :ensure nil + :commands (recentf-mode recentf-cleanup) + :custom + (recentf-auto-cleanup (if (daemonp) 1800 'never)) + (recentf-exclude + (list "\\.tar$" "\\.tbz2$" "\\.tbz$" "\\.tgz$" "\\.bz2$" + "\\.bz$" "\\.gz$" "\\.gzip$" "\\.xz$" "\\.zip$" + "\\.7z$" "\\.rar$" + "COMMIT_EDITMSG\\'" + "\\.\\(?:gz\\|gif\\|svg\\|png\\|jpe?g\\|bmp\\|xpm\\)$" + "-autoloads\\.el$" "autoload\\.el$")) + :config (progn - (quietly (recentf-mode +1)) - (advice-add 'recentf-cleanup :around #'quiet))) + ;; A cleanup depth of -90 ensures that `recentf-cleanup' runs before + ;; `recentf-save-list', allowing stale entries to be removed before the list + ;; is saved by `recentf-save-list', which is automatically added to + ;; `kill-emacs-hook' by `recentf-mode'. + (add-hook 'kill-emacs-hook #'recentf-cleanup -90))) (use-package savehist - :init (savehist-mode +1) + :ensure nil + :commands (savehist-mode savehist-save) :config (progn - (add-to-list 'savehist-additional-variables 'command-history))) + (quietly (recentf-mode +1)) + (advice-add 'recentf-cleanup :around #'quiet)) + :custom + (savehist-autosave-interval 600) + (savehist-additional-variables + '(kill-ring ; clipboard + register-alist ; macros + mark-ring global-mark-ring ; marks + search-ring regexp-search-ring))) (use-package persist-state :defer 1@@ -313,9 +304,10 @@ (vertico-prescient-mode +1))) (use-package marginalia :after vertico + :commands (marginalia-mode marginalia-cycle) + :hook (after-init . marginalia-mode) :general (:keymaps 'minibuffer-local-map - "M-A" #'marginalia-cycle) - :init (marginalia-mode +1)) + "M-A" #'marginalia-cycle)) (setq completion-ignore-case t read-buffer-completion-ignore-case t@@ -324,6 +316,8 @@ completion-styles '(flex substring basic) completion-category-overrides '((file (styles basic partial-completion)))) (use-package consult + ;; Enable automatic preview at point in the *Completions* buffer. + :hook (completion-list-mode . consult-preview-at-point-mode) :general ([remap isearch-forward] #'consult-line [remap isearch-backward] #'consult-line [remap project-switch-to-buffer] #'consult-project-buffer@@ -374,21 +368,6 @@ (unpackaged/smerge-hydra/body))))) ;;; Windows -(defun split-window-properly (&optional window) - (let ((window (or window (selected-window)))) - (or (and (window-splittable-p window) - ;; Split window vertically. - (with-selected-window window - (split-window-below))) - (and (window-splittable-p window t) - ;; Split window horizontally. - (with-selected-window window - (split-window-right)))))) - -(setq split-window-preferred-function #'split-window-properly - split-height-threshold 20 - split-width-threshold 160) - (use-package winner :defer 8 :config (progn@@ -493,10 +472,12 @@ :after evil :config (progn (evil-exchange-cx-install))) -(use-package evil-commentary - :after evil - :defer 2 - :config (evil-commentary-mode +1)) +(with-eval-after-load "evil" + (evil-define-operator my-evil-comment-or-uncomment (beg end) + "Toggle comment for the region between BEG and END." + (interactive "<r>") + (comment-or-uncomment-region beg end)) + (evil-define-key 'normal 'global (kbd "gc") 'my-evil-comment-or-uncomment)) (use-package evil-lion :after evil@@ -562,31 +543,40 @@ ;;; Completion (use-package corfu :defer 1 + :commands (corfu-mode global-corfu-mode) + :hook ((prog-mode . corfu-mode) + (shell-mode . corfu-mode) + (eshell-mode . corfu-mode)) + :custom + ;; Hide commands in M-x which do not apply to the current mode. + (read-extended-command-predicate #'command-completion-default-include-p) + ;; Disable Ispell completion function. As an alternative try `cape-dict'. + (text-mode-ispell-word-completion nil) + (corfu-auto t) + (corfu-auto-delay 0.1) + (corfu-auto-prefix 3) + (corfu-on-exact-match nil) + (corfu-preview-current nil) + (corfu-preselect 'prompt) + (corfu-on-exact-match 'quit) :config (progn (global-corfu-mode +1) - (setq corfu-auto t - corfu-auto-delay 0.1 - corfu-auto-prefix 3 - corfu-on-exact-match nil - corfu-preview-current nil - corfu-preselect 'prompt - corfu-on-exact-match 'quit) - (defun corfu-enable-in-minibuffer () - "Enable Corfu in the minibuffer if `completion-at-point' is bound." - (when (where-is-internal #'completion-at-point (list (current-local-map))) - (setq-local corfu-auto nil) ;; Enable/disable auto completion - (setq-local corfu-echo-delay nil ;; Disable automatic echo and popup - corfu-popupinfo-delay nil) - (corfu-mode 1))) - (add-hook 'minibuffer-setup-hook #'corfu-enable-in-minibuffer) (add-hook 'eshell-mode-hook (lambda () (setq-local corfu-auto nil) (corfu-mode +1))))) (use-package cape :after (corfu) + :commands (cape-dabbrev cape-file cape-elisp-block) :general (:states 'insert - "C-x C-f" #'cape-file)) + "C-x C-f" #'cape-file + "C-c p" 'cape-prefix-map) + :init + ;; Add to the global default value of `completion-at-point-functions' which is + ;; used by `completion-at-point'. + (add-hook 'completion-at-point-functions #'cape-dabbrev) + (add-hook 'completion-at-point-functions #'cape-file) + (add-hook 'completion-at-point-functions #'cape-elisp-block)) (use-package kind-icon :after (corfu)@@ -624,26 +614,37 @@ :defer 15 :general ([remap help-map] 'electric-help-map)) (use-package helpful - :general (ehelp-map - "k" #'helpful-key - "v" #'helpful-variable - "f" #'helpful-callable)) + :ensure t + :commands (helpful-callable + helpful-variable + helpful-key + helpful-command + helpful-at-point + helpful-function) + :bind + ([remap describe-command] . helpful-command) + ([remap describe-function] . helpful-callable) + ([remap describe-key] . helpful-key) + ([remap describe-symbol] . helpful-symbol) + ([remap describe-variable] . helpful-variable) + :custom + (helpful-max-buffers 7)) ;;; Files ;;;; Auto-saving -(setq auto-save-default nil - make-backup-files nil - create-lockfiles nil) +(setq auto-save-default t + auto-save-interval 300 + auto-save-timeout 30) ;;;; Auto-reloading (use-package autorevert - :config (progn - (setq auto-revert-verbose nil - auto-revert-use-notify t) - (global-auto-revert-mode 1))) + :ensure nil + :commands (auto-revert-mode global-auto-revert-mode) + :hook (after-init . global-auto-revert-mode) + :custom (auto-revert-verbose nil)) (setq delete-by-moving-to-trash t)@@ -690,17 +691,26 @@ (remove-hook 'compilation-mode-hook #'tramp-compile-disable-ssh-controlmaster-options)))) ;;; Directories -(setq dired-dwim-target t - dired-recursive-copies 'top - dired-listing-switches "-alh" +(setq dired-listing-switches "-alhv" dired-kill-when-opening-new-dired-buffer t + dired-movement-style 'bounded-files dired-recursive-deletes (if delete-by-moving-to-trash 'always 'top)) -(add-hook 'dired-mode-hook - (lambda () - (dired-hide-details-mode))) +(add-hook 'dired-mode-hook #'dired-hide-details-mode) + +(setq dired-omit-files (concat "\\`[.]\\'" + "\\|\\(?:\\.js\\)?\\.meta\\'" + "\\|\\.\\(?:elc|a\\|o\\|pyc\\|pyo\\|swp\\|class\\)\\'" + "\\|^\\.DS_Store\\'" + "\\|^\\.\\(?:svn\\|git\\)\\'" + "\\|^\\.ccls-cache\\'" + "\\|^__pycache__\\'" + "\\|^\\.project\\(?:ile\\)?\\'" + "\\|^flycheck_.*" + "\\|^flymake_.*")) +(add-hook 'dired-mode-hook #'dired-omit-mode) ;;; Shells@@ -760,14 +770,11 @@ "C-d" #'comint-delchar-or-maybe-eof)) (use-package comint :defer t + :ensure nil :general (:keymaps 'comint-mode-map "C-c C-l" #'counsel-shell-history)) ;;; Editing - -(setq-default tab-always-indent 'complete - indent-tabs-mode nil - tab-width 4) (if (fboundp 'kill-ring-deindent-mode) (kill-ring-deindent-mode +1))@@ -894,6 +901,21 @@ :ghook '(emacs-lisp-mode-hook clojure-mode-hook racket-mode-hook)) +(use-package aggressive-indent + :ghook '(emacs-lisp-mode-hook + clojure-mode-hook + racket-mode-hook)) + +(use-package highlight-defined-mode + :ghook '(emacs-lisp-mode-hook)) + +(use-package elisp-refs + :commands (elisp-refs-function + elisp-refs-macro + elisp-refs-variable + elisp-refs-special + elisp-refs-symbol)) + ;;;; org (use-package org@@ -1100,7 +1122,11 @@ (apheleia-mode -1))) (remove-hook 'before-save-hook #'eglot-format-buffer 'local))) (use-package eglot + :ensure nil :defer 3 + :commands (eglot-ensure + eglot-rename + eglot-format-buffer) :general (:states 'normal :keymaps 'eglot-mode-map "gr" #'xref-find-references "C-t" #'xref-go-back)@@ -1182,7 +1208,6 @@ ;;;; Reformat on save (use-package apheleia - :defer 11 :ghook 'prog-mode-hook :config (progn (setf (alist-get 'shfmt apheleia-formatters)@@ -1195,9 +1220,7 @@ (prettier-gotmpl "prettier" "--stdin-filepath" filepath "--parser=go-template" (apheleia-formatters-indent "--use-tabs" "--tab-width"))))) (setf (alist-get 'sql-mode apheleia-mode-alist) 'sqlfluff) - (setq apheleia-mode-alist (append apheleia-mode-alist '((toml-ts-mode . taplo))))) - :init (progn - (apheleia-global-mode +1))) + (setq apheleia-mode-alist (append apheleia-mode-alist '((toml-ts-mode . taplo)))))) ;;; Take me to my leader