Browse Source

org-element: Sync cache after changes instead of before them

* lisp/org-element.el (org-element--cache-sync,
  org-element--cache-process-request): Change signature.
(org-element--cache-before-change): Do not synchronize cache
preemptively.
(org-element--cache-submit-request): Synchronize cache preemptively.

This change makes possible to skip cache preemptive synchronization
under some circumstances.
Nicolas Goaziou 11 years ago
parent
commit
b2f200f0a1
1 changed files with 24 additions and 7 deletions
  1. 24 7
      lisp/org-element.el

+ 24 - 7
lisp/org-element.el

@@ -5027,13 +5027,19 @@ Properties are modified by side-effect."
 			(plist-get properties key))))
 			(plist-get properties key))))
 	(and value (plist-put properties key (+ offset value)))))))
 	(and value (plist-put properties key (+ offset value)))))))
 
 
-(defun org-element--cache-sync (buffer &optional threshold)
+(defun org-element--cache-sync (buffer &optional threshold extra)
   "Synchronize cache with recent modification in BUFFER.
   "Synchronize cache with recent modification in BUFFER.
+
 When optional argument THRESHOLD is non-nil, do the
 When optional argument THRESHOLD is non-nil, do the
 synchronization for all elements starting before or at threshold,
 synchronization for all elements starting before or at threshold,
 then exit.  Otherwise, synchronize cache for as long as
 then exit.  Otherwise, synchronize cache for as long as
 `org-element-cache-sync-duration' or until Emacs leaves idle
 `org-element-cache-sync-duration' or until Emacs leaves idle
-state."
+state.
+
+EXTRA, when non-nil, is an additional offset for changes not
+registered yet in the cache.  It is used in
+`org-element--cache-submit-request', where cache is partially
+updated before current modification are actually submitted."
   (when (buffer-live-p buffer)
   (when (buffer-live-p buffer)
     (with-current-buffer buffer
     (with-current-buffer buffer
       (let ((inhibit-quit t) request next)
       (let ((inhibit-quit t) request next)
@@ -5049,7 +5055,8 @@ state."
 	     threshold
 	     threshold
 	     (and (not threshold)
 	     (and (not threshold)
 		  (time-add (current-time)
 		  (time-add (current-time)
-			    org-element-cache-sync-duration)))
+			    org-element-cache-sync-duration))
+	     (or extra 0))
 	    ;; Request processed.  Merge current and next offsets and
 	    ;; Request processed.  Merge current and next offsets and
 	    ;; transfer phase number and ending position.
 	    ;; transfer phase number and ending position.
 	    (when next
 	    (when next
@@ -5064,7 +5071,8 @@ state."
 	    (org-element--cache-set-timer buffer)
 	    (org-element--cache-set-timer buffer)
 	  (clrhash org-element--cache-sync-keys))))))
 	  (clrhash org-element--cache-sync-keys))))))
 
 
-(defun org-element--cache-process-request (request next threshold time-limit)
+(defun org-element--cache-process-request
+  (request next threshold time-limit extra)
   "Process synchronization REQUEST for all entries before NEXT.
   "Process synchronization REQUEST for all entries before NEXT.
 
 
 REQUEST is a vector, built by `org-element--cache-submit-request'.
 REQUEST is a vector, built by `org-element--cache-submit-request'.
@@ -5077,6 +5085,10 @@ stops as soon as a shifted element begins after it.
 When non-nil, TIME-LIMIT is a time value.  Synchronization stops
 When non-nil, TIME-LIMIT is a time value.  Synchronization stops
 after this time or when Emacs exits idle state.
 after this time or when Emacs exits idle state.
 
 
+EXTRA is an additional offset taking into consideration changes
+not registered yet.  See `org-element--cache-submit-request' for
+more information.
+
 Throw `interrupt' if the process stops before completing the
 Throw `interrupt' if the process stops before completing the
 request."
 request."
   (catch 'quit
   (catch 'quit
@@ -5176,7 +5188,7 @@ request."
 	;; contains the real beginning position of the first element
 	;; contains the real beginning position of the first element
 	;; to shift and re-parent.
 	;; to shift and re-parent.
 	(when (equal (aref request 0) next) (throw 'quit t))
 	(when (equal (aref request 0) next) (throw 'quit t))
-	(let ((limit (+ (aref request 1) (aref request 2))))
+	(let ((limit (+ (aref request 2) (aref request 3) extra)))
 	  (when (and threshold (< threshold limit)) (throw 'interrupt nil))
 	  (when (and threshold (< threshold limit)) (throw 'interrupt nil))
 	  (let ((parent (org-element--parse-to limit t time-limit)))
 	  (let ((parent (org-element--parse-to limit t time-limit)))
 	    (aset request 4 parent)
 	    (aset request 4 parent)
@@ -5406,9 +5418,7 @@ It is a symbol among nil, t and `headline'.")
 BEG and END are the beginning and end of the range of changed
 BEG and END are the beginning and end of the range of changed
 text.  See `before-change-functions' for more information."
 text.  See `before-change-functions' for more information."
   (let ((inhibit-quit t))
   (let ((inhibit-quit t))
-    ;; Make sure buffer positions in cache are correct until END.
     (save-match-data
     (save-match-data
-      (org-element--cache-sync (current-buffer) end)
       (org-with-wide-buffer
       (org-with-wide-buffer
        (goto-char beg)
        (goto-char beg)
        (beginning-of-line)
        (beginning-of-line)
@@ -5486,6 +5496,13 @@ that range.  See `after-change-functions' for more information."
 BEG and END are buffer positions delimiting the minimal area
 BEG and END are buffer positions delimiting the minimal area
 where cache data should be removed.  OFFSET is the size of the
 where cache data should be removed.  OFFSET is the size of the
 change, as an integer."
 change, as an integer."
+  ;; Make sure buffer positions in cache are correct until END.  This
+  ;; also ensures that pending cache requests have their phases
+  ;; properly ordered.  We need to provide OFFSET as optional
+  ;; parameter since current modifications are not known yet to the
+  ;; otherwise correct part of the cache (i.e, before the first
+  ;; request).
+  (org-element--cache-sync (current-buffer) end offset)
   (let ((first-element
   (let ((first-element
 	 ;; Find the position of the first element in cache to remove.
 	 ;; Find the position of the first element in cache to remove.
 	 ;;
 	 ;;