diff --git a/org-roam.el b/org-roam.el index 2aa8c67..3bf1035 100644 --- a/org-roam.el +++ b/org-roam.el @@ -169,60 +169,83 @@ If `ABSOLUTE', return the absolute file-path. Else, return the relative file-pat ,(async-inject-variables "org-roam-files") ,(async-inject-variables "org-roam-directory") (let ((backward-links (make-hash-table :test #'equal)) - (forward-links (make-hash-table :test #'equal))) - (cl-flet* ((org-roam--parse-content (file) (with-temp-buffer - (insert-file-contents file) - (with-current-buffer (current-buffer) - (org-element-map (org-element-parse-buffer) 'link - (lambda (link) - (let ((type (org-element-property :type link)) - (path (org-element-property :path link)) - (start (org-element-property :begin link))) - (when (and (string= type "file") - (string= (file-name-extension path) "org")) - (goto-char start) - (let* ((element (org-element-at-point)) - (content (or (org-element-property :raw-value element) - (buffer-substring - (or (org-element-property :content-begin element) - (org-element-property :begin element)) - (or (org-element-property :content-end element) - (org-element-property :end element)))))) - (list :from file - :to (file-truename (expand-file-name path org-roam-directory)) - :content (string-trim content)))))))))) - (org-roam--process-items (items) (mapcar - (lambda (item) - (pcase-let ((`(:from ,p-from :to ,p-to :content ,content) item)) - ;; Build forward-links - (let ((links (gethash p-from forward-links))) - (if links - (puthash p-from - (if (member p-to links) - links - (cons p-to links)) forward-links) - (puthash p-from (list p-to) forward-links))) - ;; Build backward-links - (let ((contents-hash (gethash p-to backward-links))) - (if contents-hash - (if-let ((contents-list (gethash p-from contents-hash))) - (let ((updated (cons content contents-list))) - (puthash p-from updated contents-hash) - (puthash p-to contents-hash backward-links)) - (progn - (puthash p-from (list content) contents-hash) - (puthash p-to contents-hash backward-links))) - (let ((contents-hash (make-hash-table :test #'equal))) - (puthash p-from (list content) contents-hash) - (puthash p-to contents-hash backward-links)))))) - items))) + (forward-links (make-hash-table :test #'equal)) + (file-titles (make-hash-table :test #'equal))) + (cl-flet* ((org-roam--parse-content + (file) + (with-temp-buffer + (insert-file-contents file) + (with-current-buffer (current-buffer) + (org-element-map (org-element-parse-buffer) 'link + (lambda (link) + (let ((type (org-element-property :type link)) + (path (org-element-property :path link)) + (start (org-element-property :begin link))) + (when (and (string= type "file") + (string= (file-name-extension path) "org")) + (goto-char start) + (let* ((element (org-element-at-point)) + (content (or (org-element-property :raw-value element) + (buffer-substring + (or (org-element-property :content-begin element) + (org-element-property :begin element)) + (or (org-element-property :content-end element) + (org-element-property :end element)))))) + (list :from file + :to (file-truename (expand-file-name path org-roam-directory)) + :content (string-trim content)))))))))) + (org-roam--process-items + (items) + (mapcar + (lambda (item) + (pcase-let ((`(:from ,p-from :to ,p-to :content ,content) item)) + ;; Build forward-links + (let ((links (gethash p-from forward-links))) + (if links + (puthash p-from + (if (member p-to links) + links + (cons p-to links)) forward-links) + (puthash p-from (list p-to) forward-links))) + ;; Build backward-links + (let ((contents-hash (gethash p-to backward-links))) + (if contents-hash + (if-let ((contents-list (gethash p-from contents-hash))) + (let ((updated (cons content contents-list))) + (puthash p-from updated contents-hash) + (puthash p-to contents-hash backward-links)) + (progn + (puthash p-from (list content) contents-hash) + (puthash p-to contents-hash backward-links))) + (let ((contents-hash (make-hash-table :test #'equal))) + (puthash p-from (list content) contents-hash) + (puthash p-to contents-hash backward-links)))))) + items)) + (org-roam--extract-title + (buffer) + (with-current-buffer buffer + (org-element-map + (org-element-parse-buffer) + 'keyword + (lambda (kw) + (when (string= (org-element-property :key kw) "TITLE") + (org-element-property :value kw))) + :first-match t)))) (mapcar #'org-roam--process-items - (mapcar #'org-roam--parse-content org-roam-files))) + (mapcar #'org-roam--parse-content org-roam-files)) + (mapcar (lambda (file) + (with-temp-buffer + (insert-file-contents file) + (when-let ((title (org-roam--extract-title (current-buffer)))) + (puthash file title file-titles)))) + org-roam-files)) (list :forward forward-links - :backward backward-links))) + :backward backward-links + :titles file-titles))) (lambda (cache) - (setq org-roam-cache cache)))) + (setq org-roam-cache cache) + (message "Org-roam cache built!")))) (defun org-roam--insert-item (item) "Insert `ITEM' into `org-roam-cache'. @@ -231,7 +254,8 @@ If `ABSOLUTE', return the absolute file-path. Else, return the relative file-pat Before calling this function, `org-roam-cache' should be already populated." (let ((forward-cache (plist-get org-roam-cache :forward)) - (backward-cache (plist-get org-roam-cache :backward))) + (backward-cache (plist-get org-roam-cache :backward)) + (title-cache (plist-get org-roam-cache :titles))) (pcase-let ((`(:from ,p-from :to ,p-to :content ,content) item)) ;; Build forward-links (let ((links (gethash p-from forward-cache))) @@ -255,7 +279,8 @@ Before calling this function, `org-roam-cache' should be already populated." (puthash p-from (list content) contents-hash) (puthash p-to contents-hash backward-cache)))) (setq org-roam-cache (list :forward forward-cache - :backward backward-cache))))) + :backward backward-cache + :titles title-cache))))) (defun org-roam--parse-content () "Parse the current buffer, and return a list of items for processing." @@ -286,8 +311,9 @@ This is equivalent to removing the node from the graph." (with-current-buffer (current-buffer) (let ((file (file-truename (buffer-file-name buffer))) (forward-cache (plist-get org-roam-cache :forward)) - (backward-cache (plist-get org-roam-cache :backward))) - ;; Setup 1: Remove all existing links for file + (backward-cache (plist-get org-roam-cache :backward)) + (titles-cache (plist-get org-roam-cache :titles))) + ;; Step 1: Remove all existing links for file (when-let ((forward-links (gethash file forward-cache))) ;; Delete backlinks to file (dolist (link forward-links) @@ -296,12 +322,28 @@ This is equivalent to removing the node from the graph." (puthash link backward-links backward-cache))) ;; Clean out forward links (remhash file forward-cache)) - (setq org-roam-cache (list :forward forward-cache :backward backward-cache))))) + ;; Step 2: Remove from the title cache + (remhash file titles-cache) + (setq org-roam-cache (list :forward forward-cache + :backward backward-cache + :titles titles-cache))))) + +(defun org-roam--update-cache-title (buffer) + "Inserts the `TITLE' of file in buffer into the cache." + (when-let ((titles-cache (plist-get org-roam-cache :titles)) + (title (org-roam--extract-title buffer))) + (puthash (file-truename (buffer-file-name buffer)) + title + titles-cache) + (setq org-roam-cache (plist-put org-roam-cache :titles titles-cache)))) (defun org-roam--update-cache () "Update `org-roam-cache' for the current buffer file." (save-excursion (org-roam--clear-cache-for-buffer (current-buffer)) + ;; Insert into title cache + (org-roam--update-cache-title (current-buffer)) + ;; Insert new items (let ((items (org-roam--parse-content))) (dolist (item items) (org-roam--insert-item item)))))