Assign IDs to every entry in Org-mode

elisp, emacs, org-mode

Solution

I searched through the source and couldn't find anything obvious to do this already. I know it's used by Org-mobile, but I've not much experience of that.

By way of a starter, the following snippet will loop through all outline headings in the current file (Org-mode headings are basically standard Emacs outline headings), and add an ID if there's not already one there:

   (require 'org-id)
   (save-excursion
      (goto-char (point-max))
      (while (outline-previous-heading)
        (org-id-get-create)))

(If you're wondering why this loop goes backwards over the buffer rather than forwards, it's because the `while` loop will always call the outline navigation function at least once and if your Org-mode file starts with a heading this would be skipped if going forwards.)

This could be reasonably easily used within a loop over all the files known to the Org-mode agenda by looping over the entries returned by the function `(org-agenda-files)`, or added to a save hook for Org-mode files.

If someone more nimble-fingered than I doesn't get there first, if you can identify when you'd like the IDs added I could probably expand the above to be a complete solution.

Problem

Org-mode has a bundled extension called `org-id`, that implements global unique IDs for org-mode files. Every entry (a headline with its body) can have an ID property in its `:PROPERTIES:` drawer. New ID for a single entry can be assigned with a function `org-id-get-create`. How can I assign an ID to every entry in an org-mode file? I could use an Emacs method of automating this, like a macro that calls `org-id-get-create` for every string starting with `*`. But I'd like to know if org-mode already has that capability. If not, please recommend the most idiomatic way to write an elisp code for this purpose.

Original source