Taking ownership of org-id
Let's say most of your Org files sit in a folder /home/kept/notes/
but some others are outside, scattered here and there, plus you'd like to try not depending on Org-roam's M-x org-roam-update-org-id-locations
all the time.
The challenges with org-id:
- The classic way to tell it where to look for IDs is adding the directories to
org-agenda-files
.- Unfortunately with thousands of files, this slows down the agenda something extreme. Not an option.
- An alternative way is to populate
org-id-extra-files
ororg-agenda-text-search-extra-files
.- See snippet A below.
- Unfortunately with thousands of files, this slows down
M-x customize-group
for either org-id or org-agenda, to a grinding halt.
- Unfortunately with thousands of files, this slows down
- See snippet A below.
- To sidestep the small problem with #2, you could trust in org-id to keep itself updated, because it does that every time your Emacs creates or searches for an ID. You regenerate org-id-locations once (or well, once every time you wipe .emacs.d). See snippets B or C.
- org-id complains about duplicate IDs because it's also looking in e.g. the versioned backups generated by Logseq
- So, you need some sort of exclusion ruleset.
- For an elisp-only way, see snippets A or B.
- A natural way is to obey
.ignore
or.gitignore
, if you already keep such files. I've found no elisp gitignore parser, but see snippet C for a way to use ripgrep's builtin parser.
- Why org-roam didn't give you this problem? If I'm reading the source code right, it has actually been suppressing org-id errors!
- So, you need some sort of exclusion ruleset.
Snippet A
;; Populate `org-id-extra-files' (dolist (file (mapcan (lambda (dir) (directory-files-recursively dir "\\.org$")) '(;; Example values "/home/kept/notes/" "/home/kept/project1/" "/home/kept/project2/"))) (or (string-search "/logseq/bak/" file) (string-search "/logseq/version-files/" file) (string-search ".sync-conflict-" file) (push file org-id-extra-files))) ;; Then either run M-x org-id-update-id-locations or restart Emacs.
Snippet B
;; Populate org-id without setting `org-id-extra-files'. Only do it if ;; `org-id-locations' is gone. (when (or (and (not (file-exists-p org-id-locations-file)) (null org-id-locations)) (if (null org-id-locations) (org-id-locations-load) (if (listp org-id-locations) (null org-id-locations) (hash-table-empty-p org-id-locations)))) (org-id-update-id-locations (seq-remove (lambda (file) (or (string-search "/logseq/bak/" file) (string-search "/logseq/version-files/" file) (string-search ".sync-conflict-" file))) (mapcan (lambda (dir) (directory-files-recursively dir "\\.org$")) '(;; Example values "/home/kept/notes/" "/home/kept/project1/" "/home/kept/project2/")))) (org-id-locations-save))
Snippet C
;; Populate org-id without setting `org-id-extra-files'. Only do it if ;; `org-id-locations' is gone. (when (or (and (not (file-exists-p org-id-locations-file)) (null org-id-locations)) (if (null org-id-locations) (org-id-locations-load) (if (listp org-id-locations) (null org-id-locations) (hash-table-empty-p org-id-locations)))) (dolist (default-directory '(;; Example values "/home/kept/notes/" "/home/kept/project1/" "/home/kept/project2/")) ;; Borrow ripgrep's ability to obey .ignore/.gitignore (org-id-update-id-locations (split-string (shell-command-to-string "rg -ilt org :ID:") "\n" t)) (org-id-locations-save)))
Bonus snippet: full reset
;; FOR TESTING: wipe all records ;; You ONLY need to wipe if it won't shut up about duplicates! (progn (delete-file org-id-locations-file) (setq org-id-locations nil) (setq org-id--locations-checksum nil) (setq org-agenda-text-search-extra-files nil) (setq org-id-files nil) (setq org-id-extra-files nil))
Sudden amnesia
Every time your Emacs quits unexpectedly, it can forget many ID locations! To ensure it remembers, either use a hook like
(add-hook 'after-save-hook (defun my-save-id-soon () (run-with-idle-timer 10 nil #'org-id-locations-save)))
or enable persist-state and add the hook
(add-hook 'persist-state-saving-functions (lambda () (when (fboundp 'org-id-locations-save) (org-id-locations-save))))
Final fix
All these issues go away now that I let org-node populate ID locations for me, via its user option org-node-extra-id-dirs
.
Created (8 months ago)