Ihor Radchenko <yanta...@posteo.net> writes: > What if FILE is correct, but the file has been edited and the heading > with ID is now at a different place in that file? It would be more > efficient to try searching via `org-id-find-id-in-file' rather than > falling back to full scan in `org-id-update-id-locations'.
Indeed, the patch below may fix this issue.
>From 6d2d2a114870df2582be341ffbd5e8d26dded461 Mon Sep 17 00:00:00 2001 From: doerthous <doerth...@gmail.com> Date: Mon, 28 Apr 2025 18:54:10 +0800 Subject: [PATCH] org-id: Cache entry position * lisp/org-id.el: To speedup org id location lookup process, cache the entry position in `org-id-locations'. --- lisp/org-id.el | 45 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/lisp/org-id.el b/lisp/org-id.el index 6ff63b295..1bf5b87b6 100644 --- a/lisp/org-id.el +++ b/lisp/org-id.el @@ -396,15 +396,38 @@ With optional argument MARKERP, return the position as a new marker." (cond ((symbolp id) (setq id (symbol-name id))) ((numberp id) (setq id (number-to-string id)))) - (let ((file (org-id-find-id-file id)) - org-agenda-new-buffers where) - (when file + (let* ((loc (org-id--find-id-location id)) + (file (if (consp loc) (car loc) loc)) + (pos (if (consp loc) (cdr loc))) + org-agenda-new-buffers where buf) + ;; When loc is a cons cell, check whether it's valid or not. + (when (consp loc) + (setq buf (or (find-buffer-visiting file) + (find-file-noselect file))) + (with-current-buffer buf + (when (equal (org-entry-get pos "ID") id) + ;; Make sure we're looking at entry's heading. + (org-with-wide-buffer + (goto-char pos) + (unless (org-at-heading-p) (org-back-to-heading-or-point-min)) + (unless (bolp) (goto-char (pos-bol))) + (setq pos (point))) + (setq where (if markerp + (move-marker (make-marker) pos buf) + (cons file pos)))))) + + (when (and (null where) file) (setq where (org-id-find-id-in-file id file markerp))) (unless where (org-id-update-id-locations nil t) (setq file (org-id-find-id-file id)) (when file (setq where (org-id-find-id-in-file id file markerp)))) + + ;; Update id location cache. + (setq pos (if markerp (marker-position where) (cdr where))) + (when (and where (or (not (consp loc)) (not (= (cdr loc) pos)))) + (puthash id (cons file pos) org-id-locations)) where)) ;;; Internal functions @@ -660,9 +683,12 @@ If SILENT is non-nil, messages are suppressed." (defun org-id-hash-to-alist (hash) "Turn an org-id HASH into an alist. This is to be able to write it to a file." + ;; org-id-locations: hash, ID -> file or ID -> (file-name . point) + ;; .org-id-locations: alist, file-name -> IDs (let (res x) (maphash (lambda (k v) + (unless (stringp v) (setq v (car v))) (if (setq x (assoc v res)) (setcdr x (cons k (cdr x))) (push (list v k) res))) @@ -700,9 +726,10 @@ This is to be able to write it to a file." ;; Finding entries with specified id -;;;###autoload -(defun org-id-find-id-file (id) - "Query the id database for the file in which ID is located." +(defun org-id--find-id-location (id) + "Query the id database for the location in which ID is located. + +Return a filename or cons cell (file-name . position)." (unless org-id-locations (org-id-locations-load)) (or (and org-id-locations (hash-table-p org-id-locations) @@ -712,6 +739,12 @@ This is to be able to write it to a file." (buffer-file-name (or (buffer-base-buffer (current-buffer)) (current-buffer)))))) +;;;###autoload +(defun org-id-find-id-file (id) + "Query the id database for the file in which ID is located." + (let ((loc (org-id--find-id-location id))) + (if (stringp loc) loc (car loc)))) + (defun org-id-find-id-in-file (id file &optional markerp) "Return the position of the entry ID in FILE. -- 2.44.0.windows.1