diff options
author | Case Duckworth | 2021-01-01 10:57:27 -0600 |
---|---|---|
committer | Case Duckworth | 2021-01-01 10:57:27 -0600 |
commit | 19acf44a2997f675fe38511a91d4b7264b527eb4 (patch) | |
tree | 0cb4e0c60ba5a6eb8e1fd981d3e8cb73fa716b63 | |
parent | Add org-tag face (diff) | |
download | emacs-19acf44a2997f675fe38511a91d4b7264b527eb4.tar.gz emacs-19acf44a2997f675fe38511a91d4b7264b527eb4.zip |
Change org-return-dwim function
-rw-r--r-- | config.org | 171 |
1 files changed, 100 insertions, 71 deletions
diff --git a/config.org b/config.org index b4a6d6f..0435dc9 100644 --- a/config.org +++ b/config.org | |||
@@ -1053,79 +1053,108 @@ I’ve put org mode under Applications, as opposed to Writing, because it’s m | |||
1053 | (define-key acdw/map (kbd "C-a") #'org-agenda) | 1053 | (define-key acdw/map (kbd "C-a") #'org-agenda) |
1054 | #+END_SRC | 1054 | #+END_SRC |
1055 | 1055 | ||
1056 | *** [[http://kitchingroup.cheme.cmu.edu/blog/2017/04/09/A-better-return-in-org-mode/][A better return in Org mode]] | 1056 | *** [[https://github.com/alphapapa/unpackaged.el#org-return-dwim][Org Return: DWIM]] |
1057 | 1057 | ||
1058 | #+BEGIN_SRC emacs-lisp | 1058 | #+BEGIN_SRC emacs-lisp |
1059 | (require 'org-inlinetask) | 1059 | (defun unpackaged/org-element-descendant-of (type element) |
1060 | 1060 | "Return non-nil if ELEMENT is a descendant of TYPE. | |
1061 | (defun scimax/org-return (&optional ignore) | 1061 | TYPE should be an element type, like `item' or `paragraph'. |
1062 | "Add new list item, heading or table row with RET. | 1062 | ELEMENT should be a list like that returned by `org-element-context'." |
1063 | A double return on an empty element deletes it. | 1063 | ;; MAYBE: Use `org-element-lineage'. |
1064 | Use a prefix arg to get regular RET." | 1064 | (when-let* ((parent (org-element-property :parent element))) |
1065 | (interactive "P") | 1065 | (or (eq type (car parent)) |
1066 | (if ignore | 1066 | (unpackaged/org-element-descendant-of type parent)))) |
1067 | (org-return) | 1067 | |
1068 | (cond | 1068 | ;;;###autoload |
1069 | 1069 | (defun unpackaged/org-return-dwim (&optional default) | |
1070 | ((eq 'line-break (car (org-element-context))) | 1070 | "A helpful replacement for `org-return'. With prefix, call `org-return'. |
1071 | (org-return t)) | 1071 | |
1072 | 1072 | On headings, move point to position after entry content. In | |
1073 | ;; Open links like usual, unless point is at the end of a line. | 1073 | lists, insert a new item or end the list, with checkbox if |
1074 | ;; and if at beginning of line, just press enter. | 1074 | appropriate. In tables, insert a new row or end the table." |
1075 | ((or (and (eq 'link (car (org-element-context))) (not (eolp))) | 1075 | ;; Inspired by John Kitchin: http://kitchingroup.cheme.cmu.edu/blog/2017/04/09/A-better-return-in-org-mode/ |
1076 | (bolp)) | 1076 | (interactive "P") |
1077 | (org-return)) | 1077 | (if default |
1078 | 1078 | (org-return) | |
1079 | ;; It doesn't make sense to add headings in inline tasks. Thanks Anders | 1079 | (cond |
1080 | ;; Johansson! | 1080 | ;; Act depending on context around point. |
1081 | ((org-inlinetask-in-task-p) | 1081 | |
1082 | (org-return)) | 1082 | ;; NOTE: I prefer RET to not follow links, but by uncommenting this block, links will be |
1083 | 1083 | ;; followed. | |
1084 | ;; checkboxes too | 1084 | |
1085 | ((org-at-item-checkbox-p) | 1085 | ;; ((eq 'link (car (org-element-context))) |
1086 | (org-insert-todo-heading nil)) | 1086 | ;; ;; Link: Open it. |
1087 | 1087 | ;; (org-open-at-point-global)) | |
1088 | ;; lists end with two blank lines, so we need to make sure we are also not | 1088 | |
1089 | ;; at the beginning of a line to avoid a loop where a new entry gets | 1089 | ((org-at-heading-p) |
1090 | ;; created with only one blank line. | 1090 | ;; Heading: Move to position after entry content. |
1091 | ((org-in-item-p) | 1091 | ;; NOTE: This is probably the most interesting feature of this function. |
1092 | (if (save-excursion (beginning-of-line) (org-element-property :contents-begin (org-element-context))) | 1092 | (let ((heading-start (org-entry-beginning-position))) |
1093 | (org-insert-heading) | 1093 | (goto-char (org-entry-end-position)) |
1094 | (beginning-of-line) | 1094 | (cond ((and (org-at-heading-p) |
1095 | (delete-region (line-beginning-position) (line-end-position)) | 1095 | (= heading-start (org-entry-beginning-position))) |
1096 | (org-return))) | 1096 | ;; Entry ends on its heading; add newline after |
1097 | 1097 | (end-of-line) | |
1098 | ;; org-heading | 1098 | (insert "\n\n")) |
1099 | ((org-at-heading-p) | 1099 | (t |
1100 | (if (not (string= "" (org-element-property :title (org-element-context)))) | 1100 | ;; Entry ends after its heading; back up |
1101 | (progn (org-end-of-meta-data) | 1101 | (forward-line -1) |
1102 | (org-insert-heading-respect-content) | 1102 | (end-of-line) |
1103 | (outline-show-entry)) | 1103 | (when (org-at-heading-p) |
1104 | (beginning-of-line) | 1104 | ;; At the same heading |
1105 | (setf (buffer-substring | 1105 | (forward-line) |
1106 | (line-beginning-position) (line-end-position)) ""))) | 1106 | (insert "\n") |
1107 | 1107 | (forward-line -1)) | |
1108 | ;; tables | 1108 | ;; FIXME: looking-back is supposed to be called with more arguments. |
1109 | ((org-at-table-p) | 1109 | (while (not (looking-back (rx (repeat 3 (seq (optional blank) "\n"))))) |
1110 | (if (-any? | 1110 | (insert "\n")) |
1111 | (lambda (x) (not (string= "" x))) | 1111 | (forward-line -1))))) |
1112 | (nth | 1112 | |
1113 | (- (org-table-current-dline) 1) | 1113 | ((org-at-item-checkbox-p) |
1114 | (org-table-to-lisp))) | 1114 | ;; Checkbox: Insert new item with checkbox. |
1115 | (org-return) | 1115 | (org-insert-todo-heading nil)) |
1116 | ;; empty row | 1116 | |
1117 | (beginning-of-line) | 1117 | ((org-in-item-p) |
1118 | (setf (buffer-substring | 1118 | ;; Plain list. Yes, this gets a little complicated... |
1119 | (line-beginning-position) (line-end-position)) "") | 1119 | (let ((context (org-element-context))) |
1120 | (org-return))) | 1120 | (if (or (eq 'plain-list (car context)) ; First item in list |
1121 | 1121 | (and (eq 'item (car context)) | |
1122 | ;; fall-through case | 1122 | (not (eq (org-element-property :contents-begin context) |
1123 | (t | 1123 | (org-element-property :contents-end context)))) |
1124 | (org-return))))) | 1124 | (unpackaged/org-element-descendant-of 'item context)) ; Element in list item, e.g. a link |
1125 | 1125 | ;; Non-empty item: Add new item. | |
1126 | 1126 | (org-insert-item) | |
1127 | (define-key org-mode-map (kbd "RET") | 1127 | ;; Empty item: Close the list. |
1128 | 'scimax/org-return) | 1128 | ;; TODO: Do this with org functions rather than operating on the text. Can't seem to find the right function. |
1129 | (delete-region (line-beginning-position) (line-end-position)) | ||
1130 | (insert "\n")))) | ||
1131 | |||
1132 | ((when (fboundp 'org-inlinetask-in-task-p) | ||
1133 | (org-inlinetask-in-task-p)) | ||
1134 | ;; Inline task: Don't insert a new heading. | ||
1135 | (org-return)) | ||
1136 | |||
1137 | ((org-at-table-p) | ||
1138 | (cond ((save-excursion | ||
1139 | (beginning-of-line) | ||
1140 | ;; See `org-table-next-field'. | ||
1141 | (cl-loop with end = (line-end-position) | ||
1142 | for cell = (org-element-table-cell-parser) | ||
1143 | always (equal (org-element-property :contents-begin cell) | ||
1144 | (org-element-property :contents-end cell)) | ||
1145 | while (re-search-forward "|" end t))) | ||
1146 | ;; Empty row: end the table. | ||
1147 | (delete-region (line-beginning-position) (line-end-position)) | ||
1148 | (org-return)) | ||
1149 | (t | ||
1150 | ;; Non-empty row: call `org-return'. | ||
1151 | (org-return)))) | ||
1152 | (t | ||
1153 | ;; All other cases: call `org-return'. | ||
1154 | (org-return))))) | ||
1155 | |||
1156 | (with-eval-after-load 'org | ||
1157 | (define-key org-mode-map (kbd "RET") #'unpackaged/org-return-dwim)) | ||
1129 | #+END_SRC | 1158 | #+END_SRC |
1130 | 1159 | ||
1131 | *** Insert blank lines around headers | 1160 | *** Insert blank lines around headers |