Emacs: Roaming Roam (publ. 2024-04-18)

I feel like a big hole in the Org Roam paradigm, or at least the implementation, is how do you deal conveniently with multiple projects. I.e., you want to be able to keep your nodes segregated in some way, by project or context, but all your nodes will go into the same directory and database, creating a lot of noise during completions, or forcing you to add prefixes or such like onto node titles.

One solution is to just change your active roam directory and database file by setting the corresponding variables, namely roam-dir and roam-db. Of course, that is a lot of typing so it begs for some convenient emacs function. For this, I fell back to using an alist plus completion. Here is some code in my init.el:

(setq roam-alist
  '((ftd "~/Documents/FTD/ftd-roam" "~/Documents/FTD/ftd-roam/roam.db")
    (work "~/Documents/work-roam" "~/Documents/work-roam/roam.db")))

(defun select-roam (&optional key)
  (interactive)
  (let* ((key (or key (intern (completing-read "roam: " roam-alist))))
         (roam-details (alist-get key roam-alist))
         (roam-dir (car roam-details))
         (roam-db (cadr roam-details)))
    (setq org-roam-directory roam-dir)
    (setq org-roam-db-location roam-db)))

;; default roam
(select-roam 'work)

(org-roam-db-autosync-mode)

A very simple approach. The select-roam interactive function allows you to quickly select a configuration from your alist. However, it raises the question of how do you conveniently keep track of which roam you are using at any given moment. My approach was to put this information in the mode line. This can be done by implementing a simple minor mode that adds this information to global-mode-string, a variable affecting the format of part of the mode line. I threw one together quickly, using the example tracking minor mode in the rcirc code.

(defun build-roam-track-string ()
  (concat (car (last (file-name-split org-roam-directory))) " "))

(define-minor-mode roam-track-minor-mode
  "Global minor mode for tracking what roam is selected."
  :global t
  (or global-mode-string (setq global-mode-string '("")))
  (if roam-track-minor-mode
      (progn
        (and (not (memq 'roam-directory global-mode-string))
             (setq global-mode-string
                   (append global-mode-string
                           '((:eval (build-roam-track-string)))))))
    (setq global-mode-string
          (delete '(:eval (build-roam-track-string)) global-mode-string))))

(roam-track-minor-mode 1)

This code adds a string to the mode line, based on the name of the top-level directory component of roam-dir. This is simple, but does require you to take some thought as to what name you want to give to your roam directories, so as to make the corresponding mode-line output both short and descriptive. E.g., you probably want to name the directory "homework-roam" rather than just "roam" or "roam-for-homework-notes".

I'm considering the above code to be trivial, and therefore not requiring a license for reuse. But it would be nice to have something like this developed a little more and either packaged or integrated into org-roam itself.

Copyright

This work © 2024 by Christopher Howard is licensed under Attribution-ShareAlike 4.0 International.

CC BY-SA 4.0 Deed