From 4fcdcb456dc90634adc26f750ce8ad203847c330 Mon Sep 17 00:00:00 2001 From: Ihor Radchenko Date: Wed, 26 Apr 2023 22:47:23 +0200 Subject: [PATCH] org-element: Defer large buffer substrings when parsing * lisp/org-element.el (org-element--substring): (org-element--unescape-substring): New functions to be used for deferred buffer substring calculation. (org-element--headline-raw-value): (org-element-comment-block-parser): (org-element-example-block-parser): (org-element-export-block-parser): (org-element-latex-environment-parser): (org-element-src-block-parser): (org-element-table-parser): (org-element--parse-generic-emphasis): (org-element-inline-babel-call-parser): (org-element-latex-fragment-parser): (org-element-export-snippet-parser): Defer large buffer substrings. --- lisp/org-element.el | 90 +++++++++++++++++++++++++++++++-------------- 1 file changed, 63 insertions(+), 27 deletions(-) diff --git a/lisp/org-element.el b/lisp/org-element.el index 5bc99abbb..ee0e7f053 100644 --- a/lisp/org-element.el +++ b/lisp/org-element.el @@ -560,6 +560,20 @@ Return nil if STRING is nil." (when string (symbol-name (intern string org-element--string-cache)))) +(defun org-element--substring (element beg-offset end-offset) + "Get substring inside ELEMENT according to BEG-OFFSET and END-OFFSET." + (with-current-buffer (org-element-property :buffer element) + (let ((beg (org-element-property :begin element))) + (buffer-substring-no-properties + (+ beg beg-offset) (+ beg end-offset))))) + +(defun org-element--unescape-substring (element beg-offset end-offset) + "Call `org-element--substring' and unescape the result. +See `org-element--substring' for the meaning of ELEMENT, BEG-OFFSET, +and END-OFFSET." + (org-unescape-code-in-string + (org-element--substring element beg-offset end-offset))) + ;;; Greater elements ;; @@ -960,11 +974,7 @@ Return value is a plist." (defun org-element--headline-raw-value (headline beg-offset end-offset) "Retrieve :raw-value in HEADLINE according to BEG-OFFSET and END-OFFSET." - (with-current-buffer (org-element-property :buffer headline) - (let ((beg (org-element-property :begin headline))) - (org-trim - (buffer-substring-no-properties - (+ beg beg-offset) (+ beg end-offset)))))) + (org-trim (org-element--substring headline beg-offset end-offset))) (defun org-element-headline-parser (&optional _ raw-secondary-p) "Parse a headline. @@ -2046,8 +2056,11 @@ Assume point is at comment block beginning." (point))) (end (progn (skip-chars-forward " \r\t\n" limit) (if (eobp) (point) (line-beginning-position)))) - (value (buffer-substring-no-properties - contents-begin contents-end))) + (value + (org-element-deferred-create + nil #'org-element--substring + (- contents-begin begin) + (- contents-end begin)))) (org-element-create 'comment-block (nconc @@ -2162,9 +2175,11 @@ containing `:begin', `:end', `:number-lines', `:preserve-indent', (begin (car affiliated)) (post-affiliated (point)) (contents-begin (line-beginning-position 2)) - (value (org-unescape-code-in-string - (buffer-substring-no-properties - contents-begin contents-end))) + (value + (org-element-deferred-create + nil #'org-element--unescape-substring + (- contents-begin begin) + (- contents-end begin))) (pos-before-blank (progn (goto-char contents-end) (forward-line) (point))) @@ -2242,9 +2257,11 @@ Assume point is at export-block beginning." (point))) (end (progn (skip-chars-forward " \r\t\n" limit) (if (eobp) (point) (line-beginning-position)))) - (value (org-unescape-code-in-string - (buffer-substring-no-properties contents-begin - contents-end)))) + (value + (org-element-deferred-create + nil #'org-element--unescape-substring + (- contents-begin begin) + (- contents-end begin)))) (org-element-create 'export-block (nconc @@ -2420,13 +2437,17 @@ Assume point is at the beginning of the latex environment." (code-begin (point))) (looking-at org-element--latex-begin-environment) (if (not (re-search-forward (format org-element--latex-end-environment - (regexp-quote (match-string 1))) - limit t)) + (regexp-quote (match-string 1))) + limit t)) ;; Incomplete latex environment: parse it as a paragraph. (org-element-paragraph-parser limit affiliated) (let* ((code-end (progn (forward-line) (point))) (begin (car affiliated)) - (value (buffer-substring-no-properties code-begin code-end)) + (value + (org-element-deferred-create + nil #'org-element--substring + (- code-begin begin) + (- code-end begin))) (end (progn (skip-chars-forward " \r\t\n" limit) (if (eobp) (point) (line-beginning-position))))) (org-element-create @@ -2688,9 +2709,11 @@ Assume point is at the beginning of the block." (and retain-labels (not (string-match "-k\\>" switches))))) ;; Retrieve code. - (value (org-unescape-code-in-string - (buffer-substring-no-properties - (line-beginning-position 2) contents-end))) + (value + (org-element-deferred-create + nil #'org-element--unescape-substring + (- (line-beginning-position 2) begin) + (- contents-end begin))) (pos-before-blank (progn (goto-char contents-end) (forward-line) (point))) @@ -2790,8 +2813,10 @@ Assume point is at the beginning of the table." :contents-begin (and (eq type 'org) table-begin) :contents-end (and (eq type 'org) table-end) :value (and (eq type 'table.el) - (buffer-substring-no-properties - table-begin table-end)) + (org-element-deferred-create + nil #'org-element--substring + (- table-begin begin) + (- table-end begin))) :post-blank (count-lines pos-before-blank end) :post-affiliated table-begin) (cdr affiliated)))))) @@ -2951,8 +2976,10 @@ Assume point is at first MARK." (if (memq type '(code verbatim)) (list :value (and (memq type '(code verbatim)) - (buffer-substring - contents-begin contents-end))) + (org-element-deferred-create + nil #'org-element--substring + (- contents-begin origin) + (- contents-end origin)))) (list :contents-begin contents-begin :contents-end contents-end))))))))))))) @@ -3188,8 +3215,11 @@ Assume point is at the beginning of the snippet." (let* ((begin (match-beginning 0)) (backend (org-element--get-cached-string (match-string-no-properties 1))) - (value (buffer-substring-no-properties - (match-end 0) contents-end)) + (value + (org-element-deferred-create + nil #'org-element--substring + (- (match-end 0) begin) + (- contents-end begin))) (post-blank (skip-chars-forward " \t")) (end (point))) (org-element-create @@ -3279,7 +3309,10 @@ Assume point is at the beginning of the babel call." (let ((p (org-element--parse-paired-brackets ?\[))) (and (org-string-nw-p p) (replace-regexp-in-string "\n[ \t]*" " " (org-trim p))))) - (value (buffer-substring-no-properties begin (point))) + (value + (org-element-deferred-create + nil #'org-element--substring + 0 (- (point) begin))) (post-blank (skip-chars-forward " \t")) (end (point))) (org-element-create @@ -3411,7 +3444,10 @@ Assume point is at the beginning of the LaTeX fragment." (end (point))) (org-element-create 'latex-fragment - (list :value (buffer-substring-no-properties begin after-fragment) + (list :value + (org-element-deferred-create + nil #'org-element--substring + 0 (- after-fragment begin)) :begin begin :end end :post-blank post-blank))))))