summary refs log tree commit diff stats
path: root/config.org
diff options
context:
space:
mode:
authorCase Duckworth2021-01-01 10:57:27 -0600
committerCase Duckworth2021-01-01 10:57:27 -0600
commit19acf44a2997f675fe38511a91d4b7264b527eb4 (patch)
tree0cb4e0c60ba5a6eb8e1fd981d3e8cb73fa716b63 /config.org
parentAdd org-tag face (diff)
downloademacs-19acf44a2997f675fe38511a91d4b7264b527eb4.tar.gz
emacs-19acf44a2997f675fe38511a91d4b7264b527eb4.zip
Change org-return-dwim function
Diffstat (limited to 'config.org')
-rw-r--r--config.org171
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'."
1063A double return on an empty element deletes it. 1063 ;; MAYBE: Use `org-element-lineage'.
1064Use 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