summary refs log tree commit diff stats
path: root/README.md
diff options
context:
space:
mode:
authorCase Duckworth2021-01-02 10:04:56 -0600
committerCase Duckworth2021-01-02 10:04:56 -0600
commitcfea700270a7de9cffea06de955288ecf24d9009 (patch)
tree4b0087e918bc02cbc15c775e17af270102eafe70 /README.md
parentReorganize Org section (diff)
downloademacs-cfea700270a7de9cffea06de955288ecf24d9009.tar.gz
emacs-cfea700270a7de9cffea06de955288ecf24d9009.zip
Update README
Diffstat (limited to 'README.md')
-rw-r--r--README.md589
1 files changed, 368 insertions, 221 deletions
diff --git a/README.md b/README.md index 02029dc..d6b2457 100644 --- a/README.md +++ b/README.md
@@ -69,7 +69,7 @@ Now, I'll *try* running it regular-style, ignoring the errors. If it
69doesn't work, I'll call git directly and clone the repo myself. 69doesn't work, I'll call git directly and clone the repo myself.
70 70
71 (unless (ignore-errors (acdw/bootstrap-straight)) 71 (unless (ignore-errors (acdw/bootstrap-straight))
72 (message "Straight.el didn't bootstrap correctly. Cloning directly...") 72 (message "%s" "Straight.el didn't bootstrap correctly. Cloning directly...")
73 (call-process "git" nil 73 (call-process "git" nil
74 (get-buffer-create "*bootstrap-straight-messages*") nil 74 (get-buffer-create "*bootstrap-straight-messages*") nil
75 "clone" 75 "clone"
@@ -79,7 +79,10 @@ doesn't work, I'll call git directly and clone the repo myself.
79 (acdw/bootstrap-straight)) 79 (acdw/bootstrap-straight))
80 80
81 81
82## Customize macro 82## Customize macros
83
84
85### Emulate use-package’s `:custom`
83 86
84 (defmacro cuss (var val &optional docstring) 87 (defmacro cuss (var val &optional docstring)
85 "Basically, `:custom' from `use-package', but without `use-package'." 88 "Basically, `:custom' from `use-package', but without `use-package'."
@@ -89,76 +92,36 @@ doesn't work, I'll call git directly and clone the repo myself.
89 ',var ,val)) 92 ',var ,val))
90 93
91 94
92## Clean `.emacs.d` 95### Emulate use-package’s `:custom-face`, but better
93 96
94 (straight-use-package 'no-littering) 97 (defvar acdw--custom-faces ()
95 (require 'no-littering) 98 "List of custom faces to run through acdw/set-custom-faces.")
96 99
97 100 (defun acdw/set-custom-faces ()
98## Look and feel 101 "Run `customize-set-faces' on `acdw--custom-faces'."
102 (message "%s" "Customizing faces...")
103 (apply #'custom-set-faces acdw--custom-faces))
104
105 (defun cussface (spec)
106 "Add SPEC to `acdw--custom-faces', and add a hook to run
107 `acdw/set-custom-faces' after init."
108 (add-to-list 'acdw--custom-faces spec)
109 (add-hook 'after-init-hook #'acdw/set-custom-faces))
99 110
100 111
101### Fonts 112## Clean `.emacs.d`
102 113
1031. Define fonts 114 (straight-use-package 'no-littering)
115 (require 'no-littering)
104 116
105 (defun set-face-from-alternatives (face fonts)
106 (catch :return
107 (dolist (font fonts)
108 (when (find-font (font-spec :family (car font)))
109 (apply #'set-face-attribute `(,face nil
110 :family ,(car font)
111 ,@(cdr font)))
112 (throw :return font)))))
113
114 (defun acdw/setup-fonts ()
115 "Setup fonts. This has to happen after the frame is setup for
116 the first time, so it should be added to `window-setup-hook'. It
117 removes itself from that hook."
118 (interactive)
119 (when (display-graphic-p)
120 (set-face-from-alternatives 'default
121 '(("Libertinus Mono"
122 :height 110)
123 ("Linux Libertine Mono O"
124 :height 110)
125 ("Go Mono"
126 :height 100)
127 ("Consolas"
128 :height 100)))
129
130 (set-face-from-alternatives 'fixed-pitch
131 '(("Libertinus Mono"
132 :height 110)
133 ("Linux Libertine Mono O"
134 :height 110)
135 ("Go Mono"
136 :height 100)
137 ("Consolas"
138 :height 100)))
139
140 (set-face-from-alternatives 'variable-pitch
141 '(("Libertinus Serif"
142 :height 120)
143 ("Linux Libertine O"
144 :height 120)
145 ("Georgia"
146 :height 110)))
147
148 (remove-function after-focus-change-function #'acdw/setup-fonts)))
149
150 (add-function :before after-focus-change-function #'acdw/setup-fonts)
151 117
1522. Line spacing 118### Don’t clutter `init.el` with customizations
153 119
154 (cuss line-spacing 0.1 120 (with-eval-after-load 'no-littering
155 "Add 10% extra space below each line.") 121 (cuss custom-file (no-littering-expand-etc-file-name "custom.el")))
156 122
1573. Unicode Fonts
158 123
159 (straight-use-package 'unicode-fonts) 124## Look and feel
160 (require 'unicode-fonts)
161 (unicode-fonts-setup)
162 125
163 126
164### Cursor 127### Cursor
@@ -166,7 +129,7 @@ doesn't work, I'll call git directly and clone the repo myself.
166 (cuss cursor-type 'bar 129 (cuss cursor-type 'bar
167 "Show a vertical bar for the cursor.") 130 "Show a vertical bar for the cursor.")
168 131
169 (cuss cursor-in-non-selected-windows 'hollow 132 (cuss cursor-in-non-selected-windows 'hbar
170 "Show an empty box in inactive windows.") 133 "Show an empty box in inactive windows.")
171 134
172 ;; Don't blink the cursor 135 ;; Don't blink the cursor
@@ -344,17 +307,68 @@ doesn't work, I'll call git directly and clone the repo myself.
344 307
345 (load-theme 'modus-operandi t) 308 (load-theme 'modus-operandi t)
346 309
3472. Change themes based on time of day
348 310
349 (cuss calendar-latitude 30.4515) 311### Fonts
350 (cuss calendar-longitude -91.1871) 312
3131. Define fonts
314
315 (defun set-face-from-alternatives (face fonts)
316 (catch :return
317 (dolist (font fonts)
318 (when (find-font (font-spec :family (car font)))
319 (apply #'set-face-attribute `(,face
320 nil
321 :family (car font)
322 ,@(cdr font)))
323 (throw :return font)))))
324
325 (defun acdw/setup-fonts ()
326 "Setup fonts. This has to happen after the frame is setup for
327 the first time, so it should be added to `window-setup-hook'. It
328 removes itself from that hook."
329 (interactive)
330 (when (display-graphic-p)
331 (set-face-from-alternatives 'default
332 '(("Input Mono"
333 :height 105)
334 ("Go Mono"
335 :height 100)
336 ("Consolas"
337 :height 100)))
351 338
352 (straight-use-package 'circadian) 339 (set-face-from-alternatives 'fixed-pitch
340 '(("Input Mono")
341 ("Go Mono")
342 ("Consolas")))
353 343
354 (cuss circadian-themes '((:sunrise . modus-operandi) 344 (set-face-from-alternatives 'variable-pitch
355 (:sunset . modus-vivendi))) 345 '(("Input Serif")
346 ("Georgia")))
356 347
357 (circadian-setup) 348 (remove-function after-focus-change-function #'acdw/setup-fonts)))
349
350 (add-function :before after-focus-change-function #'acdw/setup-fonts)
351
3522. Custom faces
353
354 (cussface '(font-lock-comment-face
355 ((t (:inherit (custom-comment italic variable-pitch))))))
356
3573. Line spacing
358
359 (cuss line-spacing 0.1
360 "Add 10% extra space below each line.")
361
3624. Underlines
363
364 (cuss x-underline-at-descent-line t
365 "Draw the underline at the same place as the descent line.")
366
3675. Unicode Fonts
368
369 (straight-use-package 'unicode-fonts)
370 (require 'unicode-fonts)
371 (unicode-fonts-setup)
358 372
359 373
360## Interactivity 374## Interactivity
@@ -374,13 +388,18 @@ doesn't work, I'll call git directly and clone the repo myself.
374 (cuss read-buffer-completion-ignore-case t) 388 (cuss read-buffer-completion-ignore-case t)
375 (cuss read-file-name-completion-ignore-case t) 389 (cuss read-file-name-completion-ignore-case t)
376 390
3773. Selectrum 3913. Minibuffer recursivity
392
393 (cuss enable-recursive-minibuffers t)
394 (minibuffer-depth-indicate-mode +1)
395
3964. Selectrum
378 397
379 (straight-use-package 'selectrum) 398 (straight-use-package 'selectrum)
380 (require 'selectrum) 399 (require 'selectrum)
381 (selectrum-mode +1) 400 (selectrum-mode +1)
382 401
3834. Prescient 4025. Prescient
384 403
385 (straight-use-package 'prescient) 404 (straight-use-package 'prescient)
386 (require 'prescient) 405 (require 'prescient)
@@ -390,7 +409,7 @@ doesn't work, I'll call git directly and clone the repo myself.
390 (require 'selectrum-prescient) 409 (require 'selectrum-prescient)
391 (selectrum-prescient-mode +1) 410 (selectrum-prescient-mode +1)
392 411
3935. Consult 4126. Consult
394 413
395 (straight-use-package '(consult 414 (straight-use-package '(consult
396 :host github 415 :host github
@@ -402,27 +421,27 @@ doesn't work, I'll call git directly and clone the repo myself.
402 :repo "minad/consult")) 421 :repo "minad/consult"))
403 (require 'consult-selectrum) 422 (require 'consult-selectrum)
404 423
405 (define-key ctl-x-map "b" #'consult-buffer) 424 (with-eval-after-load 'consult
406 (define-key ctl-x-map (kbd "C-r") #'consult-buffer) 425 (define-key ctl-x-map "b" #'consult-buffer)
407 (define-key ctl-x-map "4b" #'consult-buffer-other-window) 426 (define-key ctl-x-map (kbd "C-r") #'consult-buffer)
408 (define-key ctl-x-map "5b" #'consult-buffer-other-frame) 427 (define-key ctl-x-map "4b" #'consult-buffer-other-window)
428 (define-key ctl-x-map "5b" #'consult-buffer-other-frame)
409 429
410 (define-key goto-map "o" #'consult-outline) 430 (define-key goto-map "o" #'consult-outline)
411 (define-key goto-map "g" #'consult-line) 431 (define-key goto-map "g" #'consult-line)
412 (define-key goto-map (kbd "M-g") #'consult-line) 432 (define-key goto-map (kbd "M-g") #'consult-line)
413 (define-key goto-map "l" #'consult-line) 433 (define-key goto-map "l" #'consult-line)
414 (define-key goto-map "m" #'consult-mark) 434 (define-key goto-map "m" #'consult-mark)
415 (define-key goto-map "k" #'consult-global-mark) 435 (define-key goto-map "i" #'consult-imenu)
416 (define-key goto-map "i" #'consult-imenu) 436 (define-key goto-map "e" #'consult-error)
417 (define-key goto-map "e" #'consult-error)
418 437
419 (global-set-key (kbd "M-y") #'consult-yank-pop) 438 (global-set-key (kbd "M-y") #'consult-yank-pop)
420 439
421 (define-key help-map "a" #'consult-apropos) 440 (define-key help-map "a" #'consult-apropos)
422 441
423 (fset 'multi-occur #'consult-multi-occur) 442 (fset 'multi-occur #'consult-multi-occur))
424 443
4256. Marginalia 4447. Marginalia
426 445
427 (straight-use-package '(marginalia 446 (straight-use-package '(marginalia
428 :host github 447 :host github
@@ -436,6 +455,11 @@ doesn't work, I'll call git directly and clone the repo myself.
436 (marginalia-mode +1) 455 (marginalia-mode +1)
437 456
438 457
458### Completion
459
460 (global-set-key (kbd "M-/") #'hippie-expand)
461
462
439## Keyboard 463## Keyboard
440 464
441 465
@@ -457,6 +481,22 @@ doesn't work, I'll call git directly and clone the repo myself.
457 (run-hooks 'acdw/map-defined-hook) 481 (run-hooks 'acdw/map-defined-hook)
458 482
459 483
484## Mouse
485
486
487### Preserve screen position when scrolling with the mouse wheel
488
489from [u/TheFrenchPoulp](https://www.reddit.com/r/emacs/comments/km9by4/weekly_tipstricketc_thread/ghg2c9d/).
490
491 (advice-add 'mwheel-scroll :around #'me/mwheel-scroll)
492
493 (defun me/mwheel-scroll (original &rest arguments)
494 "Like `mwheel-scroll' but preserve screen position.
495 See `scroll-preserve-screen-position'."
496 (let ((scroll-preserve-screen-position :always))
497 (apply original arguments)))
498
499
460## Persistence 500## Persistence
461 501
462 502
@@ -637,11 +677,22 @@ doesn't work, I'll call git directly and clone the repo myself.
637 677
638### Searching & Replacing 678### Searching & Replacing
639 679
640 (straight-use-package 'visual-regexp) 6801. Replace with Anzu
641 (require 'visual-regexp) 681
642 682 (straight-use-package 'anzu)
643 (with-eval-after-load 'visual-regexp 683 (require 'anzu)
644 (global-set-key (kbd "M-C-%") #'vr/query-replace)) 684
685 ;; show search count in the modeline
686 (global-anzu-mode +1)
687
688 (cuss anzu-replace-to-string-separator " → "
689 "What to separate the search from the replacement.")
690
691 (global-set-key [remap query-replace] #'anzu-query-replace)
692 (global-set-key [remap query-replace-regexp] #'anzu-query-replace-regexp)
693
694 (define-key isearch-mode-map [remap isearch-query-replace] #'anzu-isearch-query-replace)
695 (define-key isearch-mode-map [remap isearch-query-replace-regexp] #'anzu-isearch-query-replace-regexp)
645 696
646 697
647# Programming 698# Programming
@@ -731,7 +782,11 @@ This has to be done *before* loading the package. It's included in `visual-fill
731 (global-set-key [left-margin mouse-wheel-down-event] #'mwheel-scroll) 782 (global-set-key [left-margin mouse-wheel-down-event] #'mwheel-scroll)
732 (global-set-key [left-margin mouse-wheel-up-event] #'mwheel-scroll) 783 (global-set-key [left-margin mouse-wheel-up-event] #'mwheel-scroll)
733 (global-set-key [left-margin wheel-down] #'mwheel-scroll) 784 (global-set-key [left-margin wheel-down] #'mwheel-scroll)
734 (global-set-key [left-margin wheel-up] #'mwheel-scroll)) 785 (global-set-key [left-margin wheel-up] #'mwheel-scroll)
786 (global-set-key [right-margin mouse-4] #'mwheel-scroll)
787 (global-set-key [right-margin mouse-5] #'mwheel-scroll)
788 (global-set-key [left-margin mouse-4] #'mwheel-scroll)
789 (global-set-key [left-margin mouse-5] #'mwheel-scroll))
735 790
736 791
737### Load the package 792### Load the package
@@ -753,6 +808,11 @@ This has to be done *before* loading the package. It's included in `visual-fill
753## Typographical niceties 808## Typographical niceties
754 809
755 810
811### Variable pitch in text-modes
812
813 (add-hook 'text-mode-hook #'variable-pitch-mode)
814
815
756### Typo mode 816### Typo mode
757 817
758 (straight-use-package 'typo) 818 (straight-use-package 'typo)
@@ -783,147 +843,225 @@ I’ve put org mode under Applications, as opposed to Writing, because it’s m
783 (cuss org-fontify-whole-heading-line t) 843 (cuss org-fontify-whole-heading-line t)
784 (cuss org-fontify-quote-and-verse-blocks t) 844 (cuss org-fontify-quote-and-verse-blocks t)
785 (cuss org-pretty-entities t) 845 (cuss org-pretty-entities t)
786 (cuss org-num-mode +1)
787 (cuss org-src-tab-acts-natively t) 846 (cuss org-src-tab-acts-natively t)
788 (cuss org-src-fontify-natively t) 847 (cuss org-src-fontify-natively t)
789 (cuss org-src-window-setup 'current-window) 848 (cuss org-src-window-setup 'current-window)
790 (cuss org-confirm-babel-evaluate nil) 849 (cuss org-confirm-babel-evaluate nil)
791 (cuss org-directory "~/Org") 850 (cuss org-directory "~/Org")
851 (cuss org-ellipsis "…")
792 852
8531. Tags
793 854
794### Org Agenda 855 (cuss org-tags-column 0
856 "Show tags directly after the headline.
857 This is the best-looking option with variable-pitch fonts.")
858
859 (cussface
860 '(org-tag
861 ((t
862 (:height 0.8 :weight normal :slant italic :foreground "grey40" :inherit
863 (variable-pitch))))))
795 864
796 (cuss org-agenda-files (no-littering-expand-etc-file-name "agenda-files"))
797
798 (if (and (stringp org-agenda-files)
799 (not (file-exists-p org-agenda-files)))
800 (with-temp-buffer (write-file org-agenda-files)))
801
802 (define-key acdw/map (kbd "C-a") #'org-agenda)
803 865
866### General
804 867
805### [A better return in Org mode](http://kitchingroup.cheme.cmu.edu/blog/2017/04/09/A-better-return-in-org-mode/) 8681. [Org Return: DWIM](https://github.com/alphapapa/unpackaged.el#org-return-dwim)
806 869
807 (require 'org-inlinetask) 870 (defun unpackaged/org-element-descendant-of (type element)
808 871 "Return non-nil if ELEMENT is a descendant of TYPE.
809 (defun scimax/org-return (&optional ignore) 872 TYPE should be an element type, like `item' or `paragraph'.
810 "Add new list item, heading or table row with RET. 873 ELEMENT should be a list like that returned by `org-element-context'."
811 A double return on an empty element deletes it. 874 ;; MAYBE: Use `org-element-lineage'.
812 Use a prefix arg to get regular RET." 875 (when-let* ((parent (org-element-property :parent element)))
813 (interactive "P") 876 (or (eq type (car parent))
814 (if ignore 877 (unpackaged/org-element-descendant-of type parent))))
815 (org-return) 878
816 (cond 879 ;;;###autoload
880 (defun unpackaged/org-return-dwim (&optional default)
881 "A helpful replacement for `org-return'. With prefix, call `org-return'.
882
883 On headings, move point to position after entry content. In
884 lists, insert a new item or end the list, with checkbox if
885 appropriate. In tables, insert a new row or end the table."
886 ;; Inspired by John Kitchin: http://kitchingroup.cheme.cmu.edu/blog/2017/04/09/A-better-return-in-org-mode/
887 (interactive "P")
888 (if default
889 (org-return)
890 (cond
891 ;; Act depending on context around point.
892
893 ;; NOTE: I prefer RET to not follow links, but by uncommenting this block, links will be
894 ;; followed.
895
896 ;; ((eq 'link (car (org-element-context)))
897 ;; ;; Link: Open it.
898 ;; (org-open-at-point-global))
899
900 ((org-at-heading-p)
901 ;; Heading: Move to position after entry content.
902 ;; NOTE: This is probably the most interesting feature of this function.
903 (let ((heading-start (org-entry-beginning-position)))
904 (goto-char (org-entry-end-position))
905 (cond ((and (org-at-heading-p)
906 (= heading-start (org-entry-beginning-position)))
907 ;; Entry ends on its heading; add newline after
908 (end-of-line)
909 (insert "\n\n"))
910 (t
911 ;; Entry ends after its heading; back up
912 (forward-line -1)
913 (end-of-line)
914 (when (org-at-heading-p)
915 ;; At the same heading
916 (forward-line)
917 (insert "\n")
918 (forward-line -1))
919 ;; FIXME: looking-back is supposed to be called with more arguments.
920 (while (not (looking-back (rx (repeat 3 (seq (optional blank) "\n"))) nil))
921 (insert "\n"))
922 (forward-line -1)))))
923
924 ((org-at-item-checkbox-p)
925 ;; Checkbox: Insert new item with checkbox.
926 (org-insert-todo-heading nil))
927
928 ((org-in-item-p)
929 ;; Plain list. Yes, this gets a little complicated...
930 (let ((context (org-element-context)))
931 (if (or (eq 'plain-list (car context)) ; First item in list
932 (and (eq 'item (car context))
933 (not (eq (org-element-property :contents-begin context)
934 (org-element-property :contents-end context))))
935 (unpackaged/org-element-descendant-of 'item context)) ; Element in list item, e.g. a link
936 ;; Non-empty item: Add new item.
937 (org-insert-item)
938 ;; Empty item: Close the list.
939 ;; TODO: Do this with org functions rather than operating on the text. Can't seem to find the right function.
940 (delete-region (line-beginning-position) (line-end-position))
941 (insert "\n"))))
942
943 ((when (fboundp 'org-inlinetask-in-task-p)
944 (org-inlinetask-in-task-p))
945 ;; Inline task: Don't insert a new heading.
946 (org-return))
947
948 ((org-at-table-p)
949 (cond ((save-excursion
950 (beginning-of-line)
951 ;; See `org-table-next-field'.
952 (cl-loop with end = (line-end-position)
953 for cell = (org-element-table-cell-parser)
954 always (equal (org-element-property :contents-begin cell)
955 (org-element-property :contents-end cell))
956 while (re-search-forward "|" end t)))
957 ;; Empty row: end the table.
958 (delete-region (line-beginning-position) (line-end-position))
959 (org-return))
960 (t
961 ;; Non-empty row: call `org-return'.
962 (org-return))))
963 (t
964 ;; All other cases: call `org-return'.
965 (org-return)))))
966
967 (with-eval-after-load 'org
968 (define-key org-mode-map (kbd "RET") #'unpackaged/org-return-dwim))
969
9702. Insert blank lines around headers
971
972 from [unpackaged.el](https://github.com/alphapapa/unpackaged.el#ensure-blank-lines-between-headings-and-before-contents).
817 973
818 ((eq 'line-break (car (org-element-context))) 974 ;;;###autoload
819 (org-return t)) 975 (defun unpackaged/org-fix-blank-lines (&optional prefix)
976 "Ensure that blank lines exist between headings and between headings and their contents.
977 With prefix, operate on whole buffer. Ensures that blank lines
978 exist after each headings's drawers."
979 (interactive "P")
980 (org-map-entries (lambda ()
981 (org-with-wide-buffer
982 ;; `org-map-entries' narrows the buffer, which prevents us
983 ;; from seeing newlines before the current heading, so we
984 ;; do this part widened.
985 (while (not (looking-back "\n\n" nil))
986 ;; Insert blank lines before heading.
987 (insert "\n")))
988 (let ((end (org-entry-end-position)))
989 ;; Insert blank lines before entry content
990 (forward-line)
991 (while (and (org-at-planning-p)
992 (< (point) (point-max)))
993 ;; Skip planning lines
994 (forward-line))
995 (while (re-search-forward org-drawer-regexp end t)
996 ;; Skip drawers. You might think that `org-at-drawer-p'
997 ;; would suffice, but for some reason it doesn't work
998 ;; correctly when operating on hidden text. This
999 ;; works, taken from `org-agenda-get-some-entry-text'.
1000 (re-search-forward "^[ \t]*:END:.*\n?" end t)
1001 (goto-char (match-end 0)))
1002 (unless (or (= (point) (point-max))
1003 (org-at-heading-p)
1004 (looking-at-p "\n"))
1005 (insert "\n"))))
1006 t (if prefix
1007 nil
1008 'tree)))
820 1009
821 ;; Open links like usual, unless point is at the end of a line. 1010 1. Add a before-save-hook
822 ;; and if at beginning of line, just press enter.
823 ((or (and (eq 'link (car (org-element-context))) (not (eolp)))
824 (bolp))
825 (org-return))
826 1011
827 ;; It doesn't make sense to add headings in inline tasks. Thanks Anders 1012 (defun cribbed/org-mode-fix-blank-lines ()
828 ;; Johansson! 1013 (when (eq major-mode 'org-mode)
829 ((org-inlinetask-in-task-p) 1014 (let ((current-prefix-arg 4)) ; Emulate C-u
830 (org-return)) 1015 (call-interactively 'unpackaged/org-fix-blank-lines))))
1016
1017 (add-hook 'before-save-hook #'cribbed/org-mode-fix-blank-lines)
1018
1019
1020### Org Agenda
1021
1022 (cuss org-agenda-files
1023 (let ((list))
1024 (dolist (file '(;; add more files to this list
1025 "home.org"
1026 "work.org")
1027 list)
1028 (push (expand-file-name file org-directory) list))))
831 1029
832 ;; checkboxes too 1030 (define-key acdw/map (kbd "C-a") #'org-agenda)
833 ((org-at-item-checkbox-p)
834 (org-insert-todo-heading nil))
835 1031
836 ;; lists end with two blank lines, so we need to make sure we are also not 1032 (cuss org-todo-keywords
837 ;; at the beginning of a line to avoid a loop where a new entry gets 1033 '((sequence "RECUR(r)" "TODO(t)" "|" "DONE(d)")
838 ;; created with only one blank line. 1034 (sequence "|" "CANCELLED(c)")))
839 ((org-in-item-p) 1035
840 (if (save-excursion (beginning-of-line) (org-element-property :contents-begin (org-element-context))) 1036
841 (org-insert-heading) 1037### TODO Capture
842 (beginning-of-line) 1038
843 (delete-region (line-beginning-position) (line-end-position)) 1039
844 (org-return))) 1040## Git
1041
1042 (straight-use-package 'magit)
845 1043
846 ;; org-heading 1044 (define-key acdw/map "g" #'magit-status)
847 ((org-at-heading-p) 1045
848 (if (not (string= "" (org-element-property :title (org-element-context)))) 1046
849 (progn (org-end-of-meta-data) 1047## Beancount mode
850 (org-insert-heading-respect-content) 1048
851 (outline-show-entry)) 1049 (straight-use-package '(beancount-mode
852 (beginning-of-line) 1050 :host github
853 (setf (buffer-substring 1051 :repo "beancount/beancount-mode"))
854 (line-beginning-position) (line-end-position)) ""))) 1052 (require 'beancount)
855 1053
856 ;; tables 1054 (add-to-list 'auto-mode-alist '("\\.beancount\\'" . beancount-mode))
857 ((org-at-table-p)
858 (if (-any?
859 (lambda (x) (not (string= "" x)))
860 (nth
861 (- (org-table-current-dline) 1)
862 (org-table-to-lisp)))
863 (org-return)
864 ;; empty row
865 (beginning-of-line)
866 (setf (buffer-substring
867 (line-beginning-position) (line-end-position)) "")
868 (org-return)))
869 1055
870 ;; fall-through case 1056 (defun acdw/disable-aggressive-indent ()
871 (t 1057 "Turn `aggressive-indent-mode' off for a buffer."
872 (org-return))))) 1058 (aggressive-indent-mode -1))
873 1059
1060 (add-hook 'beancount-mode-hook #'outline-minor-mode)
1061 (add-hook 'beancount-mode-hook #'acdw/disable-aggressive-indent)
874 1062
875 (define-key org-mode-map (kbd "RET") 1063 (define-key beancount-mode-map (kbd "M-n") #'outline-next-visible-heading)
876 'scimax/org-return) 1064 (define-key beancount-mode-map (kbd "M-p") #'outline-previous-visible-heading)
877
878
879### Insert blank lines around headers
880
881from [unpackaged.el](https://github.com/alphapapa/unpackaged.el#ensure-blank-lines-between-headings-and-before-contents).
882
883 ;;;###autoload
884 (defun unpackaged/org-fix-blank-lines (&optional prefix)
885 "Ensure that blank lines exist between headings and between headings and their contents.
886 With prefix, operate on whole buffer. Ensures that blank lines
887 exist after each headings's drawers."
888 (interactive "P")
889 (org-map-entries (lambda ()
890 (org-with-wide-buffer
891 ;; `org-map-entries' narrows the buffer, which prevents us
892 ;; from seeing newlines before the current heading, so we
893 ;; do this part widened.
894 (while (not (looking-back "\n\n" nil))
895 ;; Insert blank lines before heading.
896 (insert "\n")))
897 (let ((end (org-entry-end-position)))
898 ;; Insert blank lines before entry content
899 (forward-line)
900 (while (and (org-at-planning-p)
901 (< (point) (point-max)))
902 ;; Skip planning lines
903 (forward-line))
904 (while (re-search-forward org-drawer-regexp end t)
905 ;; Skip drawers. You might think that `org-at-drawer-p'
906 ;; would suffice, but for some reason it doesn't work
907 ;; correctly when operating on hidden text. This
908 ;; works, taken from `org-agenda-get-some-entry-text'.
909 (re-search-forward "^[ \t]*:END:.*\n?" end t)
910 (goto-char (match-end 0)))
911 (unless (or (= (point) (point-max))
912 (org-at-heading-p)
913 (looking-at-p "\n"))
914 (insert "\n"))))
915 t (if prefix
916 nil
917 'tree)))
918
9191. Add a before-save-hook
920
921 (defun cribbed/org-mode-fix-blank-lines ()
922 (when (eq major-mode 'org-mode)
923 (let ((current-prefix-arg 4)) ; Emulate C-u
924 (call-interactively 'unpackaged/org-fix-blank-lines))))
925
926 (add-hook 'before-save-hook #'cribbed/org-mode-fix-blank-lines)
927 1065
928 1066
929# Appendices 1067# Appendices
@@ -968,7 +1106,7 @@ I realized I didn’t need `early-init.el`, since it really only set `load-prefe
968 (when (file-newer-than-file-p config (expand-file-name 1106 (when (file-newer-than-file-p config (expand-file-name
969 "README.md" 1107 "README.md"
970 user-emacs-directory)) 1108 user-emacs-directory))
971 (message "Exporting README.md...") 1109 (message "%s" "Exporting README.md...")
972 (require 'ox-md) 1110 (require 'ox-md)
973 (with-demoted-errors "Problem exporting README.md: %S" 1111 (with-demoted-errors "Problem exporting README.md: %S"
974 (org-md-export-to-markdown))) 1112 (org-md-export-to-markdown)))
@@ -976,11 +1114,11 @@ I realized I didn’t need `early-init.el`, since it really only set `load-prefe
976 (when (file-newer-than-file-p config (expand-file-name 1114 (when (file-newer-than-file-p config (expand-file-name
977 "config.el" 1115 "config.el"
978 user-emacs-directory)) 1116 user-emacs-directory))
979 (message "Tangling config.org...") 1117 (message "%s" "Tangling config.org...")
980 (require 'org) 1118 (require 'org)
981 (let ((inits (org-babel-tangle))) 1119 (let ((inits (org-babel-tangle)))
982 ;; byte-compile resulting files 1120 ;; byte-compile resulting files
983 (message "Byte-compiling...") 1121 (message "%s" "Byte-compiling...")
984 (dolist (f inits) 1122 (dolist (f inits)
985 (when (string-match "\\.el\\'" f) 1123 (when (string-match "\\.el\\'" f)
986 (byte-compile-file f (not disable-load))))))))))) 1124 (byte-compile-file f (not disable-load)))))))))))
@@ -991,7 +1129,7 @@ I realized I didn’t need `early-init.el`, since it really only set `load-prefe
991 1129
992### emacsdc 1130### emacsdc
993 1131
994Here's a wrapper script that'll start `emacs daemon` if there isn't 1132Here's a wrapper script that'll start `emacs --daemon` if there isn't
995one, and then launch `emacsclient` with the arguments. I'd recommend 1133one, and then launch `emacsclient` with the arguments. I'd recommend
996installing with either `ln -s bin/emacsdc $HOME/.local/bin/`, or 1134installing with either `ln -s bin/emacsdc $HOME/.local/bin/`, or
997adding `$HOME/.local/bin` to your `$PATH`. 1135adding `$HOME/.local/bin` to your `$PATH`.
@@ -1004,9 +1142,18 @@ adding `$HOME/.local/bin` to your `$PATH`.
1004 1142
1005### Emacs.cmd 1143### Emacs.cmd
1006 1144
1007Here’s a wrapper script that’ll run Emacs on Windows, with a custom `$HOME`. I have mine setup like this: Emacs is downloaded from [the GNU mirror](https://mirrors.tripadvisor.com/gnu/emacs/windows/emacs-27/emacs-27.1-x86_64.zip) and unzipped to `~/Downloads/emacs/`. `Emacs.cmd` sets `$HOME` to `~/Downloads/emacshome/`, which is where `.emacs.d` is, and whatever else I might want to throw in there. 1145Here's a wrapper script that'll run Emacs on Windows, with a custom
1146`$HOME`. I have mine setup like this: Emacs is downloaded from [the
1147GNU mirror](https://mirrors.tripadvisor.com/gnu/emacs/windows/emacs-27/emacs-27.1-x86_64.zip) and unzipped to `~/Downloads/emacs/`. `Emacs.cmd` sets
1148`$HOME` to `~/Downloads/emacshome/`, which is where `.emacs.d` is, and
1149whatever else I might want to throw in there.
1008 1150
1009 set HOME=%~dp0..\..\emacshome 1151 set HOME=%~dp0..\..\emacshome
1152
1153 REM Run "Quick Mode"
1154 REM "%~dp0runemacs.exe" -Q %*
1155
1156 REM Regular
1010 "%~dp0runemacs.exe" %* 1157 "%~dp0runemacs.exe" %*
1011 1158
1012 1159