Help with template and file+olp

I’m trying to write a template such that I can capture a movie title and put it in my existing org-roam file movies.org, under the heading “Watched.” Here’s that template:

  (setq org-roam-capture-templates
        '(... 
          ("m" "movie" plain "%?" :target
           (file+olp "movies.org" ("Watched")
                     "*** \n :PROPERTIES:\n :RATING:\n:END:\n%t\n")
           )))

But whenever I run org-roam-capture, and select “m,” it says “wrong type argument, integer-or-marker-p, nil.”

What am I doing wrong here? I’ve tried it every way I can think to try it, so far.

You are using an invalid list. From the docstring for org-roam-capture-templates:

   (file+olp "path/to/file" ("h1" "h2"))
       The file will be created, prescribed an ID. If the file doesn't contain
       the outline path (h1, h2), it will be automatically created. The point
       will be adjusted to the last element in the OLP.

It should be

...  
(file+olp "movies.org" ("Watched"))
...

Now it runs without error, with this:

  (setq org-roam-capture-templates
        '(("d" "default" plain "%?" :target
           (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n")
           :unnarrowed t)
          ("m" "movie" plain "*** ${title}\n :PROPERTIES:\n :RATING:\n:END:\n%t\n"
           :target (file+olp "movies.org" ("Watched")
           ))))

But I have an even bigger problem now: it wants to rewrite my whole existing movies.org file, instead of just adding something to it. It creates a new buffer with the same name but different contents.

Copy and pasted your setq (left buffer below); seems to work on my end (right buffer):

Could it be you are talking about the transient *Org-capture-...* buffer? You’d need to press C-c C-c to finalize the capture process.

Ah so I figured out what was wrong with the duplicate files—it turns out I had two org files, one called movies.org and one called movies.org with a space at the end. And that was throwing everything off.

So now it works as in @nobiot’s screenshot above.

But it’d be really nice to have the headings get IDs, so they’re indexed by org-roam as nodes. Is that possible?

You should be able to call a function with using % as a prefix like this: %(org-id-get-create). I think you can put it in in your template (somewhere after your “***”) — can’t test it now but you can read it in the docstring of org-roam-capture-templates (C-h v).

That doesn’t seem to work. I just get the literal %(org-id-get-create) appear in my capture buffer. With this:

  (setq org-roam-capture-templates
        '(("d" "default" plain "%?" :target
           (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n")
           :unnarrowed t)
          ("m" "movie" plain "*** ${title}\n :PROPERTIES:\n :ID: %(org-id-get-create)\n :RATING:\n :END:\n%t\n"
           :target (file+olp "movies.org" ("Watched")
           ))))

I get this:

*** Test
 :PROPERTIES:
 :ID: %(org-id-get-create)
 :RATING:
 :END:
<2021-12-16 ĵaŭ>

It seems like org-id-get-create expects the buffer to be visiting a file

(error ‘org-id-get’ expects a file-visiting buffer)

This below seems to work for me (lightly tested). I guess you’d need to adjust the function according to the ID you use (e.g. I use a certain date format instead of uuid).

  (setq org-roam-capture-templates
        '(("d" "default" plain "%?" :target
           (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n")
           :unnarrowed t)
          ("m" "movie" plain "*** ${title}\n :PROPERTIES:\n :ID: %(org-id-uuid)\n :RATING:\n :END:\n%t\n"
           :target (file+olp "movies.org" ("Watched")
           ))))

1 Like

Great! That works. Thanks!

1 Like