ENH make buffer scanner faster

This commit is contained in:
Nathan Dwarshuis 2022-03-27 11:56:40 -04:00
parent ea9ab62f2c
commit 65389c6611
1 changed files with 76 additions and 68 deletions

View File

@ -1218,10 +1218,9 @@ A date like (YEAR MONTH DAY).")
(defun org-x-dag-get-local-properties (bounds prop-pairs) (defun org-x-dag-get-local-properties (bounds prop-pairs)
(when bounds (when bounds
(-let (((_ beg end _) bounds) (-let (((_ beg end _) bounds))
(cur))
(save-excursion (save-excursion
(let (acc) (let (acc cur)
(while prop-pairs (while prop-pairs
(goto-char beg) (goto-char beg)
(setq cur (car prop-pairs)) (setq cur (car prop-pairs))
@ -1267,7 +1266,6 @@ A date like (YEAR MONTH DAY).")
(defconst org-x-dag-prop-drawer-re (defconst org-x-dag-prop-drawer-re
(concat (concat
"^[\t ]*:PROPERTIES:[\t ]*\n" "^[\t ]*:PROPERTIES:[\t ]*\n"
;; "\\([\t ]*:\\S-+:\\(?: .*\\)?[\t ]*\n\\)"
"\\(\\(.\\|\n\\)*?\\)" "\\(\\(.\\|\n\\)*?\\)"
"[\t ]*:END:[\t ]*$")) "[\t ]*:END:[\t ]*$"))
@ -1311,78 +1309,88 @@ used for optimization."
(org-x-dag-node i ps ,form))) (org-x-dag-node i ps ,form)))
(defun org-x-dag-get-buffer-nodes (file-meta kws target-props) (defun org-x-dag-get-buffer-nodes (file-meta kws target-props)
(let ((line-re (org-x-dag-line-regexp kws)) (goto-char (point-min))
(let* ((line-re (org-x-dag-line-regexp kws))
(first-hl (org-x-dag-next-headline))
;; If not on a headline, check for a property drawer with links in it
(this-file-links (unless (= ?* (following-char))
(org-x-dag-get-parent-links first-hl nil)))
(pps (--map (cons it (org-re-property it nil t)) target-props)) (pps (--map (cons it (org-re-property it nil t)) target-props))
(id-prop (org-re-property "ID" nil t)) (id-prop (org-re-property "ID" nil t))
cur-path this-point this-key this-level this-todo has-todo this-parent ;; stack vars
this-tags this-meta all-tags this-file-links this-links this-parent-key acc) bare-stack node-level bury-level
(goto-char (point-min)) ;; data vars
;; If not on a headline, check for a property drawer with links in it this-id this-level this-todo this-tags this-pblock acc)
(unless (= ?* (following-char)) (when first-hl
(->> (org-x-dag-next-headline) (goto-char first-hl))
(org-x-dag-get-parent-links nil) (while (looking-at line-re)
(setq this-file-links)))
;; loop through all headlines
(while (re-search-forward line-re nil t)
;; Keep track of how 'deep' we are in a given org-tree using a stack. The ;; Keep track of how 'deep' we are in a given org-tree using a stack. The
;; stack will have members like (LEVEL KEY TAGS) where LEVEL is the level ;; stack will have members like (LEVEL KEY TAGS) where LEVEL is the level
;; of the headline and KEY is the node key if it has a keyword, and TAGS ;; of the headline and KEY is the node key if it has a keyword, and TAGS
;; is a list of tags for the headlines. Only add a node to the accumulator ;; is a list of tags for the headlines. Only add a node to the accumulator
;; if it has a keyword and an ID property, and only include its parent ;; if it has a keyword and an ID property, and only include its parent
;; headline if the parent also has a keyword. ;; headline if the parent also has a keyword.
(setq this-point (car (match-data)) (setq this-point (car (match-data t))
this-level (length (match-string 1)) this-level (length (match-string 1))
this-todo (match-string 2) this-todo (match-string 2)
this-title (-if-let (s (match-string 3)) (s-trim s) "") this-title (match-string 3)
this-tags (-some-> (match-string-no-properties 4) this-tags (match-string-no-properties 4)
(split-string ":" t)) next-pos (or (org-x-dag-next-headline) (point-max)))
next-pos (or (org-x-dag-next-headline) (point-max)) (unless (and bury-level (< bury-level this-level))
this-key nil
this-links nil)
;; Adjust the stack so that the top headline is the parent of the ;; Adjust the stack so that the top headline is the parent of the
;; current headline ;; current headline
(while (and cur-path (<= this-level (nth 0 (car cur-path)))) (when (and node-level (<= this-level node-level))
(!cdr cur-path)) (setq node-level nil))
(setq this-parent (car cur-path) (unless node-level
this-parent-key (nth 1 this-parent)) (while (and bare-stack (<= this-level (nth 0 (car bare-stack))))
(!cdr bare-stack)))
;; Add the current headline to accumulator if it is a node, but only if ;; Add the current headline to accumulator if it is a node, but only if
;; its parent is a node or none of its parents are nodes ;; its parent is a node or none of its parents are nodes
(when (and this-todo (cond
(or this-parent-key (--none-p (nth 1 it) cur-path)) ((and this-todo
(setq (setq this-pblock (org-x-dag-property-block next-pos)
this-prop-bounds (org-x-dag-property-block next-pos) this-id (org-x-dag-get-local-property this-pblock id-prop)))
this-key (org-x-dag-get-local-property this-prop-bounds id-prop))) (setq bury-level nil
;; If parent is not a node and we want tag inheritance, store all this-tags nil)
;; tags above this headline (including file tags) (when this-tags
(setq this-links (or (-> (nth 3 this-prop-bounds) (setq this-tags (split-string this-tags ":" t)))
(when (and (not node-level) bare-stack)
(setq this-tags (->> (car bare-stack)
(nth 1)
(append this-tags))))
(-> (list
:id this-id
:parents (or (-> (nth 3 this-pblock)
(org-x-dag-get-parent-links next-pos)) (org-x-dag-get-parent-links next-pos))
(unless this-parent-key (unless node-level
(-some->> (--first (nth 3 it) cur-path) (nth 2 (car bare-stack))))
(nth 3)
(append this-file-links))))
this-node
(list :id this-key
:parents this-links
:node-meta :node-meta
(list :point this-point (list
:point this-point
:level this-level :level this-level
:todo this-todo :todo this-todo
:title this-title :title (if this-title (s-trim-right this-title) "")
:tags (if (and (not this-parent-key) org-use-tag-inheritance) :tags this-tags
(->> cur-path :planning (->> (car this-pblock)
(--mapcat (nth 2 it))
(append this-tags org-file-tags))
this-tags)
:planning (->> (car this-prop-bounds)
(org-x-dag-parse-this-planning)) (org-x-dag-parse-this-planning))
:props (-> this-prop-bounds :props (org-x-dag-get-local-properties this-pblock pps)))
(org-x-dag-get-local-properties pps))))) (!cons acc))
(!cons this-node acc)) (setq node-level this-level))
;; Add current headline to stack ;; Underneath a node but not on a node, therefore we are buried
;; TODO this isn't necessary for non-node children of nodes (node-level
(!cons (list this-level this-key this-tags this-links) cur-path) (setq bury-level this-level))
;; Since we know the next headline's position already, skip ahead to ;; Anything else means we are on a bare headline above any nodes
;; save some work (t
(setq bury-level nil
node-level nil)
(when this-tags
(setq this-tags (split-string this-tags ":" t)))
(-> (list this-level
(append this-tags (or (nth 1 (car bare-stack)) org-file-tags))
(or (org-x-dag-get-parent-links nil next-pos)
(nth 2 (car bare-stack))
this-file-links))
(!cons bare-stack)))))
(goto-char next-pos)) (goto-char next-pos))
(nreverse acc))) (nreverse acc)))