diff --git a/lisp/org-element.el b/lisp/org-element.el index 6d0890f4b..dd06a2a75 100644 --- a/lisp/org-element.el +++ b/lisp/org-element.el @@ -4187,7 +4187,7 @@ Assume point is at the first equal sign marker." (defvar org-inlinetask-min-level); Declared in org-inlinetask.el (defvar org-element--cache-sync-requests); Declared later -(defun org-element--current-element (limit &optional granularity mode structure add-to-cache) +(defun org-element--current-element (limit &optional granularity mode structure) "Parse the element starting at point. Return value is a list like (TYPE PROPS) where TYPE is the type @@ -4212,207 +4212,176 @@ Optional argument MODE, when non-nil, can be either If STRUCTURE isn't provided but MODE is set to `item', it will be computed. -Optional argument ADD-TO-CACHE, when non-nil, and when cache is active, -will also add current element to cache if it is not yet there. Use -this argument with care, as validity of the element in parse tree is -not checked. - This function assumes point is always at the beginning of the element it has to parse." - (let* ((element (and (not (buffer-narrowed-p)) - (org-element--cache-active-p) - (not org-element--cache-sync-requests) - (org-element--cache-find (point) t))) - (element (progn (while (and element - (not (and (eq (point) (org-element-property :begin element)) - (eq mode (org-element-property :mode element))))) - (setq element (org-element-property :parent element))) - element)) - (old-element element) - (element (when - (pcase (org-element-property :granularity element) - (`nil t) - (`object t) - (`element (not (memq granularity '(nil object)))) - (`greater-element (not (memq granularity '(nil object element)))) - (`headline (eq granularity 'headline))) - element))) - (if element - element - (save-excursion - (let ((case-fold-search t) - ;; Determine if parsing depth allows for secondary strings - ;; parsing. It only applies to elements referenced in - ;; `org-element-secondary-value-alist'. - (raw-secondary-p (and granularity (not (eq granularity 'object)))) - result) - (setq - result - ;; Regexp matches below should avoid modifying match data, - ;; if possible. Doing it unnecessarily degrades regexp - ;; matching performance an order of magnitude, which - ;; becomes important when parsing large buffers with huge - ;; amount of elements to be parsed. - ;; - ;; In general, the checks below should be as efficient as - ;; possible, especially early in the `cond' form. (The - ;; early checks will contribute to al subsequent parsers as - ;; well). - (cond - ;; Item. - ((eq mode 'item) (org-element-item-parser limit structure raw-secondary-p)) - ;; Table Row. - ((eq mode 'table-row) (org-element-table-row-parser limit)) - ;; Node Property. - ((eq mode 'node-property) (org-element-node-property-parser limit)) - ;; Headline. - ((and (looking-at-p "^\\*+ ") - (or (not (featurep 'org-inlinetask)) - (save-excursion - (< (skip-chars-forward "*") - (if org-odd-levels-only - (1- (* org-inlinetask-min-level 2)) - org-inlinetask-min-level))))) - (org-element-headline-parser limit raw-secondary-p)) - ;; Sections (must be checked after headline). - ((memq mode '(section first-section)) (org-element-section-parser nil)) - ;; Comments. - ((looking-at-p "^[ \t]*#\\(?: \\|$\\)") (org-element-comment-parser limit)) - ;; Planning. - ((and (eq mode 'planning) - (eq ?* (char-after (line-beginning-position 0))) - (looking-at-p org-element-planning-line-re)) - (org-element-planning-parser limit)) - ;; Property drawer. - ((and (pcase mode - (`planning (eq ?* (char-after (line-beginning-position 0)))) - ((or `property-drawer `top-comment) - (save-excursion - (beginning-of-line 0) - (not (looking-at-p "[[:blank:]]*$")))) - (_ nil)) - (looking-at-p org-property-drawer-re)) - (org-element-property-drawer-parser limit)) - ;; When not at bol, point is at the beginning of an item or - ;; a footnote definition: next item is always a paragraph. - ((not (bolp)) (org-element-paragraph-parser limit (list (point)))) - ;; Clock. - ((looking-at-p org-element-clock-line-re) (org-element-clock-parser limit)) - ;; Inlinetask. - ((looking-at-p "^\\*+ ") (org-element-inlinetask-parser limit raw-secondary-p)) - ;; From there, elements can have affiliated keywords. - (t (let ((affiliated (org-element--collect-affiliated-keywords - limit (memq granularity '(nil object))))) - (cond - ;; Jumping over affiliated keywords put point off-limits. - ;; Parse them as regular keywords. - ((and (cdr affiliated) (>= (point) limit)) - (goto-char (car affiliated)) - (org-element-keyword-parser limit nil)) - ;; LaTeX Environment. - ((looking-at-p org-element--latex-begin-environment) - (org-element-latex-environment-parser limit affiliated)) - ;; Drawer. - ((looking-at-p org-element-drawer-re) - (org-element-drawer-parser limit affiliated)) - ;; Fixed Width - ((looking-at-p "[ \t]*:\\( \\|$\\)") - (org-element-fixed-width-parser limit affiliated)) - ;; Inline Comments, Blocks, Babel Calls, Dynamic Blocks and - ;; Keywords. - ((looking-at "[ \t]*#\\+") - (goto-char (match-end 0)) - (cond - ((looking-at "BEGIN_\\(\\S-+\\)") - (beginning-of-line) - (funcall (pcase (upcase (match-string 1)) - ("CENTER" #'org-element-center-block-parser) - ("COMMENT" #'org-element-comment-block-parser) - ("EXAMPLE" #'org-element-example-block-parser) - ("EXPORT" #'org-element-export-block-parser) - ("QUOTE" #'org-element-quote-block-parser) - ("SRC" #'org-element-src-block-parser) - ("VERSE" #'org-element-verse-block-parser) - (_ #'org-element-special-block-parser)) - limit - affiliated)) - ((looking-at-p "CALL:") - (beginning-of-line) - (org-element-babel-call-parser limit affiliated)) - ((save-excursion - (beginning-of-line) - (looking-at-p org-element-dynamic-block-open-re)) - (beginning-of-line) - (org-element-dynamic-block-parser limit affiliated)) - ((looking-at-p "\\S-+:") - (beginning-of-line) - (org-element-keyword-parser limit affiliated)) - (t - (beginning-of-line) - (org-element-paragraph-parser limit affiliated)))) - ;; Footnote Definition. - ((looking-at-p org-footnote-definition-re) - (org-element-footnote-definition-parser limit affiliated)) - ;; Horizontal Rule. - ((looking-at-p "[ \t]*-\\{5,\\}[ \t]*$") - (org-element-horizontal-rule-parser limit affiliated)) - ;; Diary Sexp. - ((looking-at-p "%%(") - (org-element-diary-sexp-parser limit affiliated)) - ;; Table. - ((or (looking-at-p "[ \t]*|") - ;; There is no strict definition of a table.el - ;; table. Try to prevent false positive while being - ;; quick. - (let ((rule-regexp - (rx (zero-or-more (any " \t")) - "+" - (one-or-more (one-or-more "-") "+") - (zero-or-more (any " \t")) - eol)) - (non-table.el-line - (rx bol - (zero-or-more (any " \t")) - (or eol (not (any "+| \t"))))) - (next (line-beginning-position 2))) - ;; Start with a full rule. - (and - (looking-at-p rule-regexp) - (< next limit) ;no room for a table.el table - (save-excursion - (end-of-line) - (cond - ;; Must end with a full rule. - ((not (re-search-forward non-table.el-line limit 'move)) - (if (bolp) (forward-line -1) (beginning-of-line)) - (looking-at-p rule-regexp)) - ;; Ignore pseudo-tables with a single - ;; rule. - ((= next (line-beginning-position)) - nil) - ;; Must end with a full rule. - (t - (forward-line -1) - (looking-at-p rule-regexp))))))) - (org-element-table-parser limit affiliated)) - ;; List. - ((looking-at-p (org-item-re)) - (org-element-plain-list-parser - limit affiliated - (or structure (org-element--list-struct limit)))) - ;; Default element: Paragraph. - (t (org-element-paragraph-parser limit affiliated))))))) - (when result - (org-element-put-property result :mode mode) - (org-element-put-property result :granularity granularity)) - (when (and add-to-cache(not (buffer-narrowed-p)) - (not org-element--cache-sync-requests) - (org-element--cache-active-p)) - (if (not old-element) - (setq result (org-element--cache-put result)) - (org-element-set-element old-element result) - (setq result old-element))) - result))))) + (save-excursion + (let ((case-fold-search t) + ;; Determine if parsing depth allows for secondary strings + ;; parsing. It only applies to elements referenced in + ;; `org-element-secondary-value-alist'. + (raw-secondary-p (and granularity (not (eq granularity 'object)))) + result at-task?) + (setq + result + ;; Regexp matches below should avoid modifying match data, + ;; if possible. Doing it unnecessarily degrades regexp + ;; matching performance an order of magnitude, which + ;; becomes important when parsing large buffers with huge + ;; amount of elements to be parsed. + ;; + ;; In general, the checks below should be as efficient as + ;; possible, especially early in the `cond' form. (The + ;; early checks will contribute to al subsequent parsers as + ;; well). + (cond + ;; Item. + ((eq mode 'item) (org-element-item-parser limit structure raw-secondary-p)) + ;; Table Row. + ((eq mode 'table-row) (org-element-table-row-parser limit)) + ;; Node Property. + ((eq mode 'node-property) (org-element-node-property-parser limit)) + ;; Headline. + ((and (looking-at-p "^\\*+ ") + (setq at-task? t) + (or (not (featurep 'org-inlinetask)) + (save-excursion + (< (skip-chars-forward "*") + (if org-odd-levels-only + (1- (* org-inlinetask-min-level 2)) + org-inlinetask-min-level))))) + (org-element-headline-parser limit raw-secondary-p)) + ;; Sections (must be checked after headline). + ((memq mode '(section first-section)) (org-element-section-parser nil)) + ;; Comments. + ((looking-at-p "^[ \t]*#\\(?: \\|$\\)") (org-element-comment-parser limit)) + ;; Planning. + ((and (eq mode 'planning) + (eq ?* (char-after (line-beginning-position 0))) + (looking-at-p org-element-planning-line-re)) + (org-element-planning-parser limit)) + ;; Property drawer. + ((and (pcase mode + (`planning (eq ?* (char-after (line-beginning-position 0)))) + ((or `property-drawer `top-comment) + (save-excursion + (beginning-of-line 0) + (not (looking-at-p "[[:blank:]]*$")))) + (_ nil)) + (looking-at-p org-property-drawer-re)) + (org-element-property-drawer-parser limit)) + ;; When not at bol, point is at the beginning of an item or + ;; a footnote definition: next item is always a paragraph. + ((not (bolp)) (org-element-paragraph-parser limit (list (point)))) + ;; Clock. + ((looking-at-p org-element-clock-line-re) (org-element-clock-parser limit)) + ;; Inlinetask. + (at-task? (org-element-inlinetask-parser limit raw-secondary-p)) + ;; From there, elements can have affiliated keywords. + (t (let ((affiliated (org-element--collect-affiliated-keywords + limit (memq granularity '(nil object))))) + (cond + ;; Jumping over affiliated keywords put point off-limits. + ;; Parse them as regular keywords. + ((and (cdr affiliated) (>= (point) limit)) + (goto-char (car affiliated)) + (org-element-keyword-parser limit nil)) + ;; LaTeX Environment. + ((looking-at-p org-element--latex-begin-environment) + (org-element-latex-environment-parser limit affiliated)) + ;; Drawer. + ((looking-at-p org-element-drawer-re) + (org-element-drawer-parser limit affiliated)) + ;; Fixed Width + ((looking-at-p "[ \t]*:\\( \\|$\\)") + (org-element-fixed-width-parser limit affiliated)) + ;; Inline Comments, Blocks, Babel Calls, Dynamic Blocks and + ;; Keywords. + ((looking-at "[ \t]*#\\+") + (goto-char (match-end 0)) + (cond + ((looking-at "BEGIN_\\(\\S-+\\)") + (beginning-of-line) + (funcall (pcase (upcase (match-string 1)) + ("CENTER" #'org-element-center-block-parser) + ("COMMENT" #'org-element-comment-block-parser) + ("EXAMPLE" #'org-element-example-block-parser) + ("EXPORT" #'org-element-export-block-parser) + ("QUOTE" #'org-element-quote-block-parser) + ("SRC" #'org-element-src-block-parser) + ("VERSE" #'org-element-verse-block-parser) + (_ #'org-element-special-block-parser)) + limit + affiliated)) + ((looking-at-p "CALL:") + (beginning-of-line) + (org-element-babel-call-parser limit affiliated)) + ((save-excursion + (beginning-of-line) + (looking-at-p org-element-dynamic-block-open-re)) + (beginning-of-line) + (org-element-dynamic-block-parser limit affiliated)) + ((looking-at-p "\\S-+:") + (beginning-of-line) + (org-element-keyword-parser limit affiliated)) + (t + (beginning-of-line) + (org-element-paragraph-parser limit affiliated)))) + ;; Footnote Definition. + ((looking-at-p org-footnote-definition-re) + (org-element-footnote-definition-parser limit affiliated)) + ;; Horizontal Rule. + ((looking-at-p "[ \t]*-\\{5,\\}[ \t]*$") + (org-element-horizontal-rule-parser limit affiliated)) + ;; Diary Sexp. + ((looking-at-p "%%(") + (org-element-diary-sexp-parser limit affiliated)) + ;; Table. + ((or (looking-at-p "[ \t]*|") + ;; There is no strict definition of a table.el + ;; table. Try to prevent false positive while being + ;; quick. + (let ((rule-regexp + (rx (zero-or-more (any " \t")) + "+" + (one-or-more (one-or-more "-") "+") + (zero-or-more (any " \t")) + eol)) + (non-table.el-line + (rx bol + (zero-or-more (any " \t")) + (or eol (not (any "+| \t"))))) + (next (line-beginning-position 2))) + ;; Start with a full rule. + (and + (looking-at-p rule-regexp) + (< next limit) ;no room for a table.el table + (save-excursion + (end-of-line) + (cond + ;; Must end with a full rule. + ((not (re-search-forward non-table.el-line limit 'move)) + (if (bolp) (forward-line -1) (beginning-of-line)) + (looking-at-p rule-regexp)) + ;; Ignore pseudo-tables with a single + ;; rule. + ((= next (line-beginning-position)) + nil) + ;; Must end with a full rule. + (t + (forward-line -1) + (looking-at-p rule-regexp))))))) + (org-element-table-parser limit affiliated)) + ;; List. + ((looking-at-p (org-item-re)) + (org-element-plain-list-parser + limit affiliated + (or structure (org-element--list-struct limit)))) + ;; Default element: Paragraph. + (t (org-element-paragraph-parser limit affiliated))))))) + (when result + (org-element-put-property result :mode mode) + (org-element-put-property result :granularity granularity)) + result))) ;; Most elements can have affiliated keywords. When looking for an @@ -4824,20 +4793,7 @@ Elements are accumulated into ACC." (when (and (eolp) (not (eobp))) (forward-char))) ;; Find current element's type and parse it accordingly to ;; its category. - (let* ((element (org-element-copy - ;; `org-element--current-element' may return cached - ;; elements. Below code reassigns - ;; `:parent' property of the element and - ;; may interfere with cache - ;; synchronization if parent element is not - ;; yet in cache. Moreover, the returned - ;; structure may be altered by caller code - ;; arbitrarily. Hence, we return a copy of - ;; the potentially cached element to make - ;; potential modifications safe for element - ;; cache. - (org-element--current-element - end granularity mode structure))) + (let* ((element (org-element--current-element end granularity mode structure)) (type (org-element-type element)) (cbeg (org-element-property :contents-begin element))) (goto-char (org-element-property :end element)) @@ -6577,10 +6533,9 @@ If you observe Emacs hangs frequently, please report this to Org mode mailing li (unless (save-excursion (org-skip-whitespace) (eobp)) - (org-element-with-disabled-cache - (setq element (org-element--current-element - end 'element mode - (org-element-property :structure parent))))) + (setq element (org-element--current-element + end 'element mode + (org-element-property :structure parent)))) ;; Make sure that we return referenced element in cache ;; that can be altered directly. (if element