org-element: Small speed-up

* lisp/org-element.el (org-element--parse-objects): Add an optional
  argument to avoid walking a secondary string twice.  Make less
  consing.
(org-element--parse-elements): Make less consing.
(org-element-headline-parser):
(org-element-inlinetask-parser):
(org-element-item-parser):
(org-element-parse-secondary-string): Apply changes.
This commit is contained in:
Nicolas Goaziou 2016-01-21 18:43:20 +01:00
parent 188823e372
commit af1bd190e3
1 changed files with 110 additions and 107 deletions

View File

@ -990,7 +990,7 @@ Assume point is at beginning of the headline."
(org-element-put-property (org-element-put-property
headline :title headline :title
(if raw-secondary-p raw-value (if raw-secondary-p raw-value
(let ((title (org-element--parse-objects (org-element--parse-objects
(progn (goto-char title-start) (progn (goto-char title-start)
(skip-chars-forward " \t") (skip-chars-forward " \t")
(point)) (point))
@ -998,9 +998,8 @@ Assume point is at beginning of the headline."
(skip-chars-backward " \t") (skip-chars-backward " \t")
(point)) (point))
nil nil
(org-element-restriction 'headline)))) (org-element-restriction 'headline)
(dolist (datum title title) headline)))))))
(org-element-put-property datum :parent headline)))))))))
(defun org-element-headline-interpreter (headline contents) (defun org-element-headline-interpreter (headline contents)
"Interpret HEADLINE element as Org syntax. "Interpret HEADLINE element as Org syntax.
@ -1126,7 +1125,7 @@ Assume point is at beginning of the inline task."
(org-element-put-property (org-element-put-property
inlinetask :title inlinetask :title
(if raw-secondary-p raw-value (if raw-secondary-p raw-value
(let ((title (org-element--parse-objects (org-element--parse-objects
(progn (goto-char title-start) (progn (goto-char title-start)
(skip-chars-forward " \t") (skip-chars-forward " \t")
(point)) (point))
@ -1134,9 +1133,8 @@ Assume point is at beginning of the inline task."
(skip-chars-backward " \t") (skip-chars-backward " \t")
(point)) (point))
nil nil
(org-element-restriction 'inlinetask)))) (org-element-restriction 'inlinetask)
(dolist (datum title title) inlinetask))))))
(org-element-put-property datum :parent inlinetask))))))))
(defun org-element-inlinetask-interpreter (inlinetask contents) (defun org-element-inlinetask-interpreter (inlinetask contents)
"Interpret INLINETASK element as Org syntax. "Interpret INLINETASK element as Org syntax.
@ -1248,11 +1246,10 @@ Assume point is at the beginning of the item."
(let ((raw (org-list-get-tag begin struct))) (let ((raw (org-list-get-tag begin struct)))
(when raw (when raw
(if raw-secondary-p raw (if raw-secondary-p raw
(let ((tag (org-element--parse-objects (org-element--parse-objects
(match-beginning 4) (match-end 4) nil (match-beginning 4) (match-end 4) nil
(org-element-restriction 'item)))) (org-element-restriction 'item)
(dolist (datum tag tag) item))))))))
(org-element-put-property datum :parent item))))))))))
(defun org-element-item-interpreter (item contents) (defun org-element-item-interpreter (item contents)
"Interpret ITEM element as Org syntax. "Interpret ITEM element as Org syntax.
@ -3979,11 +3976,8 @@ If STRING is the empty string or nil, return nil."
(set (make-local-variable (car v)) (cdr v))))) (set (make-local-variable (car v)) (cdr v)))))
(insert string) (insert string)
(restore-buffer-modified-p nil) (restore-buffer-modified-p nil)
(let ((data (org-element--parse-objects (org-element--parse-objects
(point-min) (point-max) nil restriction))) (point-min) (point-max) nil restriction parent))))))
(when parent
(dolist (o data) (org-element-put-property o :parent parent)))
data))))))
(defun org-element-map (defun org-element-map
(data types fun &optional info first-match no-recursion with-affiliated) (data types fun &optional info first-match no-recursion with-affiliated)
@ -4200,7 +4194,7 @@ Elements are accumulated into ACC."
;; When parsing only headlines, skip any text before first one. ;; When parsing only headlines, skip any text before first one.
(when (and (eq granularity 'headline) (not (org-at-heading-p))) (when (and (eq granularity 'headline) (not (org-at-heading-p)))
(org-with-limited-levels (outline-next-heading))) (org-with-limited-levels (outline-next-heading)))
;; Main loop start. (let (elements)
(while (< (point) end) (while (< (point) end)
;; Find current element's type and parse it accordingly to ;; Find current element's type and parse it accordingly to
;; its category. ;; its category.
@ -4238,11 +4232,11 @@ Elements are accumulated into ACC."
(org-element--parse-objects (org-element--parse-objects
cbeg (org-element-property :contents-end element) element cbeg (org-element-property :contents-end element) element
(org-element-restriction type)))) (org-element-restriction type))))
(org-element-adopt-elements acc element) (push (org-element-put-property element :parent acc) elements)
;; Update mode. ;; Update mode.
(setq mode (org-element--next-mode type nil)))) (setq mode (org-element--next-mode type nil))))
;; Return result. ;; Return result.
acc)) (apply #'org-element-set-contents acc (nreverse elements)))))
(defun org-element--object-lex (restriction) (defun org-element--object-lex (restriction)
"Return next object in current buffer or nil. "Return next object in current buffer or nil.
@ -4331,51 +4325,60 @@ to an appropriate container (e.g., a paragraph)."
((and limit (memq 'link restriction)) ((and limit (memq 'link restriction))
(goto-char limit) (org-element-link-parser))))))) (goto-char limit) (org-element-link-parser)))))))
(defun org-element--parse-objects (beg end acc restriction) (defun org-element--parse-objects (beg end acc restriction &optional parent)
"Parse objects between BEG and END and return recursive structure. "Parse objects between BEG and END and return recursive structure.
Objects are accumulated in ACC. Objects are accumulated in ACC. RESTRICTION is a list of object
successors which are allowed in the current object.
RESTRICTION is a list of object successors which are allowed in ACC becomes the parent for all parsed objects. However, if ACC
the current object." is nil (i.e., a secondary string is being parsed) and optional
argument PARENT is non-nil, use it as the parent for all objects.
Eventually, if both ACC and PARENT are nil, the common parent is
the list of objects itself."
(save-excursion (save-excursion
(save-restriction (save-restriction
(narrow-to-region beg end) (narrow-to-region beg end)
(goto-char (point-min)) (goto-char (point-min))
(let (next-object) (let ((tab (make-string tab-width ?\s))
next-object contents)
(while (and (not (eobp)) (while (and (not (eobp))
(setq next-object (org-element--object-lex restriction))) (setq next-object (org-element--object-lex restriction)))
;; 1. Text before any object. Untabify it. ;; Text before any object. Untabify it.
(let ((obj-beg (org-element-property :begin next-object))) (let ((obj-beg (org-element-property :begin next-object)))
(unless (= (point) obj-beg) (unless (= (point) obj-beg)
(setq acc (let ((text
(org-element-adopt-elements
acc
(replace-regexp-in-string (replace-regexp-in-string
"\t" (make-string tab-width ?\s) "\t" tab
(buffer-substring-no-properties (point) obj-beg)))))) (buffer-substring-no-properties (point) obj-beg))))
;; 2. Object... (push (if acc (org-element-put-property text :parent acc) text)
contents))))
;; Object...
(let ((obj-end (org-element-property :end next-object)) (let ((obj-end (org-element-property :end next-object))
(cont-beg (org-element-property :contents-begin next-object))) (cont-beg (org-element-property :contents-begin next-object)))
;; Fill contents of NEXT-OBJECT by side-effect, if it has (when acc (org-element-put-property next-object :parent acc))
;; a recursive type. (push (if cont-beg
(when (and cont-beg ;; Fill contents of NEXT-OBJECT if possible.
(memq (car next-object) org-element-recursive-objects))
(org-element--parse-objects (org-element--parse-objects
cont-beg (org-element-property :contents-end next-object) cont-beg
next-object (org-element-restriction next-object))) (org-element-property :contents-end next-object)
(setq acc (org-element-adopt-elements acc next-object)) next-object
(goto-char obj-end)))) (org-element-restriction next-object))
;; 3. Text after last object. Untabify it. next-object)
contents)
(goto-char obj-end)))
;; Text after last object. Untabify it.
(unless (eobp) (unless (eobp)
(setq acc (let ((text (replace-regexp-in-string
(org-element-adopt-elements "\t" tab (buffer-substring-no-properties (point) end))))
acc (push (if acc (org-element-put-property text :parent acc) text)
(replace-regexp-in-string contents)))
"\t" (make-string tab-width ?\s) ;; Result. Set appropriate parent.
(buffer-substring-no-properties (point) end))))) (if acc (apply #'org-element-set-contents acc (nreverse contents))
;; Result. (let* ((contents (nreverse contents))
acc))) (parent (or parent contents)))
(dolist (datum contents contents)
(org-element-put-property datum :parent parent))))))))