diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ca4636..13c5033 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ In this release we support fuzzy links of the form `[[Title]]`, `[[*Headline]]` ### Features +- [#1061](https://github.com/org-roam/org-roam/pull/1061) Speed up the extraction of file properties, headlines, and titles - [#1046](https://github.com/org-roam/org-roam/pull/1046) New user option to exclude files from Org-roam - [#1032](https://github.com/org-roam/org-roam/pull/1032) File changes are now propagated to the database on idle timer. This prevents large wait times during file saves. - [#974](https://github.com/org-roam/org-roam/pull/974) Protect region targeted by `org-roam-insert` diff --git a/org-roam.el b/org-roam.el index da4ecab..bd5b31e 100644 --- a/org-roam.el +++ b/org-roam.el @@ -495,16 +495,20 @@ Use external shell commands if defined in `org-roam-list-files-commands'." (defun org-roam--extract-global-props (props) "Extract PROPS from the current org buffer. The search terminates when the first property is encountered." - (let ((buf (org-element-parse-buffer)) - res) - (dolist (prop props) - (let ((p (org-element-map buf 'keyword - (lambda (kw) - (when (string-equal (org-element-property :key kw) prop) - (org-element-property :value kw))) - :first-match t))) - (push (cons prop p) res))) - res)) + (if (functionp 'org-collect-keywords) + (->> (org-collect-keywords props) + ;; convert (("TITLE" "my title")) to (("TITLE" . "my title")) + (mapcar (pcase-lambda (`(,k ,v)) (cons k v)))) + (let ((buf (org-element-parse-buffer)) + res) + (dolist (prop props) + (let ((p (org-element-map buf 'keyword + (lambda (kw) + (when (string-equal (org-element-property :key kw) prop) + (org-element-property :value kw))) + :first-match t))) + (push (cons prop p) res))) + res))) (defun org-roam--expand-links (content path) "Crawl CONTENT for relative links and expand them. @@ -631,15 +635,15 @@ it as FILE-PATH." If FILE-PATH is nil, use the current file." (let ((file-path (or file-path (file-truename (buffer-file-name))))) - (org-element-map (org-element-parse-buffer) 'node-property - (lambda (node-property) - (let ((key (org-element-property :key node-property)) - (value (org-element-property :value node-property))) - (when (string= key "ID") - (let* ((id value) - (data (vector id - file-path))) - data))))))) + ;; Use `org-map-region' instead of `org-map-entries' as the latter + ;; would require another step to remove all nil values. + (let ((result nil)) + (org-map-region + (lambda () + (when-let ((id (org-entry-get nil "ID"))) + (push (vector id file-path) result))) + (point-min) (point-max)) + result))) (defun org-roam--extract-titles-title () "Return title from \"#+title\" of the current buffer." @@ -665,12 +669,15 @@ Reads from the \"roam_alias\" property." (defun org-roam--extract-titles-headline () "Return the first headline of the current buffer." - (let ((headline (org-element-map - (org-element-parse-buffer) - 'headline - (lambda (h) - (org-no-properties (org-element-property :raw-value h))) - :first-match t))) + (let ((headline (save-excursion + (goto-char (point-min)) + ;; "What happens if a heading star was quoted + ;; before the first heading?" + ;; - `org-map-region' also does this + ;; - Org already breaks badly when you do that; + ;; precede the heading star with a ",". + (re-search-forward org-outline-regexp-bol nil t) + (org-entry-get nil "ITEM")))) (when headline (list headline)))) diff --git a/tests/test-org-roam.el b/tests/test-org-roam.el index 32d6cd3..3995b0a 100644 --- a/tests/test-org-roam.el +++ b/tests/test-org-roam.el @@ -255,7 +255,7 @@ (it "extracts headlines" (expect (test #'org-roam--extract-headlines "headlines/headline.org") - :to-equal + :to-have-same-items-as `(["e84d0630-efad-4017-9059-5ef917908823" ,(test-org-roam--abs-path "headlines/headline.org")] ["801b58eb-97e2-435f-a33e-ff59a2f0c213" ,(test-org-roam--abs-path "headlines/headline.org")])))))