Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assign IDs to every entry in Org-mode

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.

like image 940
Mirzhan Irkegulov Avatar asked Nov 12 '12 08:11

Mirzhan Irkegulov


2 Answers

I agree with Stuart—I don't think there's anything in org-id to do this automatically so it really comes down to when you want to add the ids.

If you use org-capture to add all of your items then org-capture-prepare-finalize-hook is a logical place to put the code:

(add-hook 'org-capture-prepare-finalize-hook 'org-id-get-create)

Alternately you could do as Stuart suggested and add a save hook for org-mode files. I think the most idiomatic way to process all of the headlines in the file would be to use the mapping API:

(defun my/org-add-ids-to-headlines-in-file ()
  "Add ID properties to all headlines in the current file which
do not already have one."
  (interactive)
  (org-map-entries 'org-id-get-create))

Finally we just need to add a before-save-hook which only runs in org-mode:

(add-hook 'org-mode-hook
          (lambda ()
            (add-hook 'before-save-hook 'my/org-add-ids-to-headlines-in-file nil 'local)))

That should do it!

like image 153
camdez Avatar answered Oct 08 '22 02:10

camdez


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.

like image 37
Stuart Hickinbottom Avatar answered Oct 08 '22 00:10

Stuart Hickinbottom