branch: externals/org commit ec737554d053b2ce66a30ffc503c80c30729bebd Author: Ihor Radchenko <yanta...@gmail.com> Commit: Ihor Radchenko <yanta...@gmail.com>
org.el/org-end-of-subtree: Support cache and passing element arg --- lisp/org.el | 58 ++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/lisp/org.el b/lisp/org.el index 158e37d..196a264 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -20847,8 +20847,8 @@ If there is no such heading, return nil." (unless (< (funcall outline-level) level) (point))))) -(defun org-end-of-subtree (&optional invisible-ok to-heading) - "Goto to the end of a subtree." +(defun org-end-of-subtree (&optional invisible-ok to-heading element) + "Goto to the end of a subtree at point or for ELEMENT heading." ;; This contains an exact copy of the original function, but it uses ;; `org-back-to-heading-or-point-min', to make it work also in invisible ;; trees and before first headline. And is uses an invisible-ok argument. @@ -20857,31 +20857,37 @@ If there is no such heading, return nil." ;; with many children and grandchildren etc, this can be much faster ;; than the outline version. (org-back-to-heading-or-point-min invisible-ok) - (let ((first t) - (level (funcall outline-level))) - (cond ((= level 0) - (goto-char (point-max))) - ((and (derived-mode-p 'org-mode) (< level 1000)) - ;; A true heading (not a plain list item), in Org - ;; This means we can easily find the end by looking - ;; only for the right number of stars. Using a regexp to do - ;; this is so much faster than using a Lisp loop. - (let ((re (concat "^\\*\\{1," (number-to-string level) "\\} "))) - (forward-char 1) - (and (re-search-forward re nil 'move) (beginning-of-line 1)))) - (t - ;; something else, do it the slow way - (while (and (not (eobp)) - (or first (> (funcall outline-level) level))) - (setq first nil) - (outline-next-heading)))) - (unless to-heading + (unless (and (org-element--cache-active-p) + (let ((cached (or element (org-element-at-point nil t)))) + (and cached + (eq 'headline (org-element-type cached)) + (goto-char (org-element-property + :end cached))))) + (let ((first t) + (level (funcall outline-level))) + (cond ((= level 0) + (goto-char (point-max))) + ((and (derived-mode-p 'org-mode) (< level 1000)) + ;; A true heading (not a plain list item), in Org + ;; This means we can easily find the end by looking + ;; only for the right number of stars. Using a regexp to do + ;; this is so much faster than using a Lisp loop. + (let ((re (concat "^\\*\\{1," (number-to-string level) "\\} "))) + (forward-char 1) + (and (re-search-forward re nil 'move) (beginning-of-line 1)))) + (t + ;; something else, do it the slow way + (while (and (not (eobp)) + (or first (> (funcall outline-level) level))) + (setq first nil) + (outline-next-heading)))))) + (unless to-heading + (when (memq (preceding-char) '(?\n ?\^M)) + ;; Go to end of line before heading + (forward-char -1) (when (memq (preceding-char) '(?\n ?\^M)) - ;; Go to end of line before heading - (forward-char -1) - (when (memq (preceding-char) '(?\n ?\^M)) - ;; leave blank line before heading - (forward-char -1))))) + ;; leave blank line before heading + (forward-char -1)))) (point)) (defun org-end-of-meta-data (&optional full)