I would like to have a capture template that would take a pasted link like:


and return:


My goal is to have a shorter, cleaner description. Even better would be to have it strip the extension from the description as well.

I have seen %(EXP) in the manual but my elisp is novice (purely used for my config files). This my current capture template:

("c" "paste clipboard" entry
 (file "~/Dropbox/inbox.txt")
 "* PROC %c%?" :prepend t)))
  • You can use %(EXP) (Evaluate Elisp expression EXP and replace it with the result.) to get the style you want. see orgmode.org/manual/Template-expansion.html#Template-expansion Feb 14, 2022 at 1:17
  • Do you have a capture already that does not do the transformation? If so, add it to your question. The transformation itself should be easy.
    – NickD
    Feb 14, 2022 at 2:11
  • By the way, another way to have better descriptions is to have page titles together with the links. Personally I use two methods for this: first, a plugin in the browser for org-capture, which invokes it through org-protocol and passes the title and the address. Second, a plugin that copies both the title and the address to the clipboard, so I paste them anywhere I like. The latter kind of plugins often have customizable templates, so you can have Org-style links ready in the clipboard.
    – aaa
    Feb 15, 2022 at 7:17

1 Answer 1


You probably want to add something like this:

("l" "Insert a link with a cleaned-up description" entry (file "~/Dropbox/inbox.txt")
 "* [[%c][%(replace-regexp-in-string \"^https?://\" \"\" (replace-regexp-in-string \"\\.[a-z0-9]+$\" \"\" \"%c\"))]]"
 :prepend t)

This removes both the protocol and the extension. However, while that should work via just one regex, for some reason org-capture's processing hiccups when it sees a pipe in the regex, and doesn't perform the replacement. So instead I have to call replace-regexp-in-string twice.

Note that all those backslashes are necessary, including the double one.

Also, removing extensions can be messy: considering that the web doesn't impose any requirements for extensions to be there, people are free to use all kinds of addresses, including ones with a dot and some word at the end. E.g. Wikipedia's page of https://en.wikipedia.org/wiki/.com. These will be stripped from the description by the brute approach. Perhaps you'll want to remove just some known extensions—for that, replace [a-z0-9]+ in the second regex with something like \(html\|php\|cfm\) etc. Again, the backslashes need to be there. To switch off the removal of extensions altogether, replace the second (replace-regexp-in-string ...) with just \"%c\".

  • Capture templates are confusing enough as it is: they don't need the additional confusion that regexps introduce. IMO, it would be better to define a function that does the transformation (and encapsulates the regexps), and then just call the function in the template. Also, can you explain the difference between %c as the OP had it and %:link as you have it?
    – NickD
    Feb 15, 2022 at 1:29
  • 1
    @NickD you were right about the clink discrepancy: I fell back into the habits of dealing with org-protocol, forgetting that the OP has links coming from a different source. Thanks! As for a function, IMO that would be overkill just for the regexes—though dispensing with some backslashes would be nice. However, it might make sense if I add the ability to switch off the replacement of extensions or to customize it, as suggested by my edit. I'll think a bit later of how to better organize that.
    – aaa
    Feb 15, 2022 at 5:30
  • After adding %c that worked. Thanks so much!
    – fred
    Feb 17, 2022 at 0:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.