org-element: Fix cache update

* lisp/org-element.el (org-element--cache-sync): Fix cache update when
  a only contents of an element are modified.
(org-element--cache-shift-positions): Add optional argument allowing
partial shifting.
This commit is contained in:
Nicolas Goaziou 2013-12-30 10:58:34 +01:00
parent f58a8482b4
commit 405b505c73
1 changed files with 23 additions and 15 deletions

View File

@ -4886,25 +4886,29 @@ the value to store. Nothing will be stored if
(unless org-element--cache (org-element-cache-reset))
(puthash pos data org-element--cache)))
(defsubst org-element--cache-shift-positions (element offset)
(defsubst org-element--cache-shift-positions (element offset &optional props)
"Shift ELEMENT properties relative to buffer positions by OFFSET.
Properties containing buffer positions are `:begin', `:end',
`:contents-begin', `:contents-end' and `:structure'. They are
modified by side-effect. Return modified element."
`:contents-begin', `:contents-end' and `:structure'. When
optional argument PROPS is a list of keywords, only shift
properties provided in that list.
Properties are modified by side-effect. Return ELEMENT."
(let ((properties (nth 1 element)))
;; Shift :structure property for the first plain list only: it is
;; the only one that really matters and it prevents from shifting
;; it more than once.
(when (and (eq (org-element-type element) 'plain-list)
(when (and (or (not props) (memq :structure props))
(eq (org-element-type element) 'plain-list)
(not (eq (org-element-type (plist-get properties :parent))
'item)))
(dolist (item (plist-get properties :structure))
(incf (car item) offset)
(incf (nth 6 item) offset)))
(plist-put properties :begin (+ (plist-get properties :begin) offset))
(plist-put properties :end (+ (plist-get properties :end) offset))
(dolist (key '(:contents-begin :contents-end :post-affiliated))
(let ((value (plist-get properties key)))
(dolist (key '(:begin :contents-begin :contents-end :end :post-affiliated))
(let ((value (and (or (not props) (memq key props))
(plist-get properties key))))
(and value (plist-put properties key (+ offset value))))))
element)
@ -5078,7 +5082,7 @@ removed from the cache."
(let* ((conflictp (consp (caar value)))
(value-to-shift (if conflictp (cdr value) value)))
(cond
;; If an elements is missing one of its parents,
;; If an element is missing one of its parents,
;; remove it from cache. In a middle of
;; a conflict take care not to remove already
;; shifted element.
@ -5094,7 +5098,7 @@ removed from the cache."
(throw 'remove t)))
((<= (org-element-property :begin parent) end)
(throw 'remove t))))
;; No missing parent: Proceed with shifting.
;; No missing parent: proceed with shifting.
nil))
(if conflictp (puthash key (car value) org-element--cache)
(remhash key org-element--cache)))
@ -5163,19 +5167,23 @@ removed from the cache."
(throw 'remove
(remhash key org-element--cache))))
((>= (org-element-property :end parent) beg)
(throw 'remove (remhash key org-element--cache)))))
;; No missing parent: Keep element.
t)))
(throw 'remove
(remhash key org-element--cache))))))))
;; Preserve stable greater elements (or verse
;; blocks) when changes are limited to their
;; contents only.
;; contents only. In that case, extend both their
;; contents ending position and their ending
;; position by OFFSET.
((let ((contents-end
(org-element-property :contents-end element))
(type (org-element-type element)))
(and contents-end
(> contents-end end)
(or (memq type org-element--cache-stable-types)
(eq type 'verse-block)))))
(eq type 'verse-block))))
(org-element--cache-shift-positions
element offset '(:contents-end :end)))
;; Element ended within modified area: remove it.
(t (remhash key org-element--cache)))))))
org-element--cache)
;; Signal cache as up-to-date.