org-element: Implement lazy cache synchronization

* lisp/org-element.el (org-element-cache-sync-idle-time): Change
  default value.
(org-element-cache-sync-duration, org-element-cache-sync-break,
org-element--cache-sync-requests, org-element--cache-sync-timer,
org-element--cache-sync-keys, org-element--cache-default-key,
org-element--cache-change-warning): New variables.
(org-element-cache-merge-changes-threshold,
org-element--cache-status): Removed variables.
(org-element--cache-key, org-element--cache-generate-key,
org-element--cache-key-less-p, org-element--cache-find,
org-element--cache-set-timer, org-element--cache-process-request,
org-element--cache-submit-request, org-element--parse-to,
org-element--cache-interrupt-p, org-element--cache-put,
org-element--cache-active-p): New functions.
(org-element--cache-compare): Adapt to new keys in AVL tree.
(org-element--cache-pending-changes-p,
org-element--cache-cancel-changes, org-element--cache-mapc,
org-element-cache-get, org-element-cache-put): Removed functions.
(org-element--cache-before-change): Use new variables.
(org-element--cache-after-change): Renamed from
`org-element--cache-record-change'.
(org-element-cache-get): Change signature.
(org-element-cache-put): Rewrite function.  Use new tools.
(org-element-cache-reset): Adapt to new variables.
(org-element--cache-sync): Rewrite function.

* lisp/ox.el (org-export--generate-copy-script): Do not copy through
  new cache-related variables.
(org-export-ignored-local-variables): New variable.

* testing/lisp/test-org-element.el (test-org-element/cache): New test.

Now only the part of the cache that needs to be accessed is updated
synchronously.  Otherwise, it happens on idle time.
This commit is contained in:
Nicolas Goaziou 2014-01-31 01:14:44 +01:00
parent fb3ecad851
commit eed0500913
3 changed files with 1140 additions and 672 deletions

File diff suppressed because it is too large Load Diff

View File

@ -263,6 +263,16 @@ whose extension is either \"png\", \"jpeg\", \"jpg\", \"gif\",
See `org-export-inline-image-p' for more information about
rules.")
(defconst org-export-ignored-local-variables
'(org-font-lock-keywords
org-element--cache org-element--cache-objects org-element--cache-sync-keys
org-element--cache-sync-requests org-element--cache-sync-timer)
"List of variables not copied through upon buffer duplication.
Export process takes place on a copy of the original buffer.
When this copy is created, all Org related local variables not in
this list are copied to the new buffer. Variables with an
unreadable value are also ignored.")
(defvar org-export-async-debug nil
"Non-nil means asynchronous export process should leave data behind.
@ -2964,11 +2974,7 @@ The function assumes BUFFER's major mode is `org-mode'."
(when (consp entry)
(let ((var (car entry))
(val (cdr entry)))
(and (not (memq var '(org-font-lock-keywords
;; Do not share cache across
;; buffers as values are
;; modified by side effect.
org-element--cache)))
(and (not (memq var org-export-ignored-local-variables))
(or (memq var
'(default-directory
buffer-file-name

View File

@ -3036,5 +3036,116 @@ Paragraph \\alpha."
(org-element-type (org-element-context (org-element-at-point))))))))
;;; Test Cache.
(ert-deftest test-org-element/cache ()
"Test basic expectations and common pitfalls for cache."
;; Shift positions.
(should
(equal '(18 . 23)
(org-test-with-temp-text "para1\n\npara2\n\npara3"
(let ((org-element-use-cache t))
(save-excursion (goto-char (point-max)) (org-element-at-point))
(insert "add")
(forward-line 4)
(let ((element (org-element-at-point)))
(cons (org-element-property :begin element)
(org-element-property :end element)))))))
;; Partial shifting: when the contents of a greater element are
;; modified, only shift ending positions.
(should
(org-test-with-temp-text
"#+BEGIN_CENTER\nPara1\n\nPara2\n\nPara3\n#+END_CENTER"
(let ((org-element-use-cache t))
(save-excursion (search-forward "3") (org-element-at-point))
(search-forward "Para2")
(insert " ")
(let ((element (org-element-property :parent (org-element-at-point))))
(equal (cons (org-element-property :begin element)
(org-element-property :end element))
(cons (point-min) (point-max)))))))
;; Re-parent shifted elements.
(should
(eq 'item
(org-test-with-temp-text "- item\n\n\n para1\n para2"
(let ((org-element-use-cache t))
(end-of-line)
(org-element-at-point)
(save-excursion (goto-char (point-max)) (org-element-at-point))
(forward-line)
(delete-char 1)
(goto-char (point-max))
(org-element-type
(org-element-property :parent (org-element-at-point)))))))
;; Modifying the last line of an element alters the element below.
(should
(org-test-with-temp-text "para1\n\npara2"
(let ((org-element-use-cache t))
(goto-char (point-max))
(org-element-at-point)
(forward-line -1)
(insert "merge")
(let ((element (org-element-at-point)))
(equal (cons (org-element-property :begin element)
(org-element-property :end element))
(cons (point-min) (point-max)))))))
;; Modifying the first line of an element alters the element above.
(should
(org-test-with-temp-text ": fixed-width\n:not-fixed-width"
(let ((org-element-use-cache t))
(goto-char (point-max))
(org-element-at-point)
(search-backward ":")
(forward-char)
(insert " ")
(let ((element (org-element-at-point)))
(equal (cons (org-element-property :begin element)
(org-element-property :end element))
(cons (point-min) (point-max)))))))
;; Sensitive change: adding a line alters document structure both
;; above and below.
(should
(eq 'example-block
(org-test-with-temp-text "#+BEGIN_EXAMPLE\nPara1\n\nPara2\n"
(let ((org-element-use-cache t))
(goto-char (point-max))
(org-element-at-point)
(insert "#+END_EXAMPLE")
(search-backward "Para1")
(org-element-type (org-element-at-point))))))
(should
(eq 'example-block
(org-test-with-temp-text "Para1\n\nPara2\n#+END_EXAMPLE"
(let ((org-element-use-cache t))
(save-excursion (goto-char (point-max)) (org-element-at-point))
(insert "#+BEGIN_EXAMPLE\n")
(search-forward "Para2")
(org-element-type (org-element-at-point))))))
;; Sensitive change: removing a line alters document structure both
;; above and below.
(should
(eq 'example-block
(org-test-with-temp-text
"# +BEGIN_EXAMPLE\nPara1\n\nPara2\n#+END_EXAMPLE"
(let ((org-element-use-cache t))
(save-excursion (goto-char (point-max)) (org-element-at-point))
(forward-char)
(delete-char 1)
(search-forward "Para2")
(org-element-type (org-element-at-point))))))
(should
(eq 'example-block
(org-test-with-temp-text
"#+BEGIN_EXAMPLE\nPara1\n\nPara2\n# +END_EXAMPLE"
(let ((org-element-use-cache t))
(save-excursion (goto-char (point-max)) (org-element-at-point))
(search-forward "# ")
(delete-char -1)
(search-backward "Para1")
(org-element-type (org-element-at-point)))))))
(provide 'test-org-element)
;;; test-org-element.el ends here