Summary
As an excuse to make myself learn some elisp, org, and dig into org-roam’s source, I set out to create an org-link that would emulate Roam’s a bit more (inspired by https://github.com/jethrokuan/org-roam/issues/510).
Some goals:
- Mimic Roam brackets [ [
- Otherwise hide link prefix/syntax
- Easy to write / change
- Lazy creation of notes
- Auto-complete from notes in buffer without creating them first
- Integrate with org-roam’s existing functionality
- Allow links in normal org files
I’m very happy just using the result myself but I was wondering if anyone else would be interested in adding some of this functionality in org-roam.
Functionality
Quickly write
Insert links as you write using typical org syntax: [[roam:_]]
. But the link face hides the roam:
prefix, and colors the brackets and link path to stand out. I bound M-[
to simply insert the roam pattern and place the point where the _ is, ready to write, but of course the shortcut is arbitrary. I have M-r
bound to the same construct, but with an ivy completion prompt for more difficult titles. The link is color-coded to indicate whether the note already exists or not.
Follow links like normal
The notes use TITLE/ALIAS as their point of reference for matching files. Clicking through the roam-links opens their corresponding file, or pulls up org-capture to create a new note if it doesn’t exist, just like org-roam-find-file
. After using org-capture, the link face updates to show that it exists in the org-roam db.
Easy change and completion
Because the links use TITLEs, they are incredibly easy to change. They also offer full completion support for both existing org-roam notes and as-yet uncreated notes in the current buffer. This is only functional in the roam-link construct, so company and org-roam still insert file-links everywhere else.
Integrate with backlink buffer
Obviously they must be recognized as backlinks! That is the whole point after all. The roam-links are inserted into the db as if they were regular file links, and so they mix together in the backlinks buffer without problem. The roam-links that don’t yet have files are ignored.
Links are interchangeable
For the case where writing with roam-links might feel easier, but file-links are a preferable long-term storage solution, the types are easily converted between each other. This function could easily run on an entire buffer before saving (or convert from file to roam on load – it’s your world).
Non-existent links can be automatically created
At any time all of the links without corresponding notes in a buffer can be created with a custom ‘automatic’ org-template. It is also possible to loop through and select different templates for different notes, but this is very buggy right now Using a single automatic template for all of them works without issue.
Extras
Minibuffer shows filename (or not) and raw-link
Uses shortened name relative to org-roam-directory. This should work for sub-dirs also? I don’t have any to test on right now.
Use descriptions
The current org-roam file-links use the description to show a note’s TITLE, but since roam-link uses the title as the path, a link’s description is free to shorten a title or provide local context. It is easy to see the underlying note title, whereas with an altered file-link you might take a whole FIVE seconds to navigate to a new buffer, see the title, and navigate back. Ugh! /s
The description form also uses one less bracket pair and a different face to indicate that it is not a TITLE.
Case insensitive!!!
AFAIK Roam doesn’t even allow this yet. To roam-link [[roam:unicorn]]
is the same as [[roam:UNICORN]]
is the same as [[roam:uNiCoRn]]
. I personally never use capitalization to indicate meaning, so case sensitivity drives me nuts. It would be possible to switch it on/off, if someone is the opposite of me and thrives on capital letters…
Link in non-org-roam org files
I didn’t limit link insertion strictly to org-roam buffers because there’s no explicit reason to block their use in other org files – they just don’t create backlinks and aren’t part of the org-roam environment. I don’t anticipate using this functionality much, but it’s nice to have the option for easy linking wherever I may want it.
Future additions
- Function to search/replace a link by an ALIAS
- Mimic org-roam’s file re-name advice for TITLE or ALIAS changes
- Scan org-roam files for links to current buffer TITLE and update db (in case of roam-links that were saved without ever creating the note).
- Turn word/selection into roam-link
- Nested automatic creation in org-capture
Let me know what you think! I have to have a project to really learn any new programming, so this is a jumble of code in my config file I plan to refine for myself, but if there’s interest in any of it I’d be happy to contribute something.