summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--config.org386
-rw-r--r--early-init.el8
-rw-r--r--init.el4
3 files changed, 346 insertions, 52 deletions
diff --git a/config.org b/config.org index 2a9c97b..ac18133 100644 --- a/config.org +++ b/config.org
@@ -1,6 +1,6 @@
1#+TITLE: Emacs configuration, literate-style 1#+TITLE: Emacs configuration, literate-style
2#+AUTHOR: Case Duckworth 2#+AUTHOR: Case Duckworth
3#+PROPERTY: header-args :tangle yes :tangle-mode (identity #o444) :comments both :mkdirp yes 3#+PROPERTY: header-args :tangle yes :tangle-mode (identity #o444) :comments both
4 4
5* Settings 5* Settings
6 6
@@ -56,11 +56,10 @@ These should not require non-built-in packages.
56 (add-function :before after-focus-change-function #'acdw/set-custom-faces) 56 (add-function :before after-focus-change-function #'acdw/set-custom-faces)
57 57
58 (defmacro cussface (face spec &optional _docstring) 58 (defmacro cussface (face spec &optional _docstring)
59 "Add the form (FACE SPEC) to `acdw--custom-faces', and add a 59 "Add the form (FACE SPEC) to `acdw--custom-faces'."
60 hook to run `acdw/set-custom-faces' after init."
61 (declare (doc-string 3) 60 (declare (doc-string 3)
62 (indent 2)) 61 (indent defun))
63 `(add-to-list acdw--custom-faces '(,face ,spec))) 62 `(add-to-list 'acdw--custom-faces '(,face ,spec)))
64#+end_src 63#+end_src
65 64
66*** Only do something when Emacs is unfocused 65*** Only do something when Emacs is unfocused
@@ -110,43 +109,6 @@ My name and email address.
110 (blink-cursor-mode -1) 109 (blink-cursor-mode -1)
111#+end_src 110#+end_src
112 111
113*** Dialogs and alerts
114
115**** Don't use a dialog box
116
117#+begin_src emacs-lisp
118 (cuss use-dialog-box nil)
119#+end_src
120
121**** Yes or no questions
122
123#+begin_src emacs-lisp
124 (fset 'yes-or-no-p #'y-or-n-p)
125#+end_src
126
127**** The Bell
128
129#+begin_src emacs-lisp
130 ;; Don't flash the whole screen on bell
131 (cuss visible-bell nil)
132
133 ;; Instead, flash the mode line
134 (cuss ring-bell-function #'flash-mode-line)
135
136 (defun flash-mode-line ()
137 (invert-face 'mode-line)
138 (run-with-timer 0.2 nil #'invert-face 'mode-line))
139#+end_src
140
141t*** Minibuffer
142
143**** Keep the cursor away from the minibuffer prompt
144
145#+begin_src emacs-lisp
146 (cuss minibuffer-prompt-properties
147 '(read-only t cursor-intangible t face minibuffer-prompt))
148#+end_src
149
150*** Tabs 112*** Tabs
151 113
152**** Tab names should be current buffer + a count of windows 114**** Tab names should be current buffer + a count of windows
@@ -237,20 +199,352 @@ and have made a custom fringe bitmap.
237 199
238#+begin_src emacs-lisp 200#+begin_src emacs-lisp
239 (cuss visual-line-fringe-indicators '(left-curly-arrow nil)) 201 (cuss visual-line-fringe-indicators '(left-curly-arrow nil))
202#+end_src
240 203
241 ;; And make the `left-curly-arrow' indicator less distracting. 204***** Customize fringe bitmaps
242 205
206****** Curly arrows (continuation lines)
207
208#+begin_src emacs-lisp
243 (define-fringe-bitmap 'left-curly-arrow 209 (define-fringe-bitmap 'left-curly-arrow
244 [#b11000000 210 [#b11000000
245 #b01100000 211 #b01100000
246 #b00110000 212 #b00110000
247 #b00011000]) 213 #b00011000])
214
215 (define-fringe-bitmap 'right-curly-arrow
216 [#b00011000
217 #b00110000
218 #b01100000
219 #b11000000])
220#+end_src
221
222****** Arrows (truncation lines)
223
224#+begin_src emacs-lisp
225 (define-fringe-bitmap 'left-arrow
226 [#b00000000
227 #b01010100
228 #b01010100
229 #b00000000])
230
231 (define-fringe-bitmap 'right-arrow
232 [#b00000000
233 #b00101010
234 #b00101010
235 #b00000000])
248#+end_src 236#+end_src
249 237
250*** Windows 238*** Windows
251 239
240**** Winner mode
241
242I don't really /use/ winner-mode as of yet, but it seems like a really
243good thing to have. It lets you move between window configurations
244with =C-c <-/->=.
245
246#+begin_src emacs-lisp
247 (when (fboundp 'winner-mode)
248 (winner-mode +1))
249#+end_src
250
251**** Switch windows, or buffers if there's only one
252
253from [[https://www.reddit.com/r/emacs/comments/kz347f/what_parts_of_your_config_do_you_like_best/gjlnp2c/][u/astoff1]].
254
255#+begin_src emacs-lisp
256 (defun other-window-or-buffer ()
257 "Switch to the other window, or previous buffer."
258 (interactive)
259 (if (eq (count-windows) 1)
260 (switch-to-buffer nil)
261 (other-window 1)))
262#+end_src
263
252*** Buffers 264*** Buffers
253 265
266**** Startup buffers
267
268I don't want to see Emacs's splash screen, and I want the =*scratch*=
269buffer to have a little message.
270
271#+begin_src emacs-lisp
272 (cuss inhibit-startup-screen t
273 "Don't show the startup buffer.")
274
275 (cuss initial-buffer-choice t
276 "Start with *scratch*.")
277
278 (cuss initial-scratch-message
279 (concat ";; Hello, " (nth 0 (split-string user-full-name)) "!\n"
280 ";; Happy hacking ..."))
281#+end_src
282
283**** Immortal =*scratch*= buffer
284
285I don't want to accidentally kill the =*scratch*= buffer.
286
287#+begin_src emacs-lisp
288 (defun immortal-scratch ()
289 (if (eq (current-buffer) (get-buffer "*scratch*"))
290 (progn (bury-buffer)
291 nil)
292 t))
293
294 (add-hook 'kill-buffer-query-functions #'immortal-scratch)
295#+end_src
296
297**** Uniquify buffers
298
299I like the =forward= style, which uniquifies buffers by including path
300elements up the tree until the names are unique.
301
302#+begin_src emacs-lisp
303 (require 'uniquify)
304 (cuss uniquify-buffer-name-style 'forward)
305#+end_src
306
307**** Kill buffers more smarter-ly
308
309#+begin_src emacs-lisp
310 (defun kill-a-buffer (&optional prefix)
311 "Kill buffers and windows sanely.
312
313 `kill-a-buffer' works based on the prefix argument as follows:
314
315 - 0 => kill the CURRENT buffer and window
316 - 4 (C-u) => kill the OTHER window and its buffer
317 - 16 (C-u C-u) => kill ALL OTHER buffers and windows
318
319 Prompt iff there are unsaved changes."
320 (interactive "P")
321 (pcase (or (car prefix) 0)
322 (0 (kill-current-buffer)
323 (unless (one-window-p) (delete-window)))
324 (4 (other-window 1)
325 (kill-current-buffer)
326 (unless (one-window-p) (delete-window)))
327 (16 (mapc #'kill-buffer (delq (current-buffer) (buffer-list)))
328 (delete-other-windows))))
329#+end_src
330
331*** Fonts
332
333**** Function: =set-face-from-alternatives=
334
335To be honest, this might be better off using =cussface=, but that's
336another story for another day.
337
338#+begin_src emacs-lisp
339 (defun set-face-from-alternatives (face frame &rest fontspecs)
340 "Set FACE on FRAME from first available font from FONTSPECS.
341 FACE and FRAME work the same as with `set-face-attribute'."
342 (catch :return
343 (dolist (spec fontspecs)
344 (when-let ((found (find-font (apply #'font-spec spec))))
345 (set-face-attribute face frame :font found)
346 (throw :return found)))))
347#+end_src
348
349**** Add a hook to setup fonts after the first window focus change
350
351Of course, I only need to setup the fonts on a graphical session.
352
353#+begin_src emacs-lisp
354 (when (display-graphic-p)
355 (add-function :before after-focus-change-function #'acdw/setup-fonts))
356#+end_src
357
358**** Setup my fonts
359
360Notice that this function removes itself from
361=after-focus-change-function=, since ideally you'll only need to set
362the fonts once.
363
364#+begin_src emacs-lisp
365 (defun acdw/setup-fonts ()
366 "Setup fonts.
367
368 This has to happen after the frame is setup for the first time,
369 so it should be added to `after-focus-change-function'. It
370 removes itself."
371 (set-face-from-alternatives 'default nil
372 '(:family "Input Mono"
373 :slant normal
374 :weight normal
375 :height 110)
376 '(:family "Consolas"
377 :slant normal
378 :weight normal
379 :height 100))
380 ;; `fixed-pitch' should just inherit from `default'
381 (set-face-attribute 'fixed-pitch nil :inherit 'default)
382
383 (set-face-from-alternatives 'variable-pitch nil
384 '(:family "Input Sans"
385 :slant normal
386 :weight normal)
387 '(:family "Georgia"
388 :slant normal
389 :weight normal))
390
391 (remove-function after-focus-change-function #'acdw/setup-fonts))
392#+end_src
393
394**** Underlines
395
396#+begin_src emacs-lisp
397 (cuss x-underline-at-descent-line t)
398#+end_src
399
400** Interactivity
401*** Dialogs and alerts
402
403**** Don't use a dialog box
404
405#+begin_src emacs-lisp
406 (cuss use-dialog-box nil)
407#+end_src
408
409**** Yes or no questions
410
411#+begin_src emacs-lisp
412 (fset 'yes-or-no-p #'y-or-n-p)
413#+end_src
414
415**** The Bell
416
417#+begin_src emacs-lisp
418 ;; Don't flash the whole screen on bell
419 (cuss visible-bell nil)
420
421 ;; Instead, flash the mode line
422 (cuss ring-bell-function #'flash-mode-line)
423
424 (defun flash-mode-line ()
425 (invert-face 'mode-line)
426 (run-with-timer 0.2 nil #'invert-face 'mode-line))
427#+end_src
428
429t*** Minibuffer
430
431*** Minibuffer
432
433**** Keep the cursor away from the minibuffer prompt
434
435#+begin_src emacs-lisp
436 (cuss minibuffer-prompt-properties
437 '(read-only t cursor-intangible t face minibuffer-prompt))
438#+end_src
439
440**** Enable recursive minibuffer
441
442#+begin_src emacs-lisp
443 (cuss enable-recursive-minibuffers t)
444#+end_src
445
446**** Show how deep the minibuffer goes in the modeline
447
448#+begin_src emacs-lisp
449 (minibuffer-depth-indicate-mode +1)
450#+end_src
451
452*** Completing-read
453
454**** Shadow file names
455
456When typing =~= or =/= in the file-selection dialog, Emacs "pretends"
457that you've typed them at the beginning of the line. By default,
458however, it only /fades out/ the previous contents of the line. I
459want to /hide/ those contents.
460
461#+begin_src emacs-lisp
462 (cuss file-name-shadow-properties '(invisible t))
463
464 (file-name-shadow-mode +1)
465#+end_src
466
467**** Ignore case
468
469#+begin_src emacs-lisp
470 (cuss completion-ignore-case t)
471 (cuss read-buffer-completion-ignore-case t)
472 (cuss read-file-name-completion-ignore-case t)
473#+end_src
474
475** Persistence
476
477*** Minibuffer history
478
479The =savehist= package saves the minibuffer history between sessions.
480It can also save some other variables alongside the minibuffer
481history. Since storage is cheap, I'm also going to keep all my
482history.
483
484#+begin_src emacs-lisp
485 (require 'savehist)
486
487 (cuss savehist-additional-variables
488 '(kill-ring
489 search-ring
490 regexp-search-ring))
491
492 ;; Don't truncate history
493 (cuss history-length t)
494
495 ;; Delete history duplicates
496 (cuss history-delete-duplicates t)
497
498 (savehist-mode +1)
499#+end_src
500
501*** File places
502
503The =saveplace= package saves where I've been in the files I've
504visited, so I can return back to them.
505
506#+begin_src emacs-lisp
507 (require 'saveplace)
508
509 ;; Forget the place in unreadable files
510 (cuss save-place-forget-unreadable-files t)
511
512 (save-place-mode +1)
513#+end_src
514
515*** Recent files
516
517#+begin_src emacs-lisp
518 (require 'recentf)
519
520 ;; Limit the number of items in the recentf menu
521 (cuss recentf-max-menu-items 100)
522 ;; But not the number of items in the actual list
523 (cuss recentf-max-saved-items nil)
524
525 (recentf-mode +1)
526#+end_src
527
528**** Save the recentf list periodically
529
530#+begin_src emacs-lisp
531 (defun acdw/maybe-save-recentf ()
532 "Save `recentf-file every five minutes, but only when out of focus."
533 (defvar recentf--last-save (time-convert nil 'integer)
534 "When we last ran `recentf-save-list'.")
535
536 (when (> (time-convert (time-since recentf--last-save) 'integer)
537 (* 60 5))
538 (setq recentf--last-save (time-convert nil 'integer))
539 (acdw/when-unfocused #'recentf-save-list)))
540
541 (add-function :after after-focus-change-function #'acdw/maybe-save-recentf)
542#+end_src
543
544** Files
545
546*** Encoding
547
254* System-specific 548* System-specific
255 549
256I use both Linux (at home) and Windows (at work). To make Emacs 550I use both Linux (at home) and Windows (at work). To make Emacs
@@ -286,7 +580,7 @@ settings and written some ancillary scripts.
286 580
287**** em 581**** em
288:PROPERTIES: 582:PROPERTIES:
289:header-args: :tangle-mode (identity #o755) :tangle bin/em 583:header-args: :tangle-mode (identity #o755) :tangle bin/em :mkdirp yes
290:END: 584:END:
291 585
292Here's a wrapper script that'll start =emacs --daemon= if there isn't 586Here's a wrapper script that'll start =emacs --daemon= if there isn't
@@ -302,7 +596,7 @@ your =$PATH= somewhere.
302 596
303**** emacsclient.desktop 597**** emacsclient.desktop
304:PROPERTIES: 598:PROPERTIES:
305:header-args: :tangle bin/emacsclient.desktop 599:header-args: :tangle bin/emacsclient.desktop :mkdirp yes
306:END: 600:END:
307 601
308I haven't really tested this yet, but it should allow me to open other 602I haven't really tested this yet, but it should allow me to open other
@@ -338,7 +632,7 @@ section come from [[https://github.com/termitereform/JunkPile/blob/master/emacs-
338 632
339*** Scripts 633*** Scripts
340:PROPERTIES: 634:PROPERTIES:
341:header-args: :noweb tangle 635:header-args: :noweb tangle :mkdirp yes
342:END: 636:END:
343 637
344**** Common variables 638**** Common variables
diff --git a/early-init.el b/early-init.el index f879ee4..2e78e43 100644 --- a/early-init.el +++ b/early-init.el
@@ -7,21 +7,21 @@
7;; I use =straight.el= instead. 7;; I use =straight.el= instead.
8 8
9 9
10;; [[file:config.org::*Disable loading of =package.el=][Disable loading of =package.el=:1]] 10;; [[file:~/.emacs.d/config.org::*Disable loading of =package.el=][Disable loading of =package.el=:1]]
11(setq package-enable-at-startup nil) 11(setq package-enable-at-startup nil)
12;; Disable loading of =package.el=:1 ends here 12;; Disable loading of =package.el=:1 ends here
13 13
14;; Don't resize the frame when loading fonts 14;; Don't resize the frame when loading fonts
15 15
16 16
17;; [[file:config.org::*Don't resize the frame when loading fonts][Don't resize the frame when loading fonts:1]] 17;; [[file:~/.emacs.d/config.org::*Don't resize the frame when loading fonts][Don't resize the frame when loading fonts:1]]
18(setq frame-inhibit-implied-resize t) 18(setq frame-inhibit-implied-resize t)
19;; Don't resize the frame when loading fonts:1 ends here 19;; Don't resize the frame when loading fonts:1 ends here
20 20
21;; Resize frame by pixels 21;; Resize frame by pixels
22 22
23 23
24;; [[file:config.org::*Resize frame by pixels][Resize frame by pixels:1]] 24;; [[file:~/.emacs.d/config.org::*Resize frame by pixels][Resize frame by pixels:1]]
25(setq frame-resize-pixelwise t) 25(setq frame-resize-pixelwise t)
26;; Resize frame by pixels:1 ends here 26;; Resize frame by pixels:1 ends here
27 27
@@ -35,7 +35,7 @@
35;; what I have for now. 35;; what I have for now.
36 36
37 37
38;; [[file:config.org::*Shoe-horned from elsewhere in =config.org=][Shoe-horned from elsewhere in =config.org=:1]] 38;; [[file:~/.emacs.d/config.org::*Shoe-horned from elsewhere in =config.org=][Shoe-horned from elsewhere in =config.org=:1]]
39(add-to-list 'default-frame-alist 39(add-to-list 'default-frame-alist
40 '(tool-bar-lines . 0)) 40 '(tool-bar-lines . 0))
41 41
diff --git a/init.el b/init.el index b902c0b..d0e30b2 100644 --- a/init.el +++ b/init.el
@@ -5,7 +5,7 @@
5;; Prefer newer files to older files 5;; Prefer newer files to older files
6 6
7 7
8;; [[file:config.org::*Prefer newer files to older files][Prefer newer files to older files:1]] 8;; [[file:~/.emacs.d/config.org::*Prefer newer files to older files][Prefer newer files to older files:1]]
9(setq load-prefer-newer t) 9(setq load-prefer-newer t)
10;; Prefer newer files to older files:1 ends here 10;; Prefer newer files to older files:1 ends here
11 11
@@ -16,7 +16,7 @@
16;; directly from Org if it's newer. 16;; directly from Org if it's newer.
17 17
18 18
19;; [[file:config.org::*Load the config][Load the config:1]] 19;; [[file:~/.emacs.d/config.org::*Load the config][Load the config:1]]
20(let* (;; Speed up init 20(let* (;; Speed up init
21 (gc-cons-threshold most-positive-fixnum) 21 (gc-cons-threshold most-positive-fixnum)
22 (file-name-handler-alist nil) 22 (file-name-handler-alist nil)