I've cleaned it up and turned it into a patch. It now correctly handles (ignores) buffers without associated file names (which don't work with IDs).
>From 1861637d7b05f2e7ac11edf89f6939145c7be091 Mon Sep 17 00:00:00 2001 From: Steven Allen <ste...@stebalien.com> Date: Wed, 27 Aug 2025 09:05:08 -0700 Subject: [PATCH] org-id: implement org-insert-link completion for ID links * lisp/org-id.el (org-id-complete): add a function to prompt for a headline in both the the current buffer and all known files with IDs, returning a valid "id" link to said headline. (org-id-description): add a function to describe an ID link based on its target heading. (org-link-set-parameters "id" ...): use these functions for `org-insert-link' completion. --- lisp/org-id.el | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/lisp/org-id.el b/lisp/org-id.el index 6ff63b295..87d8a1190 100644 --- a/lisp/org-id.el +++ b/lisp/org-id.el @@ -888,9 +888,42 @@ defun org-id-open (org-element-lineage (org-element-at-point) 'headline t)))) (org-fold-show-context))) +(defun org-id-complete (&optional _arg) + "Complete IDs for `org-insert-link'. + +If a headline without an ID is selected, one will automatically be +created." + (unless org-id-locations (org-id-locations-load)) + (when-let* ((id (org-id-get-with-outline-path-completion + `((nil . ,(if (buffer-file-name) + '(:maxlevel . 10) + ;; IDs can only be used to link to + ;; buffers with file names. + '(:level . 0))) + (org-id-files . (:maxlevel . 10)))))) + (concat "id:" id))) + +(defun org-id-description (link desc) + "ID link description, derived from the LINKs target headline. + +TODO keywords, tags, and priorities are stripped from the description. + +Calling convention is similar to `org-link-make-description-function'. +DESC has higher priority and returned when it is not nil or empty string. +If LINK is not an info link then DESC is returned." + (or (org-string-nw-p desc) + (when-let* ((loc (org-id-find (string-remove-prefix "id:" link)))) + (org-with-file-buffer (car loc) + (org-with-wide-buffer + (goto-char (cdr loc)) + (org-link-display-format + (org-get-heading t t t t))))))) + (org-link-set-parameters "id" :follow #'org-id-open - :store #'org-id-store-link-maybe) + :store #'org-id-store-link-maybe + :complete #'org-id-complete + :insert-description #'org-id-description) (provide 'org-id) -- 2.51.0