branch: externals/org
commit 3a4f9604f1c358045930ef97745898a7391fc162
Author: Ihor Radchenko <[email protected]>
Commit: Ihor Radchenko <[email protected]>
Cache <N>-level headline regexps instead of calculating dynamically
* lisp/org-macs.el (org-headline-re): New function to retrieve cached
or get a new regexp for headline of level TRUE-LEVEL.
(org-get-limited-outline-regexp): Use `org-headline-re'. Add new
optional argument WITH-BOL.
---
lisp/org-element.el | 8 +++-----
lisp/org-macs.el | 31 +++++++++++++++++++++++++------
2 files changed, 28 insertions(+), 11 deletions(-)
diff --git a/lisp/org-element.el b/lisp/org-element.el
index a13e91f277..ed740fc0b4 100644
--- a/lisp/org-element.el
+++ b/lisp/org-element.el
@@ -1147,11 +1147,9 @@ Assume point is at beginning of the headline."
(time-props (org-element--get-time-properties))
(end
(save-excursion
- (let ((re (rx-to-string
- `(seq line-start (** 1 ,true-level "*") " "))))
- (if (re-search-forward re nil t)
- (line-beginning-position)
- (point-max)))))
+ (if (re-search-forward (org-headline-re true-level) nil t)
+ (line-beginning-position)
+ (point-max))))
(contents-begin (save-excursion
(forward-line)
(skip-chars-forward " \r\t\n" end)
diff --git a/lisp/org-macs.el b/lisp/org-macs.el
index 306990280a..f771c408b3 100644
--- a/lisp/org-macs.el
+++ b/lisp/org-macs.el
@@ -217,7 +217,7 @@ If BUFFER is nil, use base buffer for `current-buffer'."
(let* ((org-called-with-limited-levels t)
(org-outline-regexp (org-get-limited-outline-regexp))
(outline-regexp org-outline-regexp)
- (org-outline-regexp-bol (concat "^" org-outline-regexp)))
+ (org-outline-regexp-bol (org-get-limited-outline-regexp t)))
,@body)))
(defmacro org-eval-in-environment (environment form)
@@ -807,22 +807,41 @@ get an unnecessary O(N²) space complexity, so you're
usually better off using
(eval form t)
(error (format "%%![Error: %s]" error))))
+(defvar org--headline-re-cache (make-hash-table :test #'equal)
+ "Hash table holding association between headline level regexp.")
+(defun org-headline-re (true-level &optional no-bol)
+ "Generate headline regexp for TRUE-LEVEL.
+When NO-BOL is non-nil, regexp will not demand the regexp to start at
+beginning of line."
+ (or (gethash (cons true-level no-bol) org--headline-re-cache)
+ (puthash
+ (cons true-level no-bol)
+ (rx-to-string
+ (if no-bol
+ `(seq (** 1 ,true-level "*") " ")
+ `(seq line-start (** 1 ,true-level "*") " ")))
+ org--headline-re-cache)))
+
(defvar org-outline-regexp) ; defined in org.el
+(defvar org-outline-regexp-bol) ; defined in org.el
(defvar org-odd-levels-only) ; defined in org.el
(defvar org-inlinetask-min-level) ; defined in org-inlinetask.el
-(defun org-get-limited-outline-regexp ()
+(defun org-get-limited-outline-regexp (&optional with-bol)
"Return outline-regexp with limited number of levels.
-The number of levels is controlled by `org-inlinetask-min-level'."
+The number of levels is controlled by `org-inlinetask-min-level'.
+Match at beginning of line when WITH-BOL is non-nil."
(cond ((not (derived-mode-p 'org-mode))
- outline-regexp)
+ (if (string-prefix-p "^" outline-regexp)
+ (if with-bol outline-regexp (substring outline-regexp 1))
+ (if with-bol (concat "^" outline-regexp) outline-regexp)))
((not (featurep 'org-inlinetask))
- org-outline-regexp)
+ (if with-bol org-outline-regexp-bol org-outline-regexp))
(t
(let* ((limit-level (1- org-inlinetask-min-level))
(nstars (if org-odd-levels-only
(1- (* limit-level 2))
limit-level)))
- (format "\\*\\{1,%d\\} " nstars)))))
+ (org-headline-re nstars (not with-bol))))))
(defun org--line-empty-p (n)
"Is the Nth next line empty?