Skip to content

Instantly share code, notes, and snippets.

@herbertjones
Last active February 20, 2020 15:44
Show Gist options
  • Save herbertjones/9718942aac44cd9f0ee5d353ad015fe3 to your computer and use it in GitHub Desktop.
Save herbertjones/9718942aac44cd9f0ee5d353ad015fe3 to your computer and use it in GitHub Desktop.
Org-Roam multiple directories workaround hack
(defvar org-roam-directories nil
"Paths to org-roam files. List where CAR is name and CDR is path.")
;; Example:
;; (setq org-roam-directories '(("Home roam" . "~/Documents/home-roam")
;; ("Work roam" . "~/Documents/work-roam")))
;; Set first directory
(setq org-roam-directory (cdar org-roam-directories))
;; This buffer hook updates org-roam-directory on switching buffers.
(add-hook 'buffer-list-update-hook #'org-roam--buffer-change-hook)
(defvar org-roam--multi-dir-cache nil
"Alist keyed by name of wiki from org-roam-directories containing built cache data.")
(defun org-roam--multi-name-from-path (path)
(car (--first (f-same? path (cdr it)) org-roam-directories)))
(defun org-roam--multi-path-from-name (name)
(cdr (assoc name org-roam-directories)))
(defun org-roam--switch-cache (roam-dir-name)
"Switch cache by name from org-roam-directories."
;; Save current cache if good.
(when org-roam-cache-initialized
;; Extra checking due to async build cache
(when-let* (((< 0 (hash-table-count org-roam-titles-cache)))
(name (org-roam--multi-name-from-path org-roam-directory))
(a-file-path (block nil
(maphash (lambda (k v) (return k))
org-roam-titles-cache)))
((f-parent-of? org-roam-directory a-file-path)))
(setf (alist-get name org-roam--multi-dir-cache)
(list org-roam-forward-links-cache
org-roam-backward-links-cache
org-roam-titles-cache
org-roam-directory))))
;; Retrieve existing cache, else clear and build cache.
(if-let* ((cached (alist-get roam-dir-name org-roam--multi-dir-cache)))
(progn
(setq org-roam-cache-initialized t
org-roam-forward-links-cache (elt cached 0)
org-roam-backward-links-cache (elt cached 1)
org-roam-titles-cache (elt cached 2)
org-roam-directory (elt cached 3)))
(org-roam--clear-cache)
(setq org-roam-directory (org-roam--multi-path-from-name roam-dir-name))
(org-roam--build-cache-async)
nil))
(defun org-roam--multi-dir-helm-select (description)
"Helm selector to pick wiki directory."
(let ((max-len (--reduce-from (max acc (length (car it)))
0 org-roam-directories)))
(helm :sources (helm-build-sync-source description
:candidates (--map
(cons (format (format "%%-%ds %%s" max-len)
(car it) (cdr it))
it)
org-roam-directories)))))
(defun org-roam-multi-switch-and-find-file ()
"Switch to another roam directory defined in
org-roam-directories and find file within."
(interactive)
(when-let ((pair (org-roam--multi-dir-helm-select "Pick dir to roam:")))
(org-roam--switch-cache (car pair))
(org-roam--after-cache-initialized #'org-roam-find-file (car pair))))
(defun org-roam--buffer-change-hook ()
"To be triggered when buffers are entered. Switches the
org-roam cache if the buffer belongs to a different org-roam directory."
(when-let* ((not-minibuffer (not (active-minibuffer-window)))
((get-buffer-window nil (selected-frame)))
(path (buffer-file-name))
(wiki-pair (--first (f-parent-of? (cdr it) path)
org-roam-directories))
(is-different-wiki (not (equal (cdr wiki-pair)
org-roam-directory))))
(org-roam--switch-cache (car wiki-pair))
(when (get-buffer org-roam-buffer)
(org-roam--after-cache-initialized (lambda () (org-roam-update path))
(car wiki-pair)))))
(defun org-roam--after-cache-initialized (f multi-name)
"Execute a function when cache becomes initialized with expected multi-name."
(if (and org-roam-cache-initialized
(f-same? (org-roam--multi-path-from-name multi-name)
org-roam-directory))
(funcall f)
(run-at-time 0.2 nil
(lambda () (org-roam--after-cache-initialized f multi-name)))))
@herbertjones
Copy link
Author

Hacky because it will break if org-roam--build-cache-async already running.

@herbertjones
Copy link
Author

Added fix to avoid problems due to async builds and background buffers being loaded due to agenda hooks firing.

@herbertjones
Copy link
Author

Extended on-init-cache hack since it wasn't working with new minor mode.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment