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) (unless (< (funcall outline-level) level)
(point))))) (point)))))
(defun org-end-of-subtree (&optional invisible-ok to-heading) (defun org-end-of-subtree (&optional invisible-ok to-heading element)
"Goto to the end of a subtree." "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 ;; 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 ;; `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. ;; 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 ;; with many children and grandchildren etc, this can be much faster
;; than the outline version. ;; than the outline version.
(org-back-to-heading-or-point-min invisible-ok) (org-back-to-heading-or-point-min invisible-ok)
(let ((first t) (unless (and (org-element--cache-active-p)
(level (funcall outline-level))) (let ((cached (or element (org-element-at-point nil t))))
(cond ((= level 0) (and cached
(goto-char (point-max))) (eq 'headline (org-element-type cached))
((and (derived-mode-p 'org-mode) (< level 1000)) (goto-char (org-element-property
;; A true heading (not a plain list item), in Org :end cached)))))
;; This means we can easily find the end by looking (let ((first t)
;; only for the right number of stars. Using a regexp to do (level (funcall outline-level)))
;; this is so much faster than using a Lisp loop. (cond ((= level 0)
(let ((re (concat "^\\*\\{1," (number-to-string level) "\\} "))) (goto-char (point-max)))
(forward-char 1) ((and (derived-mode-p 'org-mode) (< level 1000))
(and (re-search-forward re nil 'move) (beginning-of-line 1)))) ;; A true heading (not a plain list item), in Org
(t ;; This means we can easily find the end by looking
;; something else, do it the slow way ;; only for the right number of stars. Using a regexp to do
(while (and (not (eobp)) ;; this is so much faster than using a Lisp loop.
(or first (> (funcall outline-level) level))) (let ((re (concat "^\\*\\{1," (number-to-string level) "\\} ")))
(setq first nil) (forward-char 1)
(outline-next-heading)))) (and (re-search-forward re nil 'move) (beginning-of-line 1))))
(unless to-heading (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)) (when (memq (preceding-char) '(?\n ?\^M))
;; Go to end of line before heading ;; leave blank line before heading
(forward-char -1) (forward-char -1))))
(when (memq (preceding-char) '(?\n ?\^M))
;; leave blank line before heading
(forward-char -1)))))
(point)) (point))
(defun org-end-of-meta-data (&optional full) (defun org-end-of-meta-data (&optional full)