about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--init.el262
-rw-r--r--init.org587
3 files changed, 599 insertions, 252 deletions
diff --git a/.gitignore b/.gitignore index 993a79e..cd10faf 100644 --- a/.gitignore +++ b/.gitignore
@@ -1,5 +1,5 @@
1* 1*
2!early-init.el 2!init.org
3!init.el 3!init.el
4!.gitignore 4!.gitignore
5!README.org 5!README.org
diff --git a/init.el b/init.el index ab596b6..52fc593 100644 --- a/init.el +++ b/init.el
@@ -1,251 +1,11 @@
1;;; init.el -*- lexical-binding: t; coding: utf-8; -*- 1 ;; This file replaces itself with the actual configuration when first run. To keep only this version in git, run this command:
2 2 ;; git update-index --assume-unchanged init.el
3;;; Commentary: 3 ;;
4;; BANKRUPT_SCORE: 1 4 ;; If it needs to be changed, start tracking it again thusly:
5;; ^ the number of times I've declared Emacs bankruptcy. 5 ;; git update-index --no-assume-unchanged init.el
6;; Does this mean I'm part of the cool kids now? 6
7 7 (require 'org)
8;;; Macros 8 (find-file (concat user-emacs-directory "init.org"))
9(defmacro cuss (var val) 9 (org-babel-tangle)
10 "Basically `use-package' `:custom' but without either." 10 (load-file (concat user-emacs-directory "init.el"))
11 `(progn 11 (byte-compile-file (concat user-emacs-directory "init.el"))
12 (funcall (or (get ',var 'custom-set) #'set-default)
13 ',var ,val)))
14
15;;; Files
16;; keep `emacs-user-directory' tidy
17(use-package no-littering)
18
19;; don't clutter `init.el' with customize crap
20(cuss custom-file (no-littering-expand-etc-file-name "custom.el"))
21
22;; backups
23(cuss backup-directory-alist
24 `((".*" . ,(no-littering-expand-var-file-name "backup/"))))
25
26;; recent files
27(use-package recentf
28 :config
29 (add-to-list 'recentf-exclude no-littering-var-directory)
30 (add-to-list 'recentf-exclude no-littering-etc-directory)
31 :custom
32 (recentf-max-menu-items 100)
33 (recentf-max-saved-items 100)
34 :config
35 (recentf-mode +1))
36
37;; encoding
38(set-charset-priority 'unicode)
39(set-language-environment "UTF-8")
40(set-default-coding-systems 'utf-8)
41(set-terminal-coding-system 'utf-8)
42(set-keyboard-coding-system 'utf-8)
43(set-selection-coding-system 'utf-8)
44(prefer-coding-system 'utf-8)
45
46;;; Save/Restore
47;; autosave, but like, better
48(use-package super-save
49 :custom
50 (auto-save-default nil)
51 (super-save-auto-save-when-idle t)
52 (super-save-exclude '(".gpg"))
53 :config
54 (super-save-mode +1))
55
56;; save places in files
57(use-package saveplace
58 :custom
59 (save-place-file (no-littering-expand-var-file-name "places"))
60 :config
61 (save-place-mode +1))
62
63;; save history of variables
64(use-package savehist
65 :custom
66 (savehist-additional-variables
67 '(kill-ring
68 search-ring
69 regexp-search-ring))
70 :config
71 (savehist-mode +1))
72
73;;; Buffers
74;; uniquely name buffers
75(cuss uniquify-buffer-name-style 'forward)
76
77;;; UI
78;; frame defaults
79(cuss default-frame-alist '((tool-bar-lines . 0)
80 (menu-bar-lines . 0)
81 (vertical-scroll-bars . nil)
82 (horizontal-scroll-bars . nil)
83 (right-divider-width . 2)
84 (bottom-divider-width . 2)
85 (left-fringe-width . 2)
86 (right-fringe-width . 2)))
87
88;; also disable these with modes, so I can re-enable them more easily
89(menu-bar-mode -1)
90(tool-bar-mode -1)
91(scroll-bar-mode -1)
92
93;; cursor
94(cuss cursor-type 'bar)
95(cuss cursor-in-non-selected-windows 'hollow)
96(blink-cursor-mode 0)
97
98;; mouse
99(cuss mouse-yank-at-point t) ; yank at the point instead of where clicked
100
101;; startup screen
102(cuss inhibit-startup-buffer-menu t)
103(cuss inhibit-startup-screen t)
104(cuss initial-buffer-choice t) ; start in *scratch*
105(cuss initial-scratch-message nil)
106
107;; interactivity
108(fset 'yes-or-no-p #'y-or-n-p)
109
110(cuss use-dialog-box nil)
111(cuss disabled-command-function nil)
112
113;; themes
114(use-package modus-operandi-theme
115 :config
116 (load-theme 'modus-operandi t))
117
118(use-package modus-vivendi-theme)
119
120;; fonts
121(set-face-attribute 'default nil
122 :family "DejaVu Sans Mono"
123 :height 110)
124
125(set-face-attribute 'fixed-pitch nil
126 :family "DejaVu Sans Mono"
127 :height 110)
128
129(set-face-attribute 'variable-pitch nil
130 :family "DejaVu Serif"
131 :height 120)
132
133;; unicode
134(use-package unicode-fonts
135 :config
136 (unicode-fonts-setup))
137
138;;; Selecting / Minibuffer
139;; ignore case
140(cuss completion-ignore-case t)
141(cuss read-buffer-completion-ignore-case t)
142(cuss read-file-name-completion-ignore-case t)
143
144(use-package selectrum
145 :config
146 (selectrum-mode +1))
147
148(use-package prescient
149 :config
150 (prescient-persist-mode +1))
151
152(use-package selectrum-prescient
153 :after (selectrum prescient)
154 :config
155 (selectrum-prescient-mode +1))
156
157;; searching
158(use-package ctrlf
159 :custom
160 (ctrlf-show-match-count-at-eol nil)
161 :config
162 (ctrlf-mode +1))
163
164;;; Undo
165(use-package undo-fu
166 :bind
167 ("C-/" . undo-fu-only-undo)
168 ("C-?" . undo-fu-only-redo))
169
170(use-package undo-fu-session
171 :after no-littering
172 :custom
173 (undo-fu-session-incompatible-files
174 '("/COMMIT_EDITMSG\\'"
175 "/git-rebase-todo\\'"))
176 (undo-fu-session-directory
177 (no-littering-expand-var-file-name "undos/"))
178 :config
179 (global-undo-fu-session-mode +1))
180
181;;; Text editing
182;; visual line mode
183(global-visual-line-mode +1)
184
185(use-package whole-line-or-region
186 :config
187 (whole-line-or-region-global-mode +1))
188
189(use-package expand-region
190 :bind
191 ("C-=" . er/expand-region))
192
193;; delete the selection when typing
194(delete-selection-mode +1)
195
196;; clipboard
197(cuss save-interprogram-paste-before-kill t) ; save existing clipboard text to kill ring before replacing it
198
199;; don't insert tabs.
200(cuss indent-tabs-mode nil)
201
202;;; Programming
203;; Git
204(use-package magit
205 :bind
206 ("C-x g" . magit-status)
207 :config
208 (add-to-list 'magit-no-confirm 'stage-all-changes))
209
210(when (executable-find "cmake")
211 (use-package libgit)
212 (use-package magit-libgit))
213
214(use-package forge
215 :after magit
216 :custom
217 (forge-owned-accounts '(("duckwork"))))
218
219;; Code formatting
220(use-package format-all
221 :hook
222 (prog-mode . format-all-mode))
223
224;; display
225(add-hook 'prog-mode-hook #'prettify-symbols-mode)
226
227;; parentheses
228(cuss show-paren-style 'mixed)
229(show-paren-mode +1)
230
231(use-package smartparens
232 :init
233 (defun acdw/setup-smartparens ()
234 (require 'smartparens-config)
235 (smartparens-mode +1))
236 :hook
237 (prog-mode . acdw/setup-smartparens))
238
239(use-package rainbow-delimiters
240 :hook
241 (prog-mode . rainbow-delimiters-mode))
242
243;; line numbers
244(add-hook 'prog-mode-hook
245 (if (and (fboundp 'display-line-numbers-mode)
246 (display-graphic-p))
247 #'display-line-numbers-mode
248 #'linum-mode))
249
250;;; Writing
251(cuss sentence-end-double-space t)
diff --git a/init.org b/init.org new file mode 100644 index 0000000..98e081d --- /dev/null +++ b/init.org
@@ -0,0 +1,587 @@
1#+TITLE: Emacs config
2#+AUTHOR: Case Duckworth
3#+BABEL: :cache yes
4#+PROPERTY: header-args :tangle init.el
5#+BANKRUPTCY_COUNT: 1
6
7* Preamble
8
9I 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.
10
11* Bootstrap
12
13/Check out Lars's config for the reasoning behind this./
14
15When this configuration is loaded for the first time, this ~init.el~ is loaded:
16
17#+BEGIN_SRC emacs-lisp :tangle no
18 ;; This file replaces itself with the actual configuration when first run. To keep only this version in git, run this command:
19 ;; git update-index --assume-unchanged init.el
20 ;;
21 ;; If it needs to be changed, start tracking it again thusly:
22 ;; git update-index --no-assume-unchanged init.el
23
24 (require 'org)
25 (find-file (concat user-emacs-directory "init.org"))
26 (org-babel-tangle)
27 (load-file (concat user-emacs-directory "init.el"))
28 (byte-compile-file (concat user-emacs-directory "init.el"))
29#+END_SRC
30
31** Tangling
32After 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.
33
34#+NAME: tangle-on-save
35#+BEGIN_SRC emacs-lisp
36 (defun acdw/tangle-init ()
37 "If the current buffer is `init.org', the code blocks are tangled,
38 and the tangled file is compiled."
39 (when (equal (buffer-file-name)
40 (expand-file-name (concat user-emacs-directory "init.org")))
41 ;; Avoid running hooks when tangling.
42 (let ((prog-mode-hook nil))
43 (org-babel-tangle)
44 (byte-compile-file (concat user-emacs-directory "init.el")))))
45
46(add-hook 'after-save-hook #'acdw/tangle-init)
47#+END_SRC
48
49* Early initiation
50Emacs 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.
51
52** Preamble
53Of course, first thing is the modeline. After that, I set ~load-prefer-newer~ because, well, it /should/.
54#+BEGIN_SRC emacs-lisp :tangle early-init.el
55 ;;; early-init.el -*- lexical-binding: t; no-byte-compile: t -*-
56
57(setq load-prefer-newer t)
58#+END_SRC
59
60** Computers
61I 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.
62
63#+BEGIN_SRC emacs-lisp :tangle early-init.el
64 (defconst *acdw/at-work* (eq system-type 'windows-nt))
65 (defconst *acdw/at-larry* (string= (system-name) "larry"))
66 (defconst *acdw/at-bax* (string= (system-name) "bax"))
67 (defconst *acdw/at-home* (or *acdw/at-larry* *acdw/at-bax*))
68#+END_SRC
69
70** Package management
71 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.
72
73*** At work, Git's in a weird place
74#+BEGIN_SRC emacs-lisp :tangle early-init.el
75 (when *acdw/at-work*
76 (add-to-list 'exec-path "~/bin")
77 (add-to-list 'exec-path "C:/Users/aduckworth/Downloads/PortableGit/bin"))
78#+END_SRC
79
80*** [[https://github.com/raxod502/straight.el][straight.el]]
81I 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/=).
82
83#+BEGIN_SRC emacs-lisp :tangle early-init.el
84 (defvar bootstrap-version)
85 (let ((bootstrap-file
86 (expand-file-name "straight/repos/straight.el/bootstrap.el"
87 user-emacs-directory))
88 (bootstrap-version 5))
89 (unless (file-exists-p bootstrap-file)
90 (with-current-buffer
91 (url-retrieve-synchronously
92 "https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
93 'silent 'inhibit-cookies)
94 (goto-char (point-max))
95 (eval-print-last-sexp)))
96 (load bootstrap-file nil 'nomessage))
97#+END_SRC
98
99*** [[https://github.com/jwiegley/use-package][use-package]]
100Yeah, you know it, I know it, we all love it. It's use-package.
101#+BEGIN_SRC emacs-lisp :tangle early-init.el
102 (setq straight-use-package-by-default t)
103 (straight-use-package 'use-package)
104#+END_SRC
105* Begin init.el
106#+BEGIN_SRC emacs-lisp
107 ;;; init.el -*- lexical-binding: t; coding: utf-8 -*-
108#+END_SRC
109* Macros
110** cuss
111I 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?
112
113Either 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~!
114#+BEGIN_SRC emacs-lisp
115 (defmacro cuss (var val)
116 "Basically `use-package''s `:custom', but without either."
117 `(progn
118 (funcall (or (get ',var 'custom-set) #'set-default)
119 ',var ,val)))
120#+END_SRC
121* Files
122** [[https://github.com/emacscollective/no-littering][Keep .emacs.d tidy]]
123#+BEGIN_SRC emacs-lisp
124 (use-package no-littering)
125#+END_SRC
126** Customize
127I 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.
128#+BEGIN_SRC emacs-lisp
129 (cuss custom-file (no-littering-expand-etc-file-name "custom.el"))
130#+END_SRC
131** Encoding
132#+BEGIN_SRC emacs-lisp
133 (set-charset-priority 'unicode)
134 (set-language-environment "UTF-8")
135 (set-default-coding-systems 'utf-8)
136 (set-terminal-coding-system 'utf-8)
137 (set-keyboard-coding-system 'utf-8)
138 (set-selection-coding-system 'utf-8)
139 (prefer-coding-system 'utf-8)
140#+END_SRC
141** Recent files
142#+BEGIN_SRC emacs-lisp
143 (use-package recentf
144 :config
145 (add-to-list 'recentf-exclude no-littering-var-directory)
146 (add-to-list 'recentf-exclude no-littering-etc-directory)
147 :custom
148 (recentf-max-menu-items 100)
149 (recentf-max-saved-items 100)
150 :config
151 (recentf-mode 1))
152#+END_SRC
153** Backups
154#+BEGIN_SRC emacs-lisp
155 (cuss backup-directory-alist
156 `((".*" . ,(no-littering-expand-var-file-name "backup/"))))
157#+END_SRC
158** [[https://github.com/bbatsov/super-save][Autosave]]
159#+BEGIN_SRC emacs-lisp
160 (use-package super-save
161 :custom
162 (auto-save-default nil)
163 (super-save-auto-save-when-idle t)
164 (super-save-exclude '(".gpg"))
165 :config
166 (super-save-mode 1))
167#+END_SRC
168** Save places
169#+BEGIN_SRC emacs-lisp
170 (use-package saveplace
171 :custom
172 (save-place-file (no-littering-expand-var-file-name "places"))
173 :config
174 (save-place-mode 1))
175#+END_SRC
176** Save history
177#+BEGIN_SRC emacs-lisp
178 (use-package savehist
179 :custom
180 (savehist-addtional-variables
181 '(kill-ring
182 search-ring
183 regexp-search-ring))
184 (savehist-save-minibuffer-history t)
185 :config
186 (savehist-mode 1))
187#+END_SRC
188* User interface
189** Look
190*** Frames and windows
191**** Frame defaults
192#+BEGIN_SRC emacs-lisp
193 (cuss default-frame-alist '((tool-bar-lines . 0)
194 (menu-bar-lines . 0)
195 (vertical-scroll-bars . nil)
196 (horizontal-scroll-bars . nil)
197 (right-divider-width . 2)
198 (bottom-divider-width . 2)
199 (left-fringe-width . 2)
200 (right-fringe-width . 2)))
201
202 ;; also disable these with modes, so I can re-enable them more easily
203 (menu-bar-mode -1)
204 (tool-bar-mode -1)
205 (scroll-bar-mode -1)
206#+END_SRC
207**** Resizing
208#+BEGIN_SRC emacs-lisp
209 (cuss frame-resize-pixelwise t)
210 (cuss window-combination-resize t)
211#+END_SRC
212*** Buffers
213#+BEGIN_SRC emacs-lisp
214 (cuss uniquify-buffer-name-style 'forward)
215
216 (cuss indicate-buffer-boundaries
217 '((top . right)
218 (bottom . right)
219 (t . nil)))
220#+END_SRC
221**** Startup buffer
222#+BEGIN_SRC emacs-lisp
223 (cuss inhibit-startup-buffer-menu t)
224 (cuss inhibit-startup-screen t)
225 (cuss initial-buffer-choice t) ; start in *scratch*
226 (cuss initial-scratch-message nil)
227#+END_SRC
228*** Cursor
229#+BEGIN_SRC emacs-lisp
230 (cuss cursor-type 'bar)
231 (cuss cursor-in-non-selected-windows 'hollow)
232 (blink-cursor-mode 0)
233#+END_SRC
234*** Interactivity
235**** Mouse
236#+BEGIN_SRC emacs-lisp
237 (cuss mouse-yank-at-point t)
238#+END_SRC
239**** Dialogs
240#+BEGIN_SRC emacs-lisp
241 (cuss use-dialog-box nil)
242#+END_SRC
243**** Disabled functions
244#+BEGIN_SRC emacs-lisp
245 (cuss disabled-command-function nil)
246#+END_SRC
247** Themes: [[https://github.com/protesilaos/modus-themes][Modus]]
248#+BEGIN_SRC emacs-lisp
249 (use-package modus-operandi-theme)
250 (use-package modus-vivendi-theme)
251#+END_SRC
252*** [[https://github.com/hadronzoo/theme-changer][Change themes]] based on time of day
253#+BEGIN_SRC emacs-lisp
254 (use-package theme-changer
255 :init
256 (setq calendar-location-name "Baton Rouge, LA"
257 calendar-latitude 30.39
258 calendar-longitude -91.83)
259 :config
260 (change-theme 'modus-operandi 'modus-vivendi))
261#+END_SRC
262** Modeline: [[https://github.com/Malabarba/smart-mode-line][smart-mode-line]]
263#+BEGIN_SRC emacs-lisp
264 (use-package smart-mode-line
265 :config
266 (sml/setup))
267#+END_SRC
268
269I 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")~.
270#+BEGIN_SRC emacs-lisp
271 (use-package rich-minority
272 :custom
273 (rm-whitelist '("^$")) ; show no minor modes
274 :config
275 (rich-minority-mode 1))
276#+END_SRC
277** Fonts
278I'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.
279#+BEGIN_SRC emacs-lisp
280 (cuss face-font-family-alternatives
281 '(("Monospace" "courier" "fixed")
282 ("Monospace Serif" "Courier 10 Pitch" "Consolas" "Courier Std" "FreeMono" "Nimbus Mono L" "courier" "fixed")
283 ("courier" "CMU Typewriter Text" "fixed")
284 ("Sans Serif" "helv" "helvetica" "arial" "fixed")
285 ("helv" "helvetica" "arial" "fixed")
286 ;; now mine
287 ("FixedPitch" "DejaVu Sans Mono" "Consolas" "fixed")
288 ("VariablePitch" "DejaVu Serif" "Georgia" "fixed")))
289
290 (set-face-attribute 'default nil
291 :family "FixedPitch"
292 :height 110)
293
294 (set-face-attribute 'fixed-pitch nil
295 :family "FixedPitch"
296 :height 110)
297
298 (set-face-attribute 'variable-pitch nil
299 :family "VariablePitch"
300 :height 110)
301#+END_SRC
302
303*** [[https://github.com/rolandwalker/unicode-fonts][Unicode fonts]]
304#+BEGIN_SRC emacs-lisp
305 (use-package unicode-fonts
306 :config
307 (unicode-fonts-setup))
308#+END_SRC
309* Editing
310** Completion
311I 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.
312#+BEGIN_SRC emacs-lisp
313 (bind-key "M-/" #'hippie-expand)
314#+END_SRC
315** Ignore case
316#+BEGIN_SRC emacs-lisp
317 (cuss completion-ignore-case t)
318 (cuss read-buffer-completion-ignore-case t)
319 (cuss read-file-name-completion-ignore-case t)
320#+END_SRC
321** Selection & Minibuffer
322*** Selectrum and Prescient for narrowing selection
323#+BEGIN_SRC emacs-lisp
324 (use-package selectrum
325 :config
326 (selectrum-mode +1))
327
328 (use-package prescient
329 :config
330 (prescient-persist-mode +1))
331
332 (use-package selectrum-prescient
333 :after (selectrum prescient)
334 :config
335 (selectrum-prescient-mode +1))
336#+END_SRC
337*** CtrlF for searching
338#+BEGIN_SRC emacs-lisp
339 (use-package ctrlf
340 :custom
341 (ctrlf-show-match-count-at-eol nil)
342 :config
343 (ctrlf-mode +1))
344#+END_SRC
345** Undo
346#+BEGIN_SRC emacs-lisp
347 (use-package undo-fu
348 :bind
349 ("C-/" . undo-fu-only-undo)
350 ("C-?" . undo-fu-only-redo))
351
352 (use-package undo-fu-session
353 :after no-littering
354 :custom
355 (undo-fu-session-incompatible-files
356 '("/COMMIT_EDITMSG\\'"
357 "/git-rebase-todo\\'"))
358 (undo-fu-session-directory
359 (no-littering-expand-var-file-name "undos/"))
360 :config
361 (global-undo-fu-session-mode +1))
362#+END_SRC
363** Visual editing
364*** ~zap-to-char~ replacement
365#+BEGIN_SRC emacs-lisp
366 (use-package zop-to-char
367 :bind
368 ([remap zap-to-char] . zop-to-char)
369 ([remap zap-up-to-char] . zop-up-to-char))
370#+END_SRC
371*** Operate on a line if there's no current region
372#+BEGIN_SRC emacs-lisp
373 (use-package whole-line-or-region
374 :config
375 (whole-line-or-region-global-mode +1))
376#+END_SRC
377*** Expand-region
378#+BEGIN_SRC emacs-lisp
379 (use-package expand-region
380 :bind
381 ("C-=" . er/expand-region)
382 ("C-+" . er/contract-region))
383#+END_SRC
384*** Volatile highlights
385#+BEGIN_SRC emacs-lisp
386 (use-package volatile-highlights
387 :config
388 (volatile-highlights-mode 1))
389#+END_SRC
390*** Visual line mode
391#+BEGIN_SRC emacs-lisp
392 (global-visual-line-mode 1)
393#+END_SRC
394*** A better ~move-beginning-of-line~
395#+BEGIN_SRC emacs-lisp
396 (defun my/smarter-move-beginning-of-line (arg)
397 "Move point back to indentation of beginning of line.
398
399 Move point to the first non-whitespace character on this line.
400 If point is already there, move to the beginning of the line.
401 Effectively toggle between the first non-whitespace character and
402 the beginning of the line.
403
404 If ARG is not nil or 1, move forward ARG - 1 lines first. If
405 point reaches the beginning or end of the buffer, stop there."
406 (interactive "^p")
407 (setq arg (or arg 1))
408
409 ;; Move lines first
410 (when (/= arg 1)
411 (let ((line-move-visual nil))
412 (forward-line (1- arg))))
413
414 (let ((orig-point (point)))
415 (back-to-indentation)
416 (when (= orig-point (point))
417 (move-beginning-of-line 1))))
418
419 (bind-key "C-a" ; can't do [remap], don't know why
420 #'my/smarter-move-beginning-of-line)
421#+END_SRC
422** Delete the selection when typing
423#+BEGIN_SRC emacs-lisp
424 (delete-selection-mode 1)
425#+END_SRC
426** Clipboard
427#+BEGIN_SRC emacs-lisp
428 (cuss save-interprogram-paste-before-kill t)
429#+END_SRC
430** Tabs & Spaces
431#+BEGIN_SRC emacs-lisp
432 (cuss indent-tabs-mode nil)
433 (cuss sentence-end-double-space t)
434#+END_SRC
435* Programming
436** Git
437#+BEGIN_SRC emacs-lisp
438 (use-package magit
439 :bind
440 ("C-x g" . magit-status)
441 :config
442 (add-to-list 'magit-no-confirm 'stage-all-changes))
443
444 ;; hook into `prescient'
445 (define-advice magit-list-refs
446 (:around (orig &optional namespaces format sortby)
447 prescient-sort)
448 "Apply prescient sorting when listing refs."
449 (let ((res (funcall orig namespaces format sortby)))
450 (if (or sortby
451 magit-list-refs-sortby
452 (not selectrum-should-sort-p))
453 res
454 (prescient-sort res))))
455
456 (when (executable-find "cmake")
457 (use-package libgit)
458 (use-package magit-libgit))
459
460 (use-package forge
461 :after magit
462 :custom
463 (forge-owned-accounts '(("duckwork"))))
464#+END_SRC
465** Code formatting and display
466#+BEGIN_SRC emacs-lisp
467 (use-package format-all
468 :hook
469 (prog-mode . format-all-mode))
470
471 (add-hook 'prog-mode-hook #'prettify-symbols-mode)
472
473#+END_SRC
474*** Parentheses
475#+BEGIN_SRC emacs-lisp
476 (cuss show-paren-style 'mixed)
477 (show-paren-mode +1)
478
479 (use-package smartparens
480 :init
481 (defun acdw/setup-smartparens ()
482 (require 'smartparens-config)
483 (smartparens-mode +1))
484 :hook
485 (prog-mode . acdw/setup-smartparens))
486
487 (use-package rainbow-delimiters
488 :hook
489 (prog-mode . rainbow-delimiters-mode))
490#+END_SRC
491** Line numbers
492#+BEGIN_SRC emacs-lisp
493 (add-hook 'prog-mode-hook
494 (if (and (fboundp 'display-line-numbers-mode)
495 (display-graphic-p))
496 #'display-line-numbers-mode
497 #'linum-mode))
498#+END_SRC
499** Languages
500*** Lua
501#+BEGIN_SRC emacs-lisp
502 (use-package lua-mode
503 :mode "\\.lua\\'"
504 :interpreter "lua")
505#+END_SRC
506*** Fennel
507#+BEGIN_SRC emacs-lisp
508 (use-package fennel-mode
509 :mode "\\.fnl\\'")
510#+END_SRC
511*** Web
512#+BEGIN_SRC emacs-lisp
513 (use-package web-mode
514 :custom
515 (web-mode-markup-indent-offset 2)
516 (web-mode-code-indent-offset 2)
517 (web-mode-css-indent-offset 2)
518 :mode (("\\.ts\\'" . web-mode)
519 ("\\.html?\\'" . web-mode)
520 ("\\.css?\\'" . web-mode)
521 ("\\.js\\'" . web-mode)))
522#+END_SRC
523* Writing
524* Applications
525** Gemini & Gopher
526#+BEGIN_SRC emacs-lisp
527 (use-package elpher
528 :straight (elpher
529 :repo "git://thelambdalab.xyz/elpher.git")
530 :bind (:map elpher-mode-map
531 ("n" . elpher-next-link)
532 ("p" . elpher-prev-link)
533 ("o" . elpher-follow-current-link)
534 ("G" . elpher-go-current)))
535
536 (use-package gemini-mode
537 :straight (gemini-mode
538 :repo "https://git.carcosa.net/jmcbray/gemini.el.git")
539 :mode "\\.\\(gemini|gmi\\)\\'")
540
541 (use-package gemini-write
542 :straight (gemini-write
543 :repo "https://alexschroeder.ch/cgit/gemini-write"))
544
545
546 (defun post-to-gemlog-blue (post-title user pass)
547 "Post current buffer to gemlog.blue."
548 (interactive
549 (let* ((title-maybe (progn ;; TODO this is ... clunky
550 (goto-char (point-min))
551 (if (re-search-forward "^# \\(.*\\)" nil t)
552 (buffer-substring-no-properties
553 (match-beginning 1)
554 (match-end 1))
555 "")))
556 (title (read-string
557 (format "Title%s: "
558 (if (string= "" title-maybe)
559 ""
560 (concat " (" title-maybe ")")))
561 nil nil title-maybe))
562 (user (read-string "User: " nil))
563 (pass (read-passwd "Pass: " nil)))
564 (list title user pass)))
565
566 (require 'mm-url)
567 (let ((url-request-method "POST")
568 (url-request-extra-headers
569 '(("Content-Type" . "application/x-www-form-urlencoded")))
570 (url-request-data
571 (mm-url-encode-www-form-urlencoded
572 `(("title" . ,post-title)
573 ("gemloguser" . ,user)
574 ("pw" . ,pass)
575 ("post" . ,(buffer-string))))))
576 (with-current-buffer
577 (url-retrieve-synchronously "https://gemlog.blue/post.php")
578 (goto-char (point-min))
579 (re-search-forward "\\(gemini://.*\\.gmi\\)")
580 (elpher-go (match-string 1)))))
581#+END_SRC
582** Pastebin
583#+BEGIN_SRC emacs-lisp
584 (use-package 0x0
585 :custom
586 (0x0-default-service 'ttm))
587#+END_SRC