Capture-template: How to insert link to org-roam-node at point

Hi,
I’m looking for a way to insert the org-ID link to the org-roam-node at point or the currently opened buffer respectively via an org-roam-capture-template? Any hints on how I could achieve that?

Thanks in advance!

Best regards,
jgru

Furthermore, I am interested if and how you denote the immediate parent-zettel.
Do you have any thoughts on this?

You can get the Org-ID at point, and file-level Org-ID of the current buffer as a string like this below. You could create your custom function to get the ID this way, set your own custom variable (global variable) with the ID, and call the capture process to use it in your template with % syntax.

Just an idea.

The code below does not consider error handling and the cases where you are not in an appropriate point or buffer (you’d need to handle cases where the program finds no Org ID, etc.)

;; at point
(org-element-property :path (org-element-context))

;; current buffer
(org-entry-get 1 "ID")

With your second question, I don’t quite understand what you mean by “parent-zettel” but if it’s just a hierarchical logical structure, why not use the standard Org headlines to represent the hierarchy? Headlines can be a node, so you can represent a hierarchy in a single file with multiple headlines:

#+title: Note about the Universe
# this is a completely fabricated example; no idea what the universe is.

* History of Universe
** Beginning
** Current
** Future expansion
* Physical Characteristics of the Universe
** Composition of the Universe
...

Thank you for helping me out, @nobiot.
Unfortunately, I can’t get it to work
I have the following

  (org-roam-capture-templates
   '(("d" "default" plain
      "%?"
      :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n%(org-entry-get 1 \"ID\")")
      :unnarrowed t)))

%(org-entry-get 1 \"ID\") does not insert anything. (However, this works in general with e.g. %(current-time-string)).

Do you have any idea where I went wrong here?

Regarding the “parent zettel”: I wondered whether inserting a link to the preceeding note like so

#+title: Note about the Universe
# this is a completely fabricated example; no idea what the universe is.
<- [[id:...][Genesis]]
* History of Universe
** Beginning
** Current
** Future expansion
* Physical Characteristics of the Universe
** Composition of the Universe
...

is reasonable. What do you think?

Yes. The ID does not exist in the capture buffer; probably that’s why – your point is not in the buffer that has the ID. Hope this makes sense.

You would need to get the ID first before calling org-roam-capture. And you would need to have a way to pass the ID to the capture process. This is what I was trying to say in this part. I can’t give a working code sample, but as an idea, you might have luck doing something like this:

(defun your-custom-capture-command ()
  (interactive)
  (setq your-variable-to-store-ID (function-to-get-ID))
  (org-roam-capture)
  (setq your-variable-to-store-ID nil))

;;  If you are using lexical binding, you could probably use let-biding like this... (untested)

(defun your-custom-capture-command ()
  (interactive)
  (let ((your-variable-to-store-ID (function-to-get-ID)))
    (org-roam-capture)
    (setq your-variable-to-store-ID nil)))

If you have something like this, you should be able to get the value of your-variable-to-store-ID in your template like %your-variable-to-store-ID.

Thank you for the clarification. I didn’t get it, when I first read it. I somehow assumed that the %() is evaluated within the buffer, where M-x org-roam-capture was called.

Makes total sense, thanks for clarifying this.

In case anybody wants to achieve the same, I came up with the following function:

(defun my/org-roam-custom-capture-with-link ()
  "Retrieve the ID of the current org-roam file and call org-roam-capture."
  (interactive)
  (if (org-roam-file-p)
      (let ((id (org-entry-get 1 "ID")))
        (setq my/org-roam-custom-curr-link
              (org-link-make-string
               (concat "id:" id)
               (org-roam-node-title (org-roam-node-from-id id)))) 
        (org-roam-capture)
        (setq my/org-roam-custom-curr-link nil))
    (error "Call this function from within an org-roam-buffer")))

and used this capture-template :

  (org-roam-capture-templates
   '(("d" "default" plain
      "%?"
      :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n%(progn my/org-roam-custom-curr-link)")
      :unnarrowed t)))

This works perfectly, however the variant with the let-binding did not work for me, although I have lexical binding set to t.

Thanks again for helping me out!

1 Like