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

Reply via email to