Nicolas Goaziou writes: Thanks for your detailed explanations! >> 2. Some of the element parsers honour LIMIT argument partially. Part of >> the parsing is typically done using looking-at (ignoring the LIMIT) >> and part is honouring it. This can backfire when LIMIT is before >> first characteristic line of the element. For example take headline >> parser: >> ... > > LIMIT is not a random position in the buffer. It is supposed to be the > end of the parent element, or (point-max). > > It is a bug (in the parser or in the cache) if it ends up being anywhere > else. Makes sense, though it is not mentioned in the docstrings and even in the docstring of the `org-element--current-element'. Moreover, section comment about parsers states that most parsers accept no arguments: > ;; A parser returns the element or object as the list described above. > ;; Most of them accepts no argument. And the comment about adding things to `org-element--current-element' does not help either. > ;; Beside implementing a parser and an interpreter, adding a new > ;; greater element requires tweaking `org-element--current-element'. > ;; Moreover, the newly defined type must be added to both > ;; `org-element-all-elements' and `org-element-greater-elements'. Probably, the docstring of `org-element--current-element' could mention about the expected values of LIMIT argument? ------ Also, I have some more questions as I am trying to understand the org-element-cache code. I tried to add some additional comments to the existing code to clarify parts I had difficulties understanding. See the attached patch. Let me know if any of the comments are incorrect so that I can update my understanding. For now I am stuck understanding some places in the code. They are either bugs or I misunderstood some things: 1. In org-element--cache-process-request: > (while t > ... > (let ((beg (aref request 0)) > (end (aref request 2)) > (node (org-element--cache-root)) > data data-key last-container) > > ... > (and last-container > ... > (progn (when (and (not last-container) > (> (org-element-property :end data) > end)) > (setq last-container data)) I do not understand the use of last-container here. The code is ran in a while loop containing let-bound last-container variable (the let binding sets it to nil). (setq last-container data) will not affect further iterations of the while loop as last-container will always be nil inside the let-binding. 2. In org-element--cache-submit-request > (let ((first (org-element--cache-for-removal beg end offset))) > ... > (push (let ((beg (org-element-property :begin first)) > (key (org-element--cache-key first))) > ... > ((let ((first-end (org-element-property :end first))) > (and (>= first-end end) > (vector key beg first-end offset first 0)))) > ... > org-element--cache-sync-requests) According to the docstring of org-element--cache-sync-requests, (aref 4 request) during "0" phase should be "PARENT, when non-nil, is the parent of the first element to be removed. Yet, KEY is the key of the FIRST and FIRST itself is passed as PARENT. > (push (let ((beg (org-element-property :begin first)) > (key (org-element--cache-key first))) > ... > ;; Otherwise, we find the first non robust > ;; element containing END. All elements between > ;; FIRST and this one are to be removed. > ... > (t > (let* ((element (org-element--cache-find end)) > (end (org-element-property :end element)) > (up element)) > (while (and (setq up (org-element-property :parent up)) > (>= (org-element-property :begin up) beg)) > (setq end (org-element-property :end up) > element up)) > (vector key beg end offset element 0))))) Despite what the comment states, the following code simply searches for the parent of FIRST and extents the region of phase 0 request all the way to the end of that parent. (note that BEG is re-bound to the beginning of the FIRST). Now, consider the following branch of org-element--cache-submit-request. The (aref next 4) may contain the parent of FIRST from the above code. That parent is robust (or it would be returned by org-element--cache-for-removal) and its :end/:contents-end have already been shifted in the earlier call to org-element--cache-for-removal (that was where we have found the FIRST value): > ;; If last change happened within area to be removed, extend > ;; boundaries of robust parents, if any. Otherwise, find > ;; first element to remove and update request accordingly. > (if (> beg delete-from) > ... > (let ((up (aref next 4))) > (while up > (org-element--cache-shift-positions > up offset '(:contents-end :end)) > (setq up (org-element-property :parent up)))) The first iteration of the while loop will potentially extend the :end/:contents-end of the parent of FIRST second time in a row. Best, Ihor