diff options
-rw-r--r-- | config.org | 324 |
1 files changed, 167 insertions, 157 deletions
diff --git a/config.org b/config.org index 2ee82e4..1bac3d5 100644 --- a/config.org +++ b/config.org | |||
@@ -5,7 +5,7 @@ | |||
5 | #+EXPORT_FILE_NAME: README.md | 5 | #+EXPORT_FILE_NAME: README.md |
6 | #+OPTIONS: toc:nil | 6 | #+OPTIONS: toc:nil |
7 | #+BANKRUPTCY_COUNT: 3.2 | 7 | #+BANKRUPTCY_COUNT: 3.2 |
8 | #+Time-stamp: <2021-01-01 11:00:05 acdw> | 8 | #+Time-stamp: <2021-01-02 10:01:56 acdw> |
9 | 9 | ||
10 | Why the hell not, let’s do this again. | 10 | Why the hell not, let’s do this again. |
11 | 11 | ||
@@ -1074,175 +1074,185 @@ I’ve put org mode under Applications, as opposed to Writing, because it’s m | |||
1074 | (variable-pitch)))))) | 1074 | (variable-pitch)))))) |
1075 | #+end_src | 1075 | #+end_src |
1076 | 1076 | ||
1077 | *** Org Agenda | 1077 | *** General |
1078 | |||
1079 | #+BEGIN_SRC emacs-lisp | ||
1080 | (cuss org-agenda-files (no-littering-expand-etc-file-name "agenda-files")) | ||
1081 | 1078 | ||
1082 | (if (and (stringp org-agenda-files) | 1079 | **** [[https://github.com/alphapapa/unpackaged.el#org-return-dwim][Org Return: DWIM]] |
1083 | (not (file-exists-p org-agenda-files))) | ||
1084 | (with-temp-buffer (write-file org-agenda-files))) | ||
1085 | 1080 | ||
1086 | (define-key acdw/map (kbd "C-a") #'org-agenda) | 1081 | #+BEGIN_SRC emacs-lisp |
1087 | #+END_SRC | 1082 | (defun unpackaged/org-element-descendant-of (type element) |
1083 | "Return non-nil if ELEMENT is a descendant of TYPE. | ||
1084 | TYPE should be an element type, like `item' or `paragraph'. | ||
1085 | ELEMENT should be a list like that returned by `org-element-context'." | ||
1086 | ;; MAYBE: Use `org-element-lineage'. | ||
1087 | (when-let* ((parent (org-element-property :parent element))) | ||
1088 | (or (eq type (car parent)) | ||
1089 | (unpackaged/org-element-descendant-of type parent)))) | ||
1090 | |||
1091 | ;;;###autoload | ||
1092 | (defun unpackaged/org-return-dwim (&optional default) | ||
1093 | "A helpful replacement for `org-return'. With prefix, call `org-return'. | ||
1094 | |||
1095 | On headings, move point to position after entry content. In | ||
1096 | lists, insert a new item or end the list, with checkbox if | ||
1097 | appropriate. In tables, insert a new row or end the table." | ||
1098 | ;; Inspired by John Kitchin: http://kitchingroup.cheme.cmu.edu/blog/2017/04/09/A-better-return-in-org-mode/ | ||
1099 | (interactive "P") | ||
1100 | (if default | ||
1101 | (org-return) | ||
1102 | (cond | ||
1103 | ;; Act depending on context around point. | ||
1104 | |||
1105 | ;; NOTE: I prefer RET to not follow links, but by uncommenting this block, links will be | ||
1106 | ;; followed. | ||
1107 | |||
1108 | ;; ((eq 'link (car (org-element-context))) | ||
1109 | ;; ;; Link: Open it. | ||
1110 | ;; (org-open-at-point-global)) | ||
1111 | |||
1112 | ((org-at-heading-p) | ||
1113 | ;; Heading: Move to position after entry content. | ||
1114 | ;; NOTE: This is probably the most interesting feature of this function. | ||
1115 | (let ((heading-start (org-entry-beginning-position))) | ||
1116 | (goto-char (org-entry-end-position)) | ||
1117 | (cond ((and (org-at-heading-p) | ||
1118 | (= heading-start (org-entry-beginning-position))) | ||
1119 | ;; Entry ends on its heading; add newline after | ||
1120 | (end-of-line) | ||
1121 | (insert "\n\n")) | ||
1122 | (t | ||
1123 | ;; Entry ends after its heading; back up | ||
1124 | (forward-line -1) | ||
1125 | (end-of-line) | ||
1126 | (when (org-at-heading-p) | ||
1127 | ;; At the same heading | ||
1128 | (forward-line) | ||
1129 | (insert "\n") | ||
1130 | (forward-line -1)) | ||
1131 | ;; FIXME: looking-back is supposed to be called with more arguments. | ||
1132 | (while (not (looking-back (rx (repeat 3 (seq (optional blank) "\n"))) nil)) | ||
1133 | (insert "\n")) | ||
1134 | (forward-line -1))))) | ||
1135 | |||
1136 | ((org-at-item-checkbox-p) | ||
1137 | ;; Checkbox: Insert new item with checkbox. | ||
1138 | (org-insert-todo-heading nil)) | ||
1139 | |||
1140 | ((org-in-item-p) | ||
1141 | ;; Plain list. Yes, this gets a little complicated... | ||
1142 | (let ((context (org-element-context))) | ||
1143 | (if (or (eq 'plain-list (car context)) ; First item in list | ||
1144 | (and (eq 'item (car context)) | ||
1145 | (not (eq (org-element-property :contents-begin context) | ||
1146 | (org-element-property :contents-end context)))) | ||
1147 | (unpackaged/org-element-descendant-of 'item context)) ; Element in list item, e.g. a link | ||
1148 | ;; Non-empty item: Add new item. | ||
1149 | (org-insert-item) | ||
1150 | ;; Empty item: Close the list. | ||
1151 | ;; TODO: Do this with org functions rather than operating on the text. Can't seem to find the right function. | ||
1152 | (delete-region (line-beginning-position) (line-end-position)) | ||
1153 | (insert "\n")))) | ||
1154 | |||
1155 | ((when (fboundp 'org-inlinetask-in-task-p) | ||
1156 | (org-inlinetask-in-task-p)) | ||
1157 | ;; Inline task: Don't insert a new heading. | ||
1158 | (org-return)) | ||
1159 | |||
1160 | ((org-at-table-p) | ||
1161 | (cond ((save-excursion | ||
1162 | (beginning-of-line) | ||
1163 | ;; See `org-table-next-field'. | ||
1164 | (cl-loop with end = (line-end-position) | ||
1165 | for cell = (org-element-table-cell-parser) | ||
1166 | always (equal (org-element-property :contents-begin cell) | ||
1167 | (org-element-property :contents-end cell)) | ||
1168 | while (re-search-forward "|" end t))) | ||
1169 | ;; Empty row: end the table. | ||
1170 | (delete-region (line-beginning-position) (line-end-position)) | ||
1171 | (org-return)) | ||
1172 | (t | ||
1173 | ;; Non-empty row: call `org-return'. | ||
1174 | (org-return)))) | ||
1175 | (t | ||
1176 | ;; All other cases: call `org-return'. | ||
1177 | (org-return))))) | ||
1178 | |||
1179 | (with-eval-after-load 'org | ||
1180 | (define-key org-mode-map (kbd "RET") #'unpackaged/org-return-dwim)) | ||
1181 | #+END_SRC | ||
1088 | 1182 | ||
1089 | *** [[https://github.com/alphapapa/unpackaged.el#org-return-dwim][Org Return: DWIM]] | 1183 | **** Insert blank lines around headers |
1090 | 1184 | ||
1091 | #+BEGIN_SRC emacs-lisp | 1185 | from [[https://github.com/alphapapa/unpackaged.el#ensure-blank-lines-between-headings-and-before-contents][unpackaged.el]]. |
1092 | (defun unpackaged/org-element-descendant-of (type element) | ||
1093 | "Return non-nil if ELEMENT is a descendant of TYPE. | ||
1094 | TYPE should be an element type, like `item' or `paragraph'. | ||
1095 | ELEMENT should be a list like that returned by `org-element-context'." | ||
1096 | ;; MAYBE: Use `org-element-lineage'. | ||
1097 | (when-let* ((parent (org-element-property :parent element))) | ||
1098 | (or (eq type (car parent)) | ||
1099 | (unpackaged/org-element-descendant-of type parent)))) | ||
1100 | |||
1101 | ;;;###autoload | ||
1102 | (defun unpackaged/org-return-dwim (&optional default) | ||
1103 | "A helpful replacement for `org-return'. With prefix, call `org-return'. | ||
1104 | |||
1105 | On headings, move point to position after entry content. In | ||
1106 | lists, insert a new item or end the list, with checkbox if | ||
1107 | appropriate. In tables, insert a new row or end the table." | ||
1108 | ;; Inspired by John Kitchin: http://kitchingroup.cheme.cmu.edu/blog/2017/04/09/A-better-return-in-org-mode/ | ||
1109 | (interactive "P") | ||
1110 | (if default | ||
1111 | (org-return) | ||
1112 | (cond | ||
1113 | ;; Act depending on context around point. | ||
1114 | |||
1115 | ;; NOTE: I prefer RET to not follow links, but by uncommenting this block, links will be | ||
1116 | ;; followed. | ||
1117 | |||
1118 | ;; ((eq 'link (car (org-element-context))) | ||
1119 | ;; ;; Link: Open it. | ||
1120 | ;; (org-open-at-point-global)) | ||
1121 | |||
1122 | ((org-at-heading-p) | ||
1123 | ;; Heading: Move to position after entry content. | ||
1124 | ;; NOTE: This is probably the most interesting feature of this function. | ||
1125 | (let ((heading-start (org-entry-beginning-position))) | ||
1126 | (goto-char (org-entry-end-position)) | ||
1127 | (cond ((and (org-at-heading-p) | ||
1128 | (= heading-start (org-entry-beginning-position))) | ||
1129 | ;; Entry ends on its heading; add newline after | ||
1130 | (end-of-line) | ||
1131 | (insert "\n\n")) | ||
1132 | (t | ||
1133 | ;; Entry ends after its heading; back up | ||
1134 | (forward-line -1) | ||
1135 | (end-of-line) | ||
1136 | (when (org-at-heading-p) | ||
1137 | ;; At the same heading | ||
1138 | (forward-line) | ||
1139 | (insert "\n") | ||
1140 | (forward-line -1)) | ||
1141 | ;; FIXME: looking-back is supposed to be called with more arguments. | ||
1142 | (while (not (looking-back (rx (repeat 3 (seq (optional blank) "\n"))))) | ||
1143 | (insert "\n")) | ||
1144 | (forward-line -1))))) | ||
1145 | |||
1146 | ((org-at-item-checkbox-p) | ||
1147 | ;; Checkbox: Insert new item with checkbox. | ||
1148 | (org-insert-todo-heading nil)) | ||
1149 | |||
1150 | ((org-in-item-p) | ||
1151 | ;; Plain list. Yes, this gets a little complicated... | ||
1152 | (let ((context (org-element-context))) | ||
1153 | (if (or (eq 'plain-list (car context)) ; First item in list | ||
1154 | (and (eq 'item (car context)) | ||
1155 | (not (eq (org-element-property :contents-begin context) | ||
1156 | (org-element-property :contents-end context)))) | ||
1157 | (unpackaged/org-element-descendant-of 'item context)) ; Element in list item, e.g. a link | ||
1158 | ;; Non-empty item: Add new item. | ||
1159 | (org-insert-item) | ||
1160 | ;; Empty item: Close the list. | ||
1161 | ;; TODO: Do this with org functions rather than operating on the text. Can't seem to find the right function. | ||
1162 | (delete-region (line-beginning-position) (line-end-position)) | ||
1163 | (insert "\n")))) | ||
1164 | |||
1165 | ((when (fboundp 'org-inlinetask-in-task-p) | ||
1166 | (org-inlinetask-in-task-p)) | ||
1167 | ;; Inline task: Don't insert a new heading. | ||
1168 | (org-return)) | ||
1169 | |||
1170 | ((org-at-table-p) | ||
1171 | (cond ((save-excursion | ||
1172 | (beginning-of-line) | ||
1173 | ;; See `org-table-next-field'. | ||
1174 | (cl-loop with end = (line-end-position) | ||
1175 | for cell = (org-element-table-cell-parser) | ||
1176 | always (equal (org-element-property :contents-begin cell) | ||
1177 | (org-element-property :contents-end cell)) | ||
1178 | while (re-search-forward "|" end t))) | ||
1179 | ;; Empty row: end the table. | ||
1180 | (delete-region (line-beginning-position) (line-end-position)) | ||
1181 | (org-return)) | ||
1182 | (t | ||
1183 | ;; Non-empty row: call `org-return'. | ||
1184 | (org-return)))) | ||
1185 | (t | ||
1186 | ;; All other cases: call `org-return'. | ||
1187 | (org-return))))) | ||
1188 | 1186 | ||
1189 | (with-eval-after-load 'org | 1187 | #+BEGIN_SRC emacs-lisp |
1190 | (define-key org-mode-map (kbd "RET") #'unpackaged/org-return-dwim)) | 1188 | ;;;###autoload |
1191 | #+END_SRC | 1189 | (defun unpackaged/org-fix-blank-lines (&optional prefix) |
1190 | "Ensure that blank lines exist between headings and between headings and their contents. | ||
1191 | With prefix, operate on whole buffer. Ensures that blank lines | ||
1192 | exist after each headings's drawers." | ||
1193 | (interactive "P") | ||
1194 | (org-map-entries (lambda () | ||
1195 | (org-with-wide-buffer | ||
1196 | ;; `org-map-entries' narrows the buffer, which prevents us | ||
1197 | ;; from seeing newlines before the current heading, so we | ||
1198 | ;; do this part widened. | ||
1199 | (while (not (looking-back "\n\n" nil)) | ||
1200 | ;; Insert blank lines before heading. | ||
1201 | (insert "\n"))) | ||
1202 | (let ((end (org-entry-end-position))) | ||
1203 | ;; Insert blank lines before entry content | ||
1204 | (forward-line) | ||
1205 | (while (and (org-at-planning-p) | ||
1206 | (< (point) (point-max))) | ||
1207 | ;; Skip planning lines | ||
1208 | (forward-line)) | ||
1209 | (while (re-search-forward org-drawer-regexp end t) | ||
1210 | ;; Skip drawers. You might think that `org-at-drawer-p' | ||
1211 | ;; would suffice, but for some reason it doesn't work | ||
1212 | ;; correctly when operating on hidden text. This | ||
1213 | ;; works, taken from `org-agenda-get-some-entry-text'. | ||
1214 | (re-search-forward "^[ \t]*:END:.*\n?" end t) | ||
1215 | (goto-char (match-end 0))) | ||
1216 | (unless (or (= (point) (point-max)) | ||
1217 | (org-at-heading-p) | ||
1218 | (looking-at-p "\n")) | ||
1219 | (insert "\n")))) | ||
1220 | t (if prefix | ||
1221 | nil | ||
1222 | 'tree))) | ||
1223 | #+END_SRC | ||
1192 | 1224 | ||
1193 | *** Insert blank lines around headers | 1225 | ***** Add a before-save-hook |
1194 | 1226 | ||
1195 | from [[https://github.com/alphapapa/unpackaged.el#ensure-blank-lines-between-headings-and-before-contents][unpackaged.el]]. | 1227 | #+BEGIN_SRC emacs-lisp |
1228 | (defun cribbed/org-mode-fix-blank-lines () | ||
1229 | (when (eq major-mode 'org-mode) | ||
1230 | (let ((current-prefix-arg 4)) ; Emulate C-u | ||
1231 | (call-interactively 'unpackaged/org-fix-blank-lines)))) | ||
1196 | 1232 | ||
1197 | #+BEGIN_SRC emacs-lisp | 1233 | (add-hook 'before-save-hook #'cribbed/org-mode-fix-blank-lines) |
1198 | ;;;###autoload | 1234 | #+END_SRC |
1199 | (defun unpackaged/org-fix-blank-lines (&optional prefix) | ||
1200 | "Ensure that blank lines exist between headings and between headings and their contents. | ||
1201 | With prefix, operate on whole buffer. Ensures that blank lines | ||
1202 | exist after each headings's drawers." | ||
1203 | (interactive "P") | ||
1204 | (org-map-entries (lambda () | ||
1205 | (org-with-wide-buffer | ||
1206 | ;; `org-map-entries' narrows the buffer, which prevents us | ||
1207 | ;; from seeing newlines before the current heading, so we | ||
1208 | ;; do this part widened. | ||
1209 | (while (not (looking-back "\n\n" nil)) | ||
1210 | ;; Insert blank lines before heading. | ||
1211 | (insert "\n"))) | ||
1212 | (let ((end (org-entry-end-position))) | ||
1213 | ;; Insert blank lines before entry content | ||
1214 | (forward-line) | ||
1215 | (while (and (org-at-planning-p) | ||
1216 | (< (point) (point-max))) | ||
1217 | ;; Skip planning lines | ||
1218 | (forward-line)) | ||
1219 | (while (re-search-forward org-drawer-regexp end t) | ||
1220 | ;; Skip drawers. You might think that `org-at-drawer-p' | ||
1221 | ;; would suffice, but for some reason it doesn't work | ||
1222 | ;; correctly when operating on hidden text. This | ||
1223 | ;; works, taken from `org-agenda-get-some-entry-text'. | ||
1224 | (re-search-forward "^[ \t]*:END:.*\n?" end t) | ||
1225 | (goto-char (match-end 0))) | ||
1226 | (unless (or (= (point) (point-max)) | ||
1227 | (org-at-heading-p) | ||
1228 | (looking-at-p "\n")) | ||
1229 | (insert "\n")))) | ||
1230 | t (if prefix | ||
1231 | nil | ||
1232 | 'tree))) | ||
1233 | #+END_SRC | ||
1234 | 1235 | ||
1235 | **** Add a before-save-hook | 1236 | *** Org Agenda |
1236 | 1237 | ||
1237 | #+BEGIN_SRC emacs-lisp | 1238 | #+BEGIN_SRC emacs-lisp |
1238 | (defun cribbed/org-mode-fix-blank-lines () | 1239 | (cuss org-agenda-files |
1239 | (when (eq major-mode 'org-mode) | 1240 | (let ((list)) |
1240 | (let ((current-prefix-arg 4)) ; Emulate C-u | 1241 | (dolist (file '(;; add more files to this list |
1241 | (call-interactively 'unpackaged/org-fix-blank-lines)))) | 1242 | "home.org" |
1242 | 1243 | "work.org") | |
1243 | (add-hook 'before-save-hook #'cribbed/org-mode-fix-blank-lines) | 1244 | list) |
1245 | (push (expand-file-name file org-directory) list)))) | ||
1246 | |||
1247 | (define-key acdw/map (kbd "C-a") #'org-agenda) | ||
1248 | |||
1249 | (cuss org-todo-keywords | ||
1250 | '((sequence "RECUR(r)" "TODO(t)" "|" "DONE(d)") | ||
1251 | (sequence "|" "CANCELLED(c)"))) | ||
1244 | #+END_SRC | 1252 | #+END_SRC |
1245 | 1253 | ||
1254 | *** TODO Capture | ||
1255 | |||
1246 | ** Git | 1256 | ** Git |
1247 | 1257 | ||
1248 | #+begin_src emacs-lisp | 1258 | #+begin_src emacs-lisp |