I'm using the package "org-roam" https://github.com/org-roam/org-roam.

But when I have lot of Org files under `org-directory' & `org-roam-directory'.
Then org-roam update ID locations with command 
`org-roam-update-org-id-locations',
and `org-roam-db-sync` will suspend and spend a long time for Emacs.

So I think update ID locations on every `after-save-hook` everytime file
updated for new :ID: locations using an "incremental way". This can
avoid run `org-id-update-id-locations' globally scan lots of files
repeatedly.

Bellowing is my prototype code (not a patch) for my propose for your reference.
Hope maintainer @Carsten Dominik (who is author of org-id.el) or Ihor can 
complete the patch.
Because I can't totally figure out the logic, and pass the testing, etc.

#+begin_src emacs-lisp
;; TEMP: extract core logic from `org-id-update-id-locations'
(defun org-id-update-id-locations-for-file (&optional file silent)
    "Scan relevant file for IDs.
Store the relation between file and corresponding IDs.
If SILENT is non-nil, messages are suppressed."
    (interactive nil org-mode)
    (let* ((file (or file (buffer-file-name)))
           (id-regexp (rx (seq bol (0+ (any "\t ")) ":ID:" (1+ " ") (not (any " 
")))))
           (checksum (when (file-exists-p file)
                       (list file (file-attribute-modification-time 
(file-attributes file)))))
           (id-locations nil))
      (unless (equal checksum org-id--locations-checksum) ; Files have changed 
since the last update.
        (with-temp-buffer
          (delay-mode-hooks
            (org-mode)
            (let ((buf (or (get-file-buffer file) nil)))
              (with-current-buffer (or buf (current-buffer))
                (unless buf (insert-file-contents file nil nil nil 'replace))
                (let ((ids nil)
                      (case-fold-search t))
                  (org-with-point-at 1
                    (while (re-search-forward id-regexp nil t)
                      (let* ((node (org-element-at-point)))
                        (when (org-element-type-p node 'node-property)
                          (push (org-element-property :value node) ids))))
                    (when ids (push (cons (abbreviate-file-name file) ids) 
id-locations))))))))
        (add-to-list 'org-id-files (abbreviate-file-name file))
        (setq file-id-locations (org-id-alist-to-hash id-locations))
        ;; save to global `org-id-locations'
        (when (and org-id-track-globally (called-interactively-p 'interactive))
          (maphash
           (lambda (key value)
             (unless (gethash key file-id-locations)
               (puthash key value org-id-locations)))
           file-id-locations)
          ;; save `org-id-locations' in `org-id-locations-file'.
          (org-id-locations-save))
        (setq org-id--locations-checksum checksum)
        (message "File %s scanned, and %d IDs found." (file-name-nondirectory 
file) (hash-table-count file-id-locations)))
      file-id-locations))

(defun org-id-update-id-locations (&optional files silent)
    "Scan relevant files for IDs.
Store the relation between files and corresponding IDs.
This will scan all agenda files, all associated archives, all open Org
files, and all files currently mentioned in `org-id-locations'.
When FILES is given, scan also these files.
If SILENT is non-nil, messages are suppressed."
    (interactive)
    (unless org-id-track-globally
      (error "Please turn on `org-id-track-globally' if you want to track IDs"))
    (let* ((files (delete-dups
                   (mapcar #'file-truename
                           (cl-remove-if-not
                            ;; Default `org-id-extra-files' value contains
                            ;; `agenda-archives' symbol.
                            #'stringp
                            (append
                             ;; Agenda files and all associated archives.
                             (org-agenda-files t org-id-search-archives)
                             ;; Explicit extra files.
                             (if (symbolp org-id-extra-files)
                                 (symbol-value org-id-extra-files)
                               org-id-extra-files)
                             ;; All files known to have IDs.
                             org-id-files
                             ;; All Org files open in Emacs.
                             (mapcar #'buffer-file-name (org-buffer-list 'files 
t))
                             ;; Additional files from function call.
                             files))))))
      (mapcar
       (lambda (file)
         (let* ((file-id-locations (org-id-update-id-locations-for-file file)))
           (unless (and (bound-and-true-p file-id-locations) (hash-table-p 
file-id-locations))
             (setq file-id-locations (org-id-alist-to-hash file-id-locations)))
           (maphash
            (lambda (key value)
              (if org-id-locations
                  (puthash key value org-id-locations)
                (setq org-id-locations (copy-hash-table file-id-locations))))
            file-id-locations)))
       files))
    ;; (org-id-locations-save) ; save `org-id-locations' in 
`org-id-locations-file'.
    (message "org-id totally hashed %d IDs from %d files"
             (length org-id-files) (hash-table-count org-id-locations)))

(defun my/org-roam/update-current-buffer-id-id-locations ()
    "org-roam update current entry ID to id locations."
    (interactive nil org-mode)
    ;; add current entry ID to id locations
    (org-id-add-location (org-id-get) (buffer-file-name))
    (org-id-update-id-locations-for-file (buffer-file-name))
    (org-id-locations-save))
#+end_src

-- 

[ stardiviner ]
I try to make every word tell the meaning that I want to express without 
misunderstanding.

Blog: https://stardiviner.github.io/
IRC(libera.chat, freenode): stardiviner, Matrix: stardiviner
GPG: F09F650D7D674819892591401B5DF1C95AE89AC3

Attachment: signature.asc
Description: PGP signature

Reply via email to