From cee1e17974adc12582a13c7340e423e494ed8da9 Mon Sep 17 00:00:00 2001 From: noa Date: Mon, 14 Oct 2024 10:28:35 +0800 Subject: Convert more things to use-package --- emacs/init.el | 286 ++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 170 insertions(+), 116 deletions(-) diff --git a/emacs/init.el b/emacs/init.el index ea7f92a..b5a0793 100644 --- a/emacs/init.el +++ b/emacs/init.el @@ -5,7 +5,10 @@ ;; - Look at grep-use-headings ;; - Look at elpa-openwith +;; (profiler-start 'cpu+mem) + (add-to-list 'load-path (expand-file-name (concat user-emacs-directory "site-lisp"))) +(add-to-list 'exec-path "/home/noa/.config/Scripts") (use-package use-package :custom (use-package-compute-statistics t)) @@ -22,32 +25,33 @@ :custom (gcmh-mode t)) -(setopt user-full-name "noa") -(setopt user-mail-address "noa@noa.pub") - ;; Properly distinguish these chords from their ascii legacy (define-key input-decode-map [?\C-m] [C-m]) ;;; Modern keybindings ;; A lot of people say that you get used to emacs keybindings over time, and this is true. But i find it hard to maintain two sets of keybindings in my head: those for emacs, and those for everything else. So i think that it's best to make emacs use the same bindings as everything else. For now, we do that with wakib mode. -(require 'wakib-keys) -(setopt wakib-keys t) - -(with-eval-after-load 'wakib-keys - (add-hook 'after-change-major-mode-hook 'wakib-update-major-mode-map) - (add-hook 'menu-bar-update-hook 'wakib-update-minor-mode-maps) - ;; Modifying other modules - ;; When remap is used it exits isearch abruptly after first instance - ;; Use explicit keybindings instead - (define-key isearch-mode-map (kbd "C-f") 'isearch-repeat-forward) - (define-key isearch-mode-map (kbd "C-S-f") 'isearch-repeat-backward) - (define-key isearch-mode-map (kbd "M-;") 'isearch-repeat-forward) - (define-key isearch-mode-map (kbd "M-:") 'isearch-repeat-backward) - (define-key isearch-mode-map (kbd "C-v") 'isearch-yank-kill) - (define-key isearch-mode-map (kbd "M-d") 'isearch-delete-char)) +(use-package wakib-keys + :disabled t + :ensure t + :custom + (wakib-keys t) + + :hook + ((after-change-major-mode . wakib-update-major-mode-map) + (menu-bar-update . wakib-update-minor-mode-maps)) + + :bind (:map isearch-mode-map + ("C-f" . isearch-repeat-forward) + ("C-S-f" . isearch-repeat-backward) + ("M-;" . isearch-repeat-forward) + ("M-:" . isearch-repeat-backward) + ("C-v" . isearch-yank-kill) + ("M-d" . isearch-delete-char))) ;; It is often useful to be able to run a command while i am already in the process of running a command in the minibuffer. This is rarely two extended commands; usually it is completion. -(setopt minibuffer-depth-indicate-mode t) +(use-package mb-depth + :custom + (minibuffer-depth-indicate-mode t)) ;; This is my emacs theme. It's a monochrome theme which, unlike most monochrome themes, really does have only two colours. I define a few faces, and set every other face as one of them. There are a few things i want to do with it before i make it properly public: make the colours configurable and able to update on the fly, and in general iron out some of the janky parts. A few things defined it are quite specific to this configuration, like the way i define the borders for the tab and header bars, and there is no mode line configuration because i don't use it. (require 'tubthumping-theme) @@ -69,34 +73,45 @@ (set-fontset-font t 'emoji (font-spec :family "Noto Emoji") nil 'append) ;; While we're here, let's set up emoji input. -(global-set-key (kbd "C-.") #'emoji-search) +(use-package emoji + :bind ("C-." . emoji-search)) ;; Update the calendar. We want weeks to start on a monday, the first day of the week. Holidays should be highlighted, and the date format should put the year first. -(setopt calendar-week-start-day 1 - calendar-date-style 'iso) +(use-package calendar + :defer t + :custom + (calendar-week-start-day 1) + (calendar-date-style 'iso) -;; Ensure the calendar always displays at the bottom of the screen, rather than wrapping weirdly and looking bad when it shows up in a side window. -(add-to-list 'display-buffer-alist + :config + ;; Ensure the calendar always displays at the bottom of the screen, rather than wrapping weirdly and looking bad when it shows up in a side window. + (add-to-list 'display-buffer-alist '("\\*Calendar\\*" (display-buffer-in-side-window) - (side . bottom))) + (side . bottom)))) + + ;; This is my own version of fixed-pitch, which has some changes to it. No hooks are added by default. Updating the whitelist automatically applies the hooks. And there is no functionality for changing the cursor type. -(use-package fixed-pitch) -(setopt fixed-pitch-whitelist-hooks '(calendar-mode-hook - dired-mode-hook - ibuffer-mode-hook - magit-mode-hook - profiler-report-mode-hook - jabber-roster-mode-hook - mu4e-headers-mode-hook - proced-mode-hook - rmail-summary-mode-hook - ebib-index-mode-hook - ebib-entry-mode-hook)) - -;; Ensure that transients look nice with a variable pitch font. -(setopt transient-align-variable-pitch t) +(use-package fixed-pitch + :custom + (fixed-pitch-whitelist-hooks '(calendar-mode-hook + dired-mode-hook + ibuffer-mode-hook + magit-mode-hook + profiler-report-mode-hook + jabber-roster-mode-hook + mu4e-headers-mode-hook + proced-mode-hook + rmail-summary-mode-hook + ebib-index-mode-hook + ebib-entry-mode-hook))) + +(use-package transient + :defer t + :custom + ;; Ensure that transients look nice with a variable pitch font. + (transient-align-variable-pitch t)) ;; Reading prose with long lines is a chore. Luckily there are several packages in emacs to make the windows squeeze text into a more legible sliver. Previously i used olivetti, which is a really nice package, but it's quite heavyweight and broke on me with no explanation more frequently than i appreciated. I've switched to visual-fill-column and been quite satisfied. (use-package visual-fill-column @@ -195,43 +210,59 @@ The misspelled word is taken from OVERLAY. WORD is the corrected word." ;; I mentioned that i thought this wasn't the best default behaviour [[https://github.com/minad/jinx/discussions/184][in the jinx repository]], but Daniel seems happy with it. I appreciate that he's made it so easy to change the behaviour to something i prefer. ;; Make it easier to close help windows -(setopt help-window-select t) - -;; When opening source files from a help window, use the same window -(setopt help-window-keep-selected t) +(use-package help + :defer t + :custom + (help-window-select t) + ;; When opening source files from a help window, use the same window + (help-window-keep-selected t)) ;; I use eww, a browser more closely aligned with browsers for the terminal. Despite the name, eww is a delight to use for text-heavy websites. If a website doesn't render well in it, because it uses fancy layout tricks or lots of javascript, we can press ~&~ to open the url in firefox. -(setopt browse-url-browser-function 'eww-browse-url - browse-url-secondary-browser-function 'browse-url-default-browser) +(use-package browse-url + :defer t + :custom + (browse-url-browser-function 'eww-browse-url) + (browse-url-secondary-browser-function 'browse-url-default-browser)) ;; For the kind of sites i use eww to visit, i've not had a use for cookies. We can tell emacs that we don't trust cookies from any sites, we don't trust cookies from all sites, and frankly, we don't want to use cookies. -(setopt url-cookie-trusted-urls '() - url-cookie-untrusted-urls '(".*") - shr-cookie-policy nil) - -;; Eww has rudimentary support for colours. But i don't want web pages to be able to specify their own colours, because i like the colours i already have set. -(setopt shr-use-colors nil) - -;; Shr has the ability to break paragraphs to fit on the screen. Instead of this, we set it to not break any lines, and use visual-fill-column-mode to do this for us instead. -(setopt shr-max-width nil) - -;; We can set what the maximum size of an image in a window should be. This is a fraction of the total window width or height, and if the image would be bigger than this, it'll be resized to fit. It's useful to have it smaller because emacs still sort of chokes on scrolling when there are large images in a buffer. This is the default value of this option. -(setopt shr-max-image-proportion 0.9 - shr-discard-aria-hidden t) +(use-package url-cookie + :defer t + :custom + (url-cookie-trusted-urls '()) + (url-cookie-untrusted-urls '(".*"))) -(setopt shr-bullet " • ") +(use-package shr + :defer t + :custom + (shr-cookie-policy nil) + ;; Eww has rudimentary support for colours. But i don't want web pages to be able to specify their own colours, because i like the colours i already have set. + (shr-use-colors nil) + ;; Shr has the ability to break paragraphs to fit on the screen. Instead of this, we set it to not break any lines, and use visual-fill-column-mode to do this for us instead. + (shr-max-width nil) + (shr-bullet " • ") + (shr-discard-aria-hidden t) + ;; We can set what the maximum size of an image in a window should be. This is a fraction of the total window width or height, and if the image would be bigger than this, it'll be resized to fit. It's useful to have it smaller because emacs still sort of chokes on scrolling when there are large images in a buffer. This is the default value of this option. +(shr-max-image-proportion 0.9)) + +(use-package eww + :defer t -;; The default name for the eww buffer is *eww*. This is unhelpful because it makes having more than one eww buffer open a bit of a chore to navigate. We can set it to 'url, 'title, or a function. I set it to 'title because marginalia already shows me the url. However, this means that i can't search for a url name when switching buffers. See the help for this variable for an example of a function which gives the page title and the url. -(setopt eww-auto-rename-buffer 'title) + :custom + ;; The default name for the eww buffer is *eww*. This is unhelpful because it makes having more than one eww buffer open a bit of a chore to navigate. We can set it to 'url, 'title, or a function. I set it to 'title because marginalia already shows me the url. However, this means that i can't search for a url name when switching buffers. See the help for this variable for an example of a function which gives the page title and the url. + (eww-auto-rename-buffer 'title)) ;; Goto address mode makes urls and email address in a buffer clickable. I want these clickable links to look like links, because that's what they are. The two mouse face variables are what face is used on hover, which at the moment i ignore. It might also be worth setting them to 'highlight. -(setopt global-goto-address-mode t) -(setopt goto-address-mail-face 'link) -(setopt goto-address-mail-mouse-face 'highlight) -(setopt goto-address-url-face 'link) -(setopt goto-address-url-mouse-face 'highlight) +(use-package goto-addr + :custom + (global-goto-address-mode t) + (goto-address-mail-face 'link) + (goto-address-mail-mouse-face 'highlight) + (goto-address-url-face 'link) + (goto-address-url-mouse-face 'highlight)) -(setopt global-eldoc-mode t) +(use-package eldoc + :custom + (global-eldoc-mode t)) ;; Use a bar cursor and blink it and don't stop blinking it. i don't know how i feel about this yet to be honest, but it helps me know which window is active so for now i'm keeping it (setopt cursor-type 'bar @@ -241,37 +272,49 @@ The misspelled word is taken from OVERLAY. WORD is the corrected word." ;; By default, dired permanently deletes files. But i have quite a bit of storage and also make bad decisions regularly, so it seems fitting to make use of the wonderful invention that is the trash. People who have used systems from the last forty years or so will likely be familiar with this innovation. (setopt delete-by-moving-to-trash t) +(use-package dired + :defer t + :custom ;; It's not fun to be asked every time whether we want to delete a directory recursively. It's an understandable default for safety reasons, but because we are not deleting permanently but rather just moving to the trash, it's not such a concern. -(setopt dired-recursive-deletes 'always) + (dired-recursive-deletes 'always) ;; Recursive copying isn't even destructive, so i definitely don't want to be asked about that. -(setopt dired-recursive-copies 'always) + (dired-recursive-copies 'always) ;; After we delete some files or directories, it makes sense to get rid of any buffers which are looking at those files or directories. -(setopt dired-clean-up-buffers-too nil) + (dired-clean-up-buffers-too t) ;; With this set, if we have two dired buffers open next to one another, a rename operation in one will default to the directory shown in the other. In this way, we can pretend we are using some kind of norton commander like file browser instead of slumming it in emacs. -(setopt dired-dwim-target t) + (dired-dwim-target t) ;; These are some useful ls switches. We have to keep -l. To show dotfiles as well, we use -a. To sort numbers by number order instead of lumping together ones, twos, and so on, we use -v. Because we don't have colour, it's nice to have a clear indicator of what is a file and what is a directory, as well as other different things like symlinks which i never remember. By using -F, a forward slash is appended to every directory. And to get more easily understandable file sizes, we use -h, which will tell us the file size in kilobytes or megabytes rather than a huge number that means nothing to me. I won't explain the meaning of the long flag. -(setopt dired-listing-switches "-alvFh --group-directories-first") +(dired-listing-switches "-alvFh --group-directories-first") ;; By default, don't show dired details -(add-hook 'dired-mode-hook #'dired-hide-details-mode) +:hook (dired-mode . dired-hide-details-mode)) ;; I find it useful to see the recursive sizes of directories. This can be a little slow, so setting it as always on might not be the best idea, but the longest i've had to wait is about a second, and that's only if i run it on my home directory, so i think it's worth it at the moment. -;; (package-ensure 'dired-du) -(setopt dired-du-size-format t) -(add-hook 'dired-mode-hook #'dired-du-mode) +(use-package dired-du + :ensure t + :after dired + :custom + (dired-du-size-format t) + :hook (dired-mode . dired-du-mode)) ;; Some tramp settings. (setopt remote-file-name-inhibit-locks t) -(setopt tramp-inline-compress-start-size 1000) -(setopt tramp-verbose 3) +(use-package tramp + :defer t + :custom +(tramp-inline-compress-start-size 1000) +(tramp-verbose 3)) ;; (add-to-list 'tramp-remote-path 'tramp-own-remote-path) ;; The version control system will try each of these methods in order. Because almost everything source controlled i do uses git, i put it first in the list. But at the moment, because i don't think i actually use any of the other methods, i remove the rest of them from the list. -(setopt vc-handled-backends '(Git)) +(use-package vc-hooks + :after vc + :custom +(vc-handled-backends '(Git))) ;; (setopt vc-handled-backends '(Git RCS CVS SVN SCCS SRC Bzr Hg)) ;; It seems that tramp can also be made faster with these .ssh/config settings. @@ -452,10 +495,14 @@ The misspelled word is taken from OVERLAY. WORD is the corrected word." ;; Annotations for completing-read ;; Marginalia provides us with annotations for candidates in completing read functions. This is things like docstrings for functions, file permissions in find-file, and so on. It's a small quality of life improvement. ;; (package-ensure 'marginalia) -(setopt marginalia-mode t) +(use-package marginalia + :ensure t + :defer t + :custom + (marginalia-mode t) -;; We want to always show the relative age of a file. By default, files which haven't been modified for more than two weeks will display an absolute date. -(setopt marginalia-max-relative-age most-positive-fixnum) + ;; We want to always show the relative age of a file. By default, files which haven't been modified for more than two weeks will display an absolute date. + (marginalia-max-relative-age most-positive-fixnum)) ;; My keyboard has a tab key and an i key. For legacy reasons, by default emacs converts C-i to mean the same thing as the tab key, but i don't really want that. The tab key is called and it gets translated to TAB. C-i is TAB, but i'd rather it by C-i. That's what this decode line does. (define-key input-decode-map [?\C-i] [C-i]) @@ -463,35 +510,36 @@ The misspelled word is taken from OVERLAY. WORD is the corrected word." ;; Now that tab and C-i are properly distinguished, i can bind C-i to completion at point. (global-set-key (kbd "") 'completion-at-point) -;; I also want to make the completion at point function a bit more friendly than the default, so i ask consult to provide the completion functionality. -(setopt completion-in-region-function 'consult-completion-in-region) - ;; Minibuffer candidate completion ;; Vertico is a package for a nice minibuffer completion experience. It displays a vertical list of candidates. It integrates well with the emacs ecosystem and lets me use other packages that also play nicely. -;; (package-ensure 'vertico) -(setopt vertico-mode t) +(use-package vertico + :ensure t + :custom + (vertico-mode t) ;; We want vertico to take up a maximum of 12 lines on the display. My screen is quite small, so that's fine, but if i had a bigger screen, i might want to look into setting a percentage or increasing this. -(setopt vertico-count 12) + (vertico-count 12) ;; By default, vertico uses a font-face trick to put a horizontal line across group titles. It looks quite nice, but doesn't really conform to my design sensibilities, so here i redefine the group format to not have this. Because we no longer have the line, we also align the group name to the left edge. -(setopt vertico-group-format #("%s " 0 3 (face vertico-group-title))) + (vertico-group-format #("%s " 0 3 (face vertico-group-title))) ;; We also want to be able to jump to the bottom of the list by moving up from the top of the list, and the opposite. I've rarely made use of this functionality and i don't know if it's actually a best practice from an interaction perspective, but i'm going to keep it on until it causes an issue for me. -(setopt vertico-cycle t) + (vertico-cycle t)) ;; And of course, i want to be able to interact with vertico with the mouse. -(with-eval-after-load 'vertico - (setopt vertico-mouse-mode t)) +(use-package vertico-mouse + :after vertico + :custom (vertico-mouse-mode t)) ;; When completing a filename, i want to be able to easily delete directories in one fell swoop, instead of character by character or word by word. Usually C- would be fine, but if directories have a hyphen or space in their name, i have to press multiple times, which is almost never desirable. -(with-eval-after-load 'vertico - (bind-key (kbd "RET") #'vertico-directory-enter 'vertico-map) - (bind-key (kbd "") #'vertico-directory-delete-char 'vertico-map) - (bind-key (kbd "") #'vertico-directory-delete-word 'vertico-map)) - -;; If i type ~/ etc in a find-file prompt, get rid of the preceding directory names for a cleaner look. -(add-hook 'rfn-eshadow-update-overlay-hook #'vertico-directory-tidy) +(use-package vertico-directory + :after vertico + :bind (:map vertico-map + ("RET" . vertico-directory-enter) + ("" . vertico-directory-delete-char) + ("C-" . vertico-directory-delete-word)) + ;; If i type ~/ etc in a find-file prompt, get rid of the preceding directory names for a cleaner look. + :hook (rfn-eshadow-update-overlay . vertico-directory-tidy)) ;; Some settings for nicer completion with the default emacs completion buffer. I don't use this, because i use vertico. ;; (setopt completion-auto-help 'lazy @@ -557,7 +605,6 @@ The misspelled word is taken from OVERLAY. WORD is the corrected word." ;;; Keybindings ;; Zap up to char - (global-set-key (kbd "M-z") 'zap-up-to-char) ;; Insert date and time at point @@ -656,32 +703,38 @@ The misspelled word is taken from OVERLAY. WORD is the corrected word." :hook ((rmail-show-message . visual-line-fill-column-mode))) +(use-package message + :defer t + :init (defun noa/message-default-headers () (format "Fcc: ~/Documents/mail/outbox/%s.mbox" (format-time-string "%Y-%m"))) -(setopt message-default-headers #'noa/message-default-headers) -;; Composing mail +:custom +(message-default-headers #'noa/message-default-headers) + ;; Setting this to nil stops auto-fill from being automatically enabled in message buffers. -(setopt message-fill-column nil) +(message-fill-column nil) + +(user-full-name "noa") +(user-mail-address "noa@noa.pub") ;; It's nice to have a message signature. I want the signature to be loaded from a file, which is stored in my configuration directory. -(setopt message-signature t) -(setopt message-signature-file "~/.config/signature") +(message-signature t) +(message-signature-file "~/.config/signature") ;; Sending mail -(setopt message-send-mail-function 'message-send-mail-with-sendmail) -(add-to-list 'exec-path "/home/noa/.config/Scripts") -(setopt sendmail-program (executable-find "msmtpq")) +(message-send-mail-function 'message-send-mail-with-sendmail) +(sendmail-program (executable-find "msmtpq")) -(setopt message-sendmail-extra-arguments '("--read-envelope-from")) -(setopt message-sendmail-envelope-from 'header) -(setopt message-kill-buffer-on-exit t) -(setopt message-sendmail-f-is-evil t) -(setopt message-forward-as-mime t) -(setopt message-interactive t) +(message-sendmail-extra-arguments '("--read-envelope-from")) +(message-sendmail-envelope-from 'header) +(message-kill-buffer-on-exit t) +(message-sendmail-f-is-evil t) +(message-forward-as-mime t) +(message-interactive t) -(setopt message-auto-save-directory "~/Documents/mail/drafts") +(message-auto-save-directory "~/Documents/mail/drafts")) ;; Environment variables (setenv "PAGER" "cat") @@ -741,6 +794,7 @@ The misspelled word is taken from OVERLAY. WORD is the corrected word." ;;; Bibliography management (use-package ebib :ensure t + :defer t :custom (ebib-bibtex-dialect 'biblatex) (ebib-index-columns '(("Author/Editor" 40 t) -- cgit 1.4.1-2-gfad0