Using org-capture template expansion "%(EXP)" in org-roam

Hey there,

has anyone used the org-capture template expansion “%(EXP)” (Template expansion (The Org Manual)) and made it work during node creation in org-roam? Here’s a minimal example of what I am trying to achieve:

  (use-package org-roam
    :custom
    (org-roam-directory "~/org/roam/")
    (org-roam-capture-templates
     '(("d" "default" plain
        "%?"
        :if-new (file+head "${slug}.org" "#+title: ${title}\n#+date: %U\n#+filetags: %(org-roam-node-insert)")
        :unnarrowed t)))
    :bind (("C-c n l" . org-roam-buffer-toggle)
           ("C-c n f" . org-roam-node-find)
           ("C-c n i" . org-roam-node-insert))
    :config
    (org-roam-db-autosync-mode t))

How it should work: Creating a new node via “org-roam-node-insert” or “org-roam-node-find” will call “org-roam-node-insert” inside the capture buffer. A node can be selected and will be inserted after “#+filetags:”.

What actually happens: “org-roam-node-insert” is called and a node can be selected. However, the node is not inserted.

Is this a limitation of %(EXP) or org-roam?

I think this answers your question: Capture template from file but only for new entries - #9 by nobiot

Okay, my previous response was probably unhelpful given this result. I think this result means that you need to create a wrapper function to return a string you want to be inserted and that org-roam-node-insert does not return a string. I think it returns nil (and inserts the node as a side effect). Does this make sense to you?

This makes absolutely sense. I was assuming that org-roam-node-insert returns a string. I am not sure, if I am proficient enough to write a wrapper. Maybe at some point. Calling org-roam-node-insert manually is a viable option for the time being :slight_smile:

It should be something like this.

(with-temp-buffer
  (org-roam-node-insert)
  (buffer-string))

This worked marvelously! Thank you very much!

  (defun insert-node-as-str ()
    "Call org-roam-node-insert and return a string."
    (with-temp-buffer 
     (org-roam-node-insert)
     (buffer-string)))

Just add “%(insert-node-as-str)” to the capture template.

1 Like

Just adding my two cents, I had to add (interactive) for this to work

(defun insert-node-as-str ()
  "Call org-roam-node-insert and return a string."
  (interactive)
  (with-temp-buffer 
    (org-roam-node-insert)
    (buffer-string)))