This question already has an answer here:

I have a variety of org easy templates. I have a new file template which includes a #+DATE header that I'd like to populate with the current date [at the time the template is called].

The concatenated string I'd like to insert could be printed in the minibuffer using:

(concat "#+DATE: " (format-time-string "%m/%d/%Y"))

I try to implement this in my easy template, however, when I include the following in my config file, emacs will not compile the code:

  (eval-after-load 'org
    '(progn
       (add-to-list 'org-structure-template-alist '("n" (concat "#+DATE: " (format-time-string "%m/%d/%Y"))))))

I'm trying to get an error message (running emacs with --debut-init), but I'm not seeing anything. I ran across this SX thread where the OP describes a problem using concat in org-capture-templates. The only reply is to add a backquote (,) before the concat, so I try this:

  (eval-after-load 'org
    '(progn
       (add-to-list 'org-structure-template-alist '("n" ,(concat "#+DATE: " (format-time-string "%m/%d/%Y"))))))

This is still being ignored, and I'm not seeing feedback from the debugger. Any ideas?

1) How should I fix this?

2) What's the best way to go about tracing this type of problem myself in the future?

marked as duplicate by Drew, Stefan, JeanPierre, Community Aug 11 at 8:37

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 1
    @Drew there are a couple of wrinkles that may qualify this as a new question. Maybe. – Tyler Aug 9 at 21:50
  • @Tyler: Looks like the same issue to me; nothing more. – Drew Aug 10 at 14:27
up vote 2 down vote accepted

As @Drew mentioned in the comments, you can accomplish this, almost, with quasi-quoting. The syntax is a little confusing. The variable org-structure-template-alist is initialized as an alist:

'(("s" "#+BEGIN_SRC ?\n\n#+END_SRC")
  ("e" "#+BEGIN_EXAMPLE\n?\n#+END_EXAMPLE")
  ("q" "#+BEGIN_QUOTE\n?\n#+END_QUOTE")
  ...
     )

You want to insert an element that includes the concat form, and you need to evaluate that form and leave the rest of the alist 'as-is'. You can do this by switching from a straight quote to a back-quote, then using the , to indicate that the concat needs to be evaluated:

`(("n" ,(concat "#+DATE: "
          (format-time-string "%m/%d/%Y")))
  ("s" "#+BEGIN_SRC ?\n\n#+END_SRC")
  ("e" "#+BEGIN_EXAMPLE\n?\n#+END_EXAMPLE")
  ("q" "#+BEGIN_QUOTE\n?\n#+END_QUOTE")
  ...
     )

Note that you can't back-quote just the template you add (i.e., the ("n" ...) part). If you leave the original quote symbol, you can't selectively backquote the parts nested inside it. You need to backquote the entire list, as I've done - change the initial ' to a `. Once you do that, you can use the comma to get the concat form evaluated.

You can't accomplish this with add-to-list, since you need to change the entire list, not just add something to it. It will be easier to modify the variable via M-x customize-variable org-structure-template-alist. You may need to change the state to "Show saved Lisp expresssion", as you'll need to see the actual list to change the leading quote to a backquote.

BEWARE! There is a catch. This form gets evaluated once, when your initialization runs. That is, when you start Emacs. That will be fine if you start Emacs at 9 AM and close it at 5 PM. But should you have a session that runs longer than one day (i.e., lasts past midnight), your easy template will continue to insert the day at the time you started Emacs, not the current day. If that will be an issue for you, you'll need to find a more robust solution. Or maybe just redefine the variable at the beginning of each day with a timer of some sort.

  • Thanks for the explanation! Also interested in the catch you mention, but I /will/ open that as another question. – Clark Henry Aug 10 at 14:19

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