about summary refs log tree commit diff stats
path: root/config.org
diff options
context:
space:
mode:
Diffstat (limited to 'config.org')
-rw-r--r--config.org1022
1 files changed, 181 insertions, 841 deletions
diff --git a/config.org b/config.org index 493406c..a1bd3e6 100644 --- a/config.org +++ b/config.org
@@ -1,20 +1,42 @@
1#+TITLE: Emacs config 1#+TITLE: Emacs config
2#+AUTHOR: Case Duckworth 2#+AUTHOR: Case Duckworth
3# -*- encoding: utf-8-unix -*-
3#+BABEL: :cache yes 4#+BABEL: :cache yes
4#+PROPERTY: header-args :tangle init.el 5#+PROPERTY: header-args :tangle init.el
5#+OPTIONS: toc:nil 6#+OPTIONS: toc:nil
6#+BANKRUPTCY_COUNT: 1 7#+BANKRUPTCY_COUNT: 1.5
7 8
8* Preamble 9* Preamble
9 10
10I wanted to write my Emacs configuration in [[https://orgmode.org][Org mode]] for a while, but never could quite figure out how. Finally, I found [[https://github.com/larstvei/dot-emacs][Lars Tveito]]'s config, which does exactly what I want: =init.el= is small and simple, and replaced after the first run, and =init.org= is automatically tangled. So I'm very excited. 11** Inspiration
12
13I've been inspired by [[https://github.com/larstvei/dot-emacs][Lars Tveito]]'s config, which does exactly what I
14want: =init.el= is small and simple, and is replaced after the first
15run by the tangled contents of this file -- =config.org= -- which is
16furthermore automatically tangled.
17
18** Problems with this setup
19
20+ While =config.org= automatically tangles, I can't run =(load-file
21 init.el)= -- it results in an endless loop for some reason. I might
22 need to look into a hook of some kind.
11 23
12* License 24* License
13 25
14Copyright © 2020 Case Duckworth <acdw@acdw.net> 26Copyright © 2020 Case Duckworth <acdw@acdw.net>
15This work is free. You can redistribute it and/or modify it under the 27
16terms of the Do What The Fuck You Want To Public License, Version 2, 28This work is free. You can redistribute it and/or modify it under the
17as published by Sam Hocevar. See the LICENSE file, or below, for more details. 29terms of the Do What the Fuck You Want To Public License, Version 2,
30as published by Sam Hocevar. See the LICENSE file, or below, for more
31details.
32
33NOTE: the WTFPL is probably (most definitely!) not compatible with GNU
34Emacs's license, and I'm not sure, though I'm pretty confident, that
35my =config.org= would be classified as a /derivative work/ under those
36terms. Therefore, me licensing my =config.org= under the WTFPL is at
37best, unenforceable, and at worst, downright in violation of the GPL.
38
39SUE ME, RMS !!!
18 40
19#+begin_src text :tangle LICENSE 41#+begin_src text :tangle LICENSE
20 DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 42 DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
@@ -32,147 +54,187 @@ as published by Sam Hocevar. See the LICENSE file, or below, for more details.
32 54
33 0. You just DO WHAT THE FUCK YOU WANT TO. 55 0. You just DO WHAT THE FUCK YOU WANT TO.
34 56
35
36#+end_src 57#+end_src
37 58
38Probably that's not legal under the terms of the GPL or whatever Emacs is licensed under.
39SUE ME, RMS
40
41* Bootstrap 59* Bootstrap
42 60
43/Check out Lars's config for the reasoning behind this./ 61When this configuration is loaded for the first time, /this/ =init.el=
44 62is loaded:
45When this configuration is loaded for the first time, this ~init.el~ is loaded:
46 63
47#+BEGIN_SRC emacs-lisp :tangle no 64#+begin_src emacs-lisp :tangle no
48 ;; This file replaces itself with the actual configuration when first run. To keep only this version in git, run this command: 65 ;; This file replaces itself with the actual configuration when first
66 ;; run. To keep only this version tracked by git, run the command
67 ;;
49 ;; git update-index --assume-unchanged init.el 68 ;; git update-index --assume-unchanged init.el
50 ;; 69 ;;
51 ;; If it needs to be changed, start tracking it again thusly: 70 ;; If it needs to be changed, start tracking it again with the command
71 ;;
52 ;; git update-index --no-assume-unchanged init.el 72 ;; git update-index --no-assume-unchanged init.el
53 73 ;;
74 ;; edit as needed, and run the first command again.
54 (require 'org) 75 (require 'org)
55 (find-file (concat user-emacs-directory "init.org")) 76 (find-file (concat user-emacs-directory "config.org"))
56 (org-babel-tangle) 77 (org-babel-tangle)
57 (load-file (concat user-emacs-directory "early-init.el")) 78 (load-file (concat-user-emacs-directory "early-init.el"))
58 (load-file (concat user-emacs-directory "init.el")) 79 (load-file (concat-user-emacs-directory "init.el"))
59 (byte-compile-file (concat user-emacs-directory "init.el")) 80#+end_src
60#+END_SRC
61 81
62** Tangling 82** Tangling
63After the first run, the above ~init.el~ will be replaced by the tangled stuff here. However, when /this/ file is edited, we'll need to re-tangle everything. However, nobody has time to do that manually with =C-c C-v t=, /every time/! Luckily, Emacs is highly programmable. 83
84After first running Emacs with this config, the above snippet will be
85replaced by the result of tangling this file. However, when we edit
86=config.org=, we'll need to retangle it. The default keybinding to
87tangle is =C-c C-v t=, which takes a while and is easy to forget. So
88let's automatically tangle =config.org= on save.
64 89
65#+NAME: tangle-on-save 90#+NAME: tangle-on-save
66#+BEGIN_SRC emacs-lisp :tangle no 91#+begin_src emacs-lisp
92 ;;; init.el -*- lexical-binding: t; coding: utf-8-unix -*-
67 (defun acdw/tangle-init () 93 (defun acdw/tangle-init ()
68 "If the current buffer is `init.org', the code blocks are tangled, 94 "If the current buffer is `config.org', the code blocks are
69 and the tangled file is compiled and loaded." 95 tangled, and the tangled file is compiled and loaded."
70 (interactive) 96 (interactive)
71 (when (equal (buffer-file-name) 97 (let (config-org (expand-file-name
72 (expand-file-name 98 (concat user-emacs-directory "config.org")))
73 (concat user-emacs-directory "config.org"))) 99 (when (equal (buffer-file-name) config-org)
74 ;; Now with async! 100 (require 'async)
75 (require 'async) 101 (async-start
76 (async-start 102 `(lambda ()
77 `(lambda () 103 ;; Avoid running hooks when tangling.
78 ;; Avoid running hooks when tangling. 104 (let ((prog-mode-hook nil))
79 (let ((prog-mode-hook nil)) 105 (require 'org)
80 (require 'org) 106 (org-babel-tangle-file config-org)))
81 (org-babel-tangle-file 107 (lambda (_)
82 (expand-file-name 108 (message "Tangle complete."))))))
83 (concat user-emacs-directory "config.org"))))) 109
84 (lambda (_) 110 ;; Add a hook to tangle config.org.
85 (message "Tangle complete.")))))
86
87 (add-hook 'after-save-hook #'acdw/tangle-init) 111 (add-hook 'after-save-hook #'acdw/tangle-init)
88#+END_SRC 112#+end_src
89 113
90* Early initiation 114* Early initiation
91Emacs 27.1+ uses ~early-init.el~, which is evaluated before things like ~package.el~ and other stuff. So I have a few settings in there.
92 115
93** Preamble 116Emacs 27.1+ uses =early-init.el= /in addition to/ =init.el=, mostly
94Of course, first thing is the modeline. After that, I set ~load-prefer-newer~ because, well, it /should/. 117for settings related to packags. Since I use =straight.el= for
95#+BEGIN_SRC emacs-lisp :tangle early-init.el 118package management, I need to specify that in this file.
96 ;;; early-init.el -*- lexical-binding: t; no-byte-compile: t -*-
97
98(setq load-prefer-newer t)
99#+END_SRC
100
101** Computers
102I have to set these constants before bootstrapping the package manager, since ~straight.el~ depends on Git, and at work, those are in a weird place.
103 119
104#+BEGIN_SRC emacs-lisp :tangle early-init.el 120#+begin_src emacs-lisp :tangle early-init.el
105 (defconst *acdw/at-work* (eq system-type 'windows-nt)) 121 ;;; early-init.el -*- lexical-binding: t; no-byte-compile: t -*-
106 (defconst *acdw/at-larry* (string= (system-name) "larry")) 122 ;; DO NOT EDIT THIS FILE BY HAND. Edit =config.org= instead!
107 (defconst *acdw/at-bax* (string= (system-name) "bax"))
108 (defconst *acdw/at-home* (or *acdw/at-larry* *acdw/at-bax*))
109#+END_SRC
110 123
111** Package management 124 (setq load-prefer-newer t)
112 I've started using straight.el, which is great. It grabs packages from git, and apparently will let me fork and edit them, which I'll probably get around to ... eventually.
113 125
114*** At work, Git's in a weird place 126 (when (eq system-type 'windows-nt) ; I'm at work
115#+BEGIN_SRC emacs-lisp :tangle early-init.el
116 (when *acdw/at-work*
117 (add-to-list 'exec-path "~/bin") 127 (add-to-list 'exec-path "~/bin")
118 (add-to-list 'exec-path "C:/Users/aduckworth/Downloads/PortableGit/bin")) 128 (add-to-list 'exec-path
119#+END_SRC 129 "C:/Users/aduckworth/Downloads/PortableGit/bin"))
120 130
121*** [[https://github.com/raxod502/straight.el][straight.el]] 131 ;; This DOES NOT WORK on Windows.
122I don't know why, but for some reason the bootstrapping doesn't work on Windows. I have to download the repo directly from github and put it in the right place (=~/.emacs.d/straight/repos/straight.el/=). 132 ;; Download the repo directly from Github and unzip it into
133 ;; ~/.emacs.d/straight/repos/straight.el.
123 134
124#+BEGIN_SRC emacs-lisp :tangle early-init.el
125 (defvar bootstrap-version) 135 (defvar bootstrap-version)
126 (let ((bootstrap-file 136 (let ((bootstrap-file
127 (expand-file-name "straight/repos/straight.el/bootstrap.el" 137 (expand-file-name "straight/repos/straight.el/bootstrap.el"
128 user-emacs-directory)) 138 user-emacs-directory))
129 (bootstrap-version 5)) 139 (bootstrap-version 5))
130 (unless (file-exists-p bootstrap-file) 140 (unless (file-exists-p bootstrap-file)
131 (with-current-buffer 141 (with-current-buffer
132 (url-retrieve-synchronously 142 (url-retrieve-synchronously
133 "https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el" 143 "https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
134 'silent 'inhibit-cookies) 144 'silent 'inhibit-cookies)
135 (goto-char (point-max)) 145 (goto-char (point-max))
136 (eval-print-last-sexp))) 146 (eval-print-last-sexp)))
137 (load bootstrap-file nil 'nomessage)) 147 (load bootstrap-file nil 'nomessage))
138#+END_SRC
139 148
140*** [[https://github.com/jwiegley/use-package][use-package]] 149 ;; Use-package
141Yeah, you know it, I know it, we all love it. It's use-package. 150
142#+BEGIN_SRC emacs-lisp :tangle early-init.el
143 (setq straight-use-package-by-default t) 151 (setq straight-use-package-by-default t)
144 (straight-use-package 'use-package) 152 (straight-use-package 'use-package)
145#+END_SRC 153
146* Begin init.el 154 ;; Use-package extra keywords
147#+BEGIN_SRC emacs-lisp :noweb tangle 155
148 ;;; init.el -*- lexical-binding: t; coding: utf-8 -*- 156 (use-package use-package-custom-update
149 <<tangle-on-save>> 157 :straight (use-package-custom-update
150#+END_SRC 158 :host github
159 :repo "a13/use-package-custom-update"))
160
161#+end_src
162
151* Macros 163* Macros
164
152** cuss 165** cuss
153I like ~use-package~, but I don't like doing the weird "pseudo-package" stuff a lot of people do in their emacs configs. Partially because I have to set ~:straight nil~ on a lot of built-in packages, but also because I think being /that/ obsessive over one interface through the whole config is ... I don't know, short-sighted?
154 166
155Either way, I /do/ like the ~:custom~ interface that ~use-package~ has, so I've re-implemented it in my own macro. This way I don't have to worry about whether to ~setq~ or ~custom-set-variable~ or whatever. Just ~cuss~! 167I like =use-package= a lot, but I don't like the weird
156#+BEGIN_SRC emacs-lisp 168"pseudo-package" things you see with a lot of =use-package= setups
169around the Internet. They're cludgy, they /don't/ actually, in my
170opinion anyway, make the config any easier to read (how am I supposed
171to know what options are in =mule=, for example?!), and most
172importantly, =straight.el= doesn't really like them that much.
173
174*However*, I really like the =:custom= keyword in =use-package=,
175 enough to implement it as my own macro. =cuss= will automagically
176 call =custom-set-variable= or =setq=, whichever is best for the
177 variable being tweaked. I pulled this straight from =use-package=,
178 so I /know/ it works! :P
179
180#+begin_src emacs-lisp
157 (defmacro cuss (var val) 181 (defmacro cuss (var val)
158 "Basically `use-package''s `:custom', but without either." 182 "Basically the `:custom' macro from `use-package', by itself."
159 `(progn 183 `(progn
160 (funcall (or (get ',var 'custom-set) #'set-default) 184 (funcall (or (get ',var 'custom-set) #'set-default)
161 ',var ,val))) 185 ',var ,val)))
162#+END_SRC 186;;; test
187#+end_src
188
189* Machines
190
191I use Emacs on a couple of different computers: my two at home, and
192assorted Windows machines at work. I define a couple of constants to
193easily keep track of which computer I'm using.
194
195#+begin_src emacs-lisp
196 (defconst *acdw/at-work* (eq system-type 'windows-nt))
197
198 (defconst *acdw/at-larry* (string= (system-name) "larry"))
199 (defconst *acdw/at-bax* (string= (system-name) "bax"))
200 (defconst *acdw/at-home* (or *acdw/at-larry* *acdw/at-bax*))
201#+end_src
202
163* Files 203* Files
164** [[https://github.com/emacscollective/no-littering][Keep .emacs.d tidy]] 204
165#+BEGIN_SRC emacs-lisp 205** Keep .emacs.d tidy
166 (straight-use-package 'no-littering) 206
167 (require 'no-littering) 207 By default, Emacs keeps files all over the damn place. I like the
168#+END_SRC 208 =no-littering= package to keep files in one of two directories --
209 =etc/= and =var/=. I'm going to require it right away so that I can
210 immediately use it.
211
212 #+begin_src emacs-lisp
213 (use-package no-littering)
214 (require 'no-littering)
215 #+end_src
216
169** Customize 217** Customize
170I don't like the customize interface, but I still sometimes use it when I'm not sure what the name of a variable is. So I save the stuff to a file, I just don't load it or keep track of it. 218
171#+BEGIN_SRC emacs-lisp 219I don't use the customize interface -- but sometimes it's good to
220figure out what settings are available for a package. So I keep the
221customizations in a file (some people just throw it in =/dev/null=),
222but I /don't/ load the file.
223
224#+begin_src emacs-lisp
172 (cuss custom-file (no-littering-expand-etc-file-name "custom.el")) 225 (cuss custom-file (no-littering-expand-etc-file-name "custom.el"))
173#+END_SRC 226#+end_src
227
174** Encoding 228** Encoding
175#+BEGIN_SRC emacs-lisp 229
230It's 2020 -- let's use UTF-8 everywhere. Furthermore, even Notepad
231can figure out Unix line endings (=LF=) -- so let's only use that.
232
233I'm going to be perfectly honest here. I'm not sure what like, any of
234these do. I just threw everything =utf-8-unix= into a block and hope
235for the best.
236
237#+begin_src emacs-lisp
176 (prefer-coding-system 'utf-8-unix) 238 (prefer-coding-system 'utf-8-unix)
177 (set-default-coding-systems 'utf-8-unix) 239 (set-default-coding-systems 'utf-8-unix)
178 (set-terminal-coding-system 'utf-8-unix) 240 (set-terminal-coding-system 'utf-8-unix)
@@ -181,753 +243,31 @@ I don't like the customize interface, but I still sometimes use it when I'm not
181 (set-file-name-coding-system 'utf-8-unix) 243 (set-file-name-coding-system 'utf-8-unix)
182 (set-clipboard-coding-system 'utf-8-unix) 244 (set-clipboard-coding-system 'utf-8-unix)
183 (set-buffer-file-coding-system 'utf-8-unix) 245 (set-buffer-file-coding-system 'utf-8-unix)
184 (cuss locale-coding-system 'utf-8) 246 (cuss locale-coding-system 'utf-8-unix)
185 (cuss x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING)) 247 (cuss x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING))
186#+END_SRC
187** Recent files
188#+BEGIN_SRC emacs-lisp
189 (use-package recentf
190 :config
191 (add-to-list 'recentf-exclude no-littering-var-directory)
192 (add-to-list 'recentf-exclude no-littering-etc-directory)
193 :custom
194 (recentf-max-menu-items 100)
195 (recentf-max-saved-items 100)
196 :config
197 (recentf-mode 1))
198#+END_SRC
199** Backups
200#+BEGIN_SRC emacs-lisp
201 (cuss backup-directory-alist
202 `((".*" . ,(no-littering-expand-var-file-name "backup/"))))
203#+END_SRC
204** [[https://github.com/bbatsov/super-save][Autosave]]
205#+BEGIN_SRC emacs-lisp
206 (use-package super-save
207 :custom
208 (auto-save-default nil)
209 (super-save-exclude '(".gpg"))
210 :config
211 (super-save-mode 1))
212#+END_SRC
213** [[https://www.emacswiki.org/emacs/SavePlace][Save places]]
214#+BEGIN_SRC emacs-lisp
215 (use-package saveplace
216 :custom
217 (save-place-file (no-littering-expand-var-file-name "places"))
218 (save-place-forget-unreadable-files (not *acdw/at-work*))
219 :config
220 (save-place-mode 1))
221#+END_SRC
222** [[https://www.emacswiki.org/emacs/SaveHist][Save history]]
223#+BEGIN_SRC emacs-lisp
224 (use-package savehist
225 :custom
226 (savehist-addtional-variables
227 '(kill-ring
228 search-ring
229 regexp-search-ring))
230 (savehist-save-minibuffer-history t)
231 :config
232 (savehist-mode 1))
233#+END_SRC
234* User interface
235** Look
236*** Frames and windows
237**** Frame defaults
238#+BEGIN_SRC emacs-lisp
239 (cuss default-frame-alist '((tool-bar-lines . 0)
240 (menu-bar-lines . 0)
241 (vertical-scroll-bars . nil)
242 (horizontal-scroll-bars . nil)
243 (right-divider-width . 2)
244 (bottom-divider-width . 2)
245 (left-fringe-width . 2)
246 (right-fringe-width . 2)))
247
248 ;; also disable these with modes, so I can re-enable them more easily
249 (menu-bar-mode -1)
250 (tool-bar-mode -1)
251 (scroll-bar-mode -1)
252#+END_SRC
253**** Resizing
254#+BEGIN_SRC emacs-lisp
255 (cuss frame-resize-pixelwise t)
256 (cuss window-combination-resize t)
257#+END_SRC
258*** Buffers
259#+BEGIN_SRC emacs-lisp
260 (cuss uniquify-buffer-name-style 'forward)
261
262 (cuss indicate-buffer-boundaries
263 '((top . right)
264 (bottom . right)
265 (t . nil)))
266#+END_SRC
267**** Startup buffer
268#+BEGIN_SRC emacs-lisp
269 (cuss inhibit-startup-buffer-menu t)
270 (cuss inhibit-startup-screen t)
271 (cuss initial-buffer-choice t) ; start in *scratch*
272 (cuss initial-scratch-message nil)
273#+END_SRC
274*** Cursor
275#+BEGIN_SRC emacs-lisp
276 (cuss cursor-type 'bar)
277 (cuss cursor-in-non-selected-windows 'hollow)
278 (blink-cursor-mode 0)
279#+END_SRC
280*** Interactivity
281**** Mouse
282#+BEGIN_SRC emacs-lisp
283 (cuss mouse-yank-at-point t)
284#+END_SRC
285**** Dialogs
286#+BEGIN_SRC emacs-lisp
287 (cuss use-dialog-box nil)
288#+END_SRC
289**** Disabled functions
290#+BEGIN_SRC emacs-lisp
291 (cuss disabled-command-function nil)
292#+END_SRC
293**** Function aliases
294#+begin_src emacs-lisp
295 (fset 'yes-or-no-p #'y-or-n-p)
296#+end_src
297*** Miscellaneous
298**** Convert =^L= to a line
299#+begin_src emacs-lisp
300 (use-package form-feed
301 :hook
302 ((text-mode prog-mode) . form-feed-mode))
303#+end_src 248#+end_src
304** Themes: [[https://github.com/protesilaos/modus-themes][Modus]]
305#+BEGIN_SRC emacs-lisp
306 (use-package modus-operandi-theme)
307 (use-package modus-vivendi-theme)
308#+END_SRC
309*** [[https://github.com/hadronzoo/theme-changer][Change themes]] based on time of day
310#+BEGIN_SRC emacs-lisp
311 (use-package theme-changer
312 :init
313 (setq calendar-location-name "Baton Rouge, LA"
314 calendar-latitude 30.39
315 calendar-longitude -91.83)
316 :config
317 (change-theme 'modus-operandi 'modus-vivendi))
318#+END_SRC
319*** Disable the current theme when a theme is interactively loaded
320This doesn't happen often, but I'll be ready when it does.
321#+begin_src emacs-lisp
322 (defadvice load-theme
323 (before disable-before-load (theme &optional no-confirm no-enable) activate)
324 (mapc 'disable-theme custom-enabled-themes))
325#+end_src
326** Modeline: [[https://github.com/Malabarba/smart-mode-line][smart-mode-line]]
327#+BEGIN_SRC emacs-lisp
328 (use-package smart-mode-line
329 :config
330 (sml/setup))
331#+END_SRC
332 249
333I hide all minor-modes by default for a clean modeline. However, I can add them back by adding them to the whitelist with ~(add-to-list 'rm-whitelist " REGEX")~. 250** Recent files
334#+BEGIN_SRC emacs-lisp
335 (defun rm-whitelist-add (regexp)
336 "Add a regexp to the whitelist."
337 (add-to-list 'rm--whitelist-regexps regexp)
338 (setq rm-whitelist
339 (mapconcat 'identity rm--whitelist-regexps "\\|")))
340 251
341 (setq rm--whitelist-regexps '("^$")) 252Though I haven't used this feature ... yet, maybe if I use the =C-x
253C-r= binding that is suggested (like /everywhere/), it'll be easier
254for me to use.
342 255
343 (use-package rich-minority 256I'm putting =recentf= in a =use-package= declaration, by the way,
344 :custom 257because even though it's a part of Emacs, it's conveniently in its own
345 (rm-whitelist 258package.
346 (mapconcat 'identity rm--whitelist-regexps "\\|")))
347#+END_SRC
348** Fonts
349I'm sure there's a better way to do this, but for now, this is the best I've got. I append to the ~face-font-family-alternatives~ because I don't know what kind of weird magic they're doing in there.
350#+BEGIN_SRC emacs-lisp
351 (cuss face-font-family-alternatives
352 '(("Monospace" "courier" "fixed")
353 ("Monospace Serif" "Courier 10 Pitch" "Consolas" "Courier Std" "FreeMono" "Nimbus Mono L" "courier" "fixed")
354 ("courier" "CMU Typewriter Text" "fixed")
355 ("Sans Serif" "helv" "helvetica" "arial" "fixed")
356 ("helv" "helvetica" "arial" "fixed")
357 ;; now mine
358 ("FixedPitch" "Go Mono" "DejaVu Sans Mono" "Consolas" "fixed")
359 ("VariablePitch" "Go" "DejaVu Sans" "Georgia" "fixed")))
360
361 (set-face-attribute 'default nil
362 :family "FixedPitch"
363 :height 140)
364
365 (set-face-attribute 'fixed-pitch nil
366 :family "FixedPitch"
367 :height 140)
368
369 (set-face-attribute 'variable-pitch nil
370 :family "VariablePitch"
371 :height 150)
372#+END_SRC
373*** Ligatures
374These cause big problems with cc-mode (as in, totally freezing everything), so I'm going to comment it out.
375#+begin_src emacs-lisp
376 ;; (use-package ligature
377 ;; :straight (ligature
378 ;; :host github
379 ;; :repo "mickeynp/ligature.el")
380 ;; :config
381 ;; (ligature-set-ligatures 'prog-mode
382 ;; '("++" "--" "/=" "&&" "||" "||="
383 ;; "->" "=>" "::" "__"
384 ;; "==" "===" "!=" "=/=" "!=="
385 ;; "<=" ">=" "<=>"
386 ;; "/*" "*/" "//" "///"
387 ;; "\\n" "\\\\"
388 ;; "<<" "<<<" "<<=" ">>" ">>>" ">>="
389 ;; "|=" "^="
390 ;; "**" "--" "---" "----" "-----"
391 ;; "==" "===" "====" "====="
392 ;; "</" "<!--" "</>" "-->" "/>"
393 ;; ":=" "..." ":>" ":<" ">:" "<:"
394 ;; "::=" ;; add others here
395 ;; ))
396 ;; :config
397 ;; (global-ligature-mode))
398#+end_src
399*** [[https://github.com/rolandwalker/unicode-fonts][Unicode fonts]]
400#+BEGIN_SRC emacs-lisp
401 (use-package persistent-soft)
402 259
403 (use-package unicode-fonts
404 :after persistent-soft
405 :config
406 (unicode-fonts-setup))
407
408#+END_SRC
409* Editing
410** Completion
411I was using company, but I think it might've been causing issues with ~awk-mode~, so I'm trying ~hippie-mode~ right now. So far, I'm also enjoying not having a popup all the time.
412#+BEGIN_SRC emacs-lisp
413 (bind-key "M-/" #'hippie-expand)
414#+END_SRC
415** Ignore case
416#+BEGIN_SRC emacs-lisp
417 (cuss completion-ignore-case t)
418 (cuss read-buffer-completion-ignore-case t)
419 (cuss read-file-name-completion-ignore-case t)
420#+END_SRC
421** Selection & Minibuffer
422*** Selectrum & Prescient
423#+begin_src emacs-lisp
424 (use-package selectrum
425 :config
426 (selectrum-mode +1))
427
428 (use-package prescient
429 :config
430 (prescient-persist-mode +1))
431
432 (use-package selectrum-prescient
433 :after (selectrum prescient)
434 :config
435 (selectrum-prescient-mode +1))
436#+end_src
437** Search
438*** CtrlF for searching
439#+BEGIN_SRC emacs-lisp
440 (use-package ctrlf
441 :custom
442 (ctrlf-show-match-count-at-eol nil)
443 :config
444 (ctrlf-mode +1)
445 :bind
446 ("C-s" . ctrlf-forward-regexp))
447#+END_SRC
448*** [[https://github.com/benma/visual-regexp.el][Visual Regexp]]
449#+begin_src emacs-lisp 260#+begin_src emacs-lisp
450 (use-package visual-regexp 261 (use-package recentf
451 :bind 262 :custom-update
452 ([remap query-replace] . 'vr/query-replace)) 263 (recentf-exclude
453#+end_src 264 (no-littering-var-directory
454** Undo 265 no-littering-etc-directory))
455#+BEGIN_SRC emacs-lisp
456 (use-package undo-fu
457 :bind
458 ("C-/" . undo-fu-only-undo)
459 ("C-?" . undo-fu-only-redo))
460
461 (use-package undo-fu-session
462 :after no-littering
463 :custom 266 :custom
464 (undo-fu-session-incompatible-files 267 (recentf-max-menu-items 100)
465 '("/COMMIT_EDITMSG\\'" 268 (recentf-max-saved-items 100)
466 "/git-rebase-todo\\'"))
467 (undo-fu-session-directory
468 (no-littering-expand-var-file-name "undos/"))
469 :config
470 (global-undo-fu-session-mode +1))
471#+END_SRC
472** Visual editing
473*** ~zap-to-char~ replacement
474#+BEGIN_SRC emacs-lisp
475 (use-package zop-to-char
476 :bind
477 ([remap zap-to-char] . zop-to-char)
478 ([remap zap-up-to-char] . zop-up-to-char))
479#+END_SRC
480*** Operate on a line if there's no current region
481#+BEGIN_SRC emacs-lisp
482 (use-package whole-line-or-region
483 :config
484 (whole-line-or-region-global-mode +1))
485#+END_SRC
486*** Expand-region
487#+BEGIN_SRC emacs-lisp
488 (use-package expand-region
489 :bind
490 ("C-=" . er/expand-region)
491 ("C-+" . er/contract-region))
492#+END_SRC
493*** Volatile highlights
494#+BEGIN_SRC emacs-lisp
495 (use-package volatile-highlights
496 :config
497 (volatile-highlights-mode 1))
498#+END_SRC
499*** Visual line mode
500#+BEGIN_SRC emacs-lisp
501 (global-visual-line-mode 1)
502#+END_SRC
503*** A better ~move-beginning-of-line~
504#+BEGIN_SRC emacs-lisp
505 (defun my/smarter-move-beginning-of-line (arg)
506 "Move point back to indentation of beginning of line.
507
508 Move point to the first non-whitespace character on this line.
509 If point is already there, move to the beginning of the line.
510 Effectively toggle between the first non-whitespace character and
511 the beginning of the line.
512
513 If ARG is not nil or 1, move forward ARG - 1 lines first. If
514 point reaches the beginning or end of the buffer, stop there."
515 (interactive "^p")
516 (setq arg (or arg 1))
517
518 ;; Move lines first
519 (when (/= arg 1)
520 (let ((line-move-visual nil))
521 (forward-line (1- arg))))
522
523 (let ((orig-point (point)))
524 (back-to-indentation)
525 (when (= orig-point (point))
526 (move-beginning-of-line 1))))
527
528 (bind-key "C-a" #'my/smarter-move-beginning-of-line)
529#+END_SRC
530** Delete the selection when typing
531#+BEGIN_SRC emacs-lisp
532 (delete-selection-mode 1)
533#+END_SRC
534** Clipboard
535#+BEGIN_SRC emacs-lisp
536 (cuss save-interprogram-paste-before-kill t)
537#+END_SRC
538** Tabs & Spaces
539#+BEGIN_SRC emacs-lisp
540 (cuss sentence-end-double-space t)
541
542 ;; cf https://dougie.io/emacs/indentation/
543 ;; Create a variable for our preferred tab width
544 (setq custom-tab-width 4)
545
546 ;; Two callable functions for enabling/disabling tabs in Emacs
547 (defun disable-tabs () (setq indent-tabs-mode nil))
548 (defun enable-tabs ()
549 (setq indent-tabs-mode t)
550 (setq tab-width custom-tab-width))
551
552 ;; Hooks to Enable Tabs
553 (add-hook 'prog-mode-hook 'enable-tabs)
554 ;; Hooks to Disable Tabs
555 (add-hook 'lisp-mode-hook 'disable-tabs)
556 (add-hook 'emacs-lisp-mode-hook 'disable-tabs)
557
558 ;; Language-Specific Tweaks
559 (setq-default python-indent-offset custom-tab-width) ;; Python
560 (setq-default js-indent-level custom-tab-width) ;; Javascript
561
562 ;; Make the backspace properly erase the tab instead of
563 ;; removing 1 space at a time.
564 (setq backward-delete-char-untabify-method 'hungry)
565
566 ;; WARNING: This will change your life
567 ;; (OPTIONAL) Visualize tabs as a pipe character - "|"
568 ;; This will also show trailing characters as they are useful to spot.
569 (setq whitespace-style '(face tabs tab-mark trailing))
570 (custom-set-faces
571 '(whitespace-tab ((t (:foreground "#636363")))))
572 (setq whitespace-display-mappings
573 '((tab-mark 9 [124 9] [92 9]))) ; 124 is the ascii ID for '\|'
574 (global-whitespace-mode) ; Enable whitespace mode everywhere
575
576 (use-package smart-tabs-mode
577 :init
578 (smart-tabs-insinuate 'c 'javascript))
579#+END_SRC
580* Programming
581** Git
582#+BEGIN_SRC emacs-lisp
583 (use-package magit
584 :bind 269 :bind
585 ("C-x g" . magit-status) 270 ("C-x C-r" . recentf-open-files)
586 :config
587 (add-to-list 'magit-no-confirm 'stage-all-changes))
588
589 ;; hook into `prescient'
590 (define-advice magit-list-refs
591 (:around (orig &optional namespaces format sortby)
592 prescient-sort)
593 "Apply prescient sorting when listing refs."
594 (let ((res (funcall orig namespaces format sortby)))
595 (if (or sortby
596 magit-list-refs-sortby
597 (not selectrum-should-sort-p))
598 res
599 (prescient-sort res))))
600
601 (when (executable-find "cmake")
602 (use-package libgit)
603 (use-package magit-libgit))
604
605 (use-package forge
606 :after magit
607 :custom
608 (forge-owned-accounts '(("duckwork"))))
609#+END_SRC
610** Code display
611#+BEGIN_SRC emacs-lisp
612 (add-hook 'prog-mode-hook #'prettify-symbols-mode)
613#+END_SRC
614*** Parentheses
615#+BEGIN_SRC emacs-lisp
616 (cuss show-paren-style 'mixed)
617 (show-paren-mode +1)
618
619 (use-package smartparens
620 :init
621 (defun acdw/setup-smartparens ()
622 (require 'smartparens-config)
623 (smartparens-mode +1))
624 :hook
625 (prog-mode . acdw/setup-smartparens))
626
627 (use-package rainbow-delimiters
628 :hook
629 (prog-mode . rainbow-delimiters-mode))
630#+END_SRC
631** Line numbers
632#+BEGIN_SRC emacs-lisp
633 (add-hook 'prog-mode-hook
634 (if (and (fboundp 'display-line-numbers-mode)
635 (display-graphic-p))
636 #'display-line-numbers-mode
637 #'linum-mode))
638#+END_SRC
639** Languages
640*** Shell
641#+begin_src emacs-lisp
642 (use-package shfmt
643 :custom
644 (shfmt-arguments '("-i" "4" "-ci"))
645 :hook
646 (sh-mode . shfmt-on-save-mode))
647
648 ;; fish
649 (use-package fish-mode)
650#+end_src
651*** Lua
652#+BEGIN_SRC emacs-lisp
653 (use-package lua-mode
654 :mode "\\.lua\\'"
655 :interpreter "lua")
656#+END_SRC
657*** Fennel
658#+BEGIN_SRC emacs-lisp
659 (use-package fennel-mode
660 :mode "\\.fnl\\'")
661#+END_SRC
662*** Web
663#+BEGIN_SRC emacs-lisp
664 (use-package web-mode
665 :custom
666 (web-mode-markup-indent-offset 2)
667 (web-mode-code-indent-offset 2)
668 (web-mode-css-indent-offset 2)
669 :mode (("\\.ts\\'" . web-mode)
670 ("\\.html?\\'" . web-mode)
671 ("\\.css?\\'" . web-mode)
672 ("\\.js\\'" . web-mode)))
673#+END_SRC
674*** SSH config
675#+begin_src emacs-lisp
676 (use-package ssh-config-mode)
677#+end_src
678*** Lisp (SLIME)
679#+begin_src emacs-lisp
680 (use-package slime
681 :when (executable-find "sbcl")
682 :custom
683 (inferior-lisp-program "sbcl")
684 (slime-contribs '(slime-fancy))
685 ;;:config
686 ;;(load (expand-file-name "~/.quicklisp/slime-helper.el"))
687 )
688#+end_src
689* Writing
690** Word count
691#+begin_src emacs-lisp
692 (use-package wc-mode
693 :config
694 (rm-whitelist-add "WC")
695 :hook
696 (text-mode . wc-mode))
697#+end_src
698** Visual fill column
699#+begin_src emacs-lisp
700 (use-package visual-fill-column
701 :custom
702 (split-window-preferred-function 'visual-fill-column-split-window-sensibly)
703 (visual-fill-column-center-text t)
704 (fill-column 80)
705 :config
706 (advice-add 'text-scale-adjust
707 :after #'visual-fill-column-adjust)
708 :hook
709 (org-mode . visual-fill-column-mode))
710#+end_src
711** Org mode
712#+begin_src emacs-lisp
713 (use-package org
714 :custom
715 (org-startup-indented t)
716 (org-src-tab-acts-natively t)
717 (org-hide-emphasis-markers t)
718 (org-fontify-done-headline t)
719 (org-hide-leading-stars t)
720 (org-pretty-entities t)
721 (org-src-window-setup 'current-window)
722 :hook
723 (org-mode . variable-pitch-mode))
724
725 (use-package org-superstar
726 :hook
727 (org-mode . org-superstar-mode))
728#+end_src
729*** Org export to gemini
730#+begin_src emacs-lisp
731 (use-package ox-gemini
732 :straight (ox-gemini
733 :repo "https://git.sr.ht/~abrahms/ox-gemini"
734 :branch "main"))
735#+end_src
736* Applications
737** Gemini & Gopher
738#+BEGIN_SRC emacs-lisp
739 (use-package elpher
740 :straight (elpher
741 :repo "git://thelambdalab.xyz/elpher.git")
742 :custom
743 (elpher-certificate-directory
744 (no-littering-expand-var-file-name "elpher-certificates/"))
745 (elpher-ipv4-always t)
746 :config
747 (defun elpher:eww-browse-url (original url &optional new-window)
748 "Handle gemini/gopher links with eww."
749 (cond ((string-match-p "\\`\\(gemini\\|gopher\\)://" url)
750 (require 'elpher)
751 (elpher-go url))
752 (t (funcall original url new-window))))
753 (advice-add 'eww-browse-url :around 'elpher:eww-browse-url)
754 :bind (:map elpher-mode-map
755 ("n" . elpher-next-link)
756 ("p" . elpher-prev-link)
757 ("o" . elpher-follow-current-link)
758 ("G" . elpher-go-current))
759 :hook
760 (elpher-mode . visual-fill-column-mode))
761
762 (use-package gemini-mode
763 :straight (gemini-mode
764 :repo "https://git.carcosa.net/jmcbray/gemini.el.git")
765 :mode "\\.\\(gemini|gmi\\)\\'"
766 :hook
767 (gemini-mode . visual-fill-column-mode))
768
769 (use-package gemini-write
770 :straight (gemini-write
771 :repo "https://alexschroeder.ch/cgit/gemini-write"))
772
773 (use-package post-to-gemlog-blue
774 :straight (post-to-gemlog-blue
775 :repo "https://git.sr.ht/~acdw/post-to-gemlog-blue.el"))
776#+END_SRC
777** Pastebin
778#+BEGIN_SRC emacs-lisp
779 (use-package 0x0
780 :custom
781 (0x0-default-service 'ttm))
782#+END_SRC
783** Gnus
784#+begin_src emacs-lisp
785 (cuss gnus-select-method
786 '(nnimap "imap.fastmail.com"
787 (nnimap-inbox "INBOX")
788 (nnimap-split-methods default)
789 (nnimap-expunge t)
790 (nnimap-stream ssl)))
791
792 (cuss gnus-secondary-select-methods
793 '((nntp "news.gwene.org")))
794#+end_src
795** Nov.el: read Ebooks
796#+begin_src emacs-lisp
797 (use-package nov
798 :mode ("\\.epub\\'" . nov-mode)
799 :custom
800 (nov-text-width t)
801 :hook
802 (nov-mode . visual-line-mode)
803 (nov-mode . visual-fill-column-mode))
804#+end_src
805** Circe: IRC
806Commented for now while I figure out exactly what I want from IRC, et al.
807#+begin_src emacs-lisp
808 ;; (cuss auth-sources '("~/.authinfo"))
809
810 ;; (defun acdw/fetch-password (&rest params)
811 ;; (require 'auth-source)
812 ;; (let ((match (car (apply 'auth-source-search params))))
813 ;; (if match
814 ;; (let ((secret (plist-get match :secret)))
815 ;; (if (functionp secret)
816 ;; (funcall secret)
817 ;; secret))
818 ;; (error "Password not found for %S" params))))
819
820 ;; (defun acdw/nickserv-password (nick server)
821 ;; (acdw/fetch-password :login nick :machine server))
822
823 ;; (defun acdw/setup-lui ()
824 ;; (interactive)
825 ;; (setq right-margin-width 5)
826 ;; (setq fringes-outside-margins t)
827 ;; (setq word-wrap t)
828 ;; (setq wrap-prefix " ")
829 ;; (setf (cdr (assoc 'continuation fringe-indicator-alist)) nil))
830
831 ;; (defun acdw/circe-prompt ()
832 ;; (lui-set-prompt
833 ;; (concat (propertize (concat (buffer-name) ">")
834 ;; 'face 'circe-prompt-face)
835 ;; " ")))
836
837 ;; (use-package circe
838 ;; :init
839 ;; (defun acdw/setup-circe ()
840 ;; (whitespace-mode -1)
841 ;; (enable-lui-autopaste))
842 ;; :custom
843 ;; (circe-default-part-message "Peace out, cub scouts")
844 ;; (circe-default-quit-message "See You Space Cowpokes....")
845 ;; (circe-default-realname "Case")
846 ;; (circe-highlight-nick-type 'all)
847 ;; (circe-reduce-lurker-spam t)
848 ;; (circe-format-say "{nick:-15s}| {body}")
849 ;; (circe-format-self-say "{nick:-15s}> {body}")
850 ;; (circe-format-action " * {nick} {body}")
851 ;; (circe-format-message " *{nick}* {body}")
852 ;; (circe-format-message-action " * *{nick}* {body}")
853 ;; (circe-format-self-action " * {nick} {body}")
854 ;; (circe-use-cycle-completion t)
855 ;; (circe-channel-killed-confirmation nil)
856 ;; (circe-color-nicks-everywhere t)
857 ;; (circe-default-nick "acdw")
858 ;; (circe-default-user "acdw")
859 ;; (circe-server-auto-join-default-type :after-auth)
860 ;; (lui-time-stamp-position 'right-margin)
861 ;; (lui-fill-type nil)
862 ;; (lui-time-stamp-format "%H:%M")
863 ;; (lui-track-bar-behavior 'before-switch-to-buffer)
864 ;; (circe-network-options
865 ;; `(("Freenode"
866 ;; :tls t
867 ;; :host "irc.acdw.net"
868 ;; :port 16789
869 ;; :nick "acdw"
870 ;; :sasl-username "acdw"
871 ;; :sasl-password "freenode:purple-mountains-majesty"
872 ;; :channels ("#emacs"))
873 ;; ("Tilde.chat"
874 ;; :tls t
875 ;; :host "irc.acdw.net"
876 ;; :port 16789
877 ;; :nick "acdw"
878 ;; :sasl-username "acdw"
879 ;; :sasl-password "tilde.chat:purple-mountains-majesty"
880 ;; :channels ("#gemini" "#meta" "#team" "#bread"))))
881 ;; :custom-face
882 ;; (circe-highlight-nick-face ((t (:inherit bold))))
883 ;; (circe-originator-face ((t (:weight bold))))
884 ;; (circe-prompt-face ((t (:foreground "blue"))))
885 ;; (lui-time-stamp-face ((t (:foreground "#808080" :height 0.8))))
886 ;; :config
887 ;; (enable-lui-track-bar)
888 ;; (enable-circe-color-nicks)
889 ;; (enable-circe-display-images)
890 ;; :hook
891 ;; (circe-channel-mode . acdw/setup-circe)
892 ;; (circe-chat-mode . acdw/circe-prompt)
893 ;; (lui-mode . acdw/setup-lui))
894#+end_src
895** Elfeed: Feed reader
896Elfeed keeps freezing emacs. I'm commenting this for now.
897#+begin_src emacs-lisp
898 ;; (use-package elfeed
899 ;; :custom
900 ;; (elfeed-feeds
901 ;; '(("https://acdw.net/atom.xml" me)
902 ;; ("https://planet.emacslife.com/atom.xml" emacs programming blog)
903 ;; ("https://www.xkcd.com/rss.xml" comics)
904 ;; ("https://portal.mozz.us/gemini/breadpunk.club/~bakersdozen/gemlog/atom.xml" friends)
905 ;; ("https://kotobank.ch/~vaartis/rss.xml" friends)
906 ;; ("https://m455.casa/feed.rss" friends)
907 ;; ("https://eli.li/feed.rss" friends)
908 ;; ("http://len.falken.ink/" friends)
909 ;; ("https://cadence.moe/blog/atom.xml?limit=30" friends)
910 ;; ("https://benjaminwil.info/feed.xml" friends)
911 ;; ("https://www.5snb.club/rss.xml" friends)
912 ;; ("https://write.lain.faith/@/haskal/atom.xml" friends)
913 ;; ("https://p1k3.com/feed" friends)
914 ;; )))
915#+end_src
916* Machine-specific configurations
917#+begin_src emacs-lisp
918 (use-package su
919 :when *acdw/at-home*
920 :config 271 :config
921 (su-mode 1)) 272 (recentf-mode 1))
922
923 (use-package trashed
924 :when *acdw/at-home*
925 :custom
926 (delete-by-moving-to-trash t))
927
928 (use-package exec-path-from-shell
929 :when *acdw/at-home*
930 :demand
931 :config
932 (exec-path-from-shell-initialize))
933#+end_src 273#+end_src