org.el/org-end-of-subtree: Support cache and passing element arg

This commit is contained in:
Ihor Radchenko 2021-10-16 23:39:11 +08:00
parent d43781707b
commit ec737554d0
No known key found for this signature in database
GPG Key ID: 6470762A7DA11D8B
1 changed files with 32 additions and 26 deletions

View File

@ -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)