0

I use the following code for the org mode capture functionality, but it returns the error "Invalid file location: nil". What is wrong? Thanks in advance for any help!

(setq org-capture-templates '(              
     (
    "t"                                                                                                  
    "todo"                                                                     
    entry                                                                                                
    (file (format "C:/Users/%s/Dropbox/.orgzly/capture2022.org" user-login-name))                   
    "* TODO %^{Todo}  \nSCHEDULED: %t\n:PROPERTIES:\n  :Created: %U\n  :NOBLOCKING: t\n  :ORDERED: t\n:END:\n:LOGBOOK:\n\n:END:\n\nFrom: %a\n\nNote: %?\n"  
    :prepend t                                                                                          
    :empty-lines 1
    )
))
NickD
  • 27,023
  • 3
  • 23
  • 42
myotis
  • 1,099
  • 1
  • 13
  • 27
  • Search for `backquote`. You are quoting the list *including* the call to `format`. You want to backquote it and precede the `format` call with a comma in order to allow evaluation: ` `((... (file ,(format "/path/%s" user-login-name))...))`. – NickD Jun 20 '22 at 17:49
  • 1
    Does this answer your question? [How to evaluate the variables before adding them to a list?](https://emacs.stackexchange.com/questions/7481/how-to-evaluate-the-variables-before-adding-them-to-a-list) – NickD Jun 20 '22 at 17:56
  • Hi NickD. I do not understand your answer above. I am only a part time emacs user with limited understanding of the coding. The code I use did work 2 years or so ago, so I have no clue why it doesnt work any more. – myotis Jun 22 '22 at 07:32
  • I added a (community wiki) answer. Hope it helps but keep asking if it's still not clear. The reason that it worked before and does not work now is a change that was made to Org mode back in version 9.1: see [etc/ORG-NEWS](https://git.savannah.gnu.org/cgit/emacs/org-mode.git/tree/etc/ORG-NEWS#n2378) or thereabouts (search for `org-capture-templates` if the link sends you to the wrong line). – NickD Jun 22 '22 at 13:58
  • Thanks a lot for your patient answer below, I will study it thorourgly. – myotis Jun 22 '22 at 16:25
  • And your solution worked :) thanks again! – myotis Jun 22 '22 at 17:23

1 Answers1

1

[Making this a community answer: feel free to add more examples]

This is a FAQ as you will see if you search for backquote. The trouble with the general problem however is that it is a chameleon and tends to blend if you are not familiar with it, but it eventually starts jumping out at you.

The basic problem is that when you quote a list, nothing inside is evaluated. So if you do

(setq mylist '("foo" (format "%s" "bar")))

the result is a list of two elements: the first element is a string but the second element is a list. The value is ("foo" (format "%s" "bar")). You might have expected it to be a list of two strings: ("foo" "bar") but it is not. The quoting inhibits the evaluation of everything inside. That does not matter if the quoted list consists of constants which are self-evaluating, but it matters when what you think is a function call (e.g. (format "%s" "bar")) is not evaluated because of the quoting. I hope you can see what is happening in your case.

The solution is to make sure that the format call is evaluated. You do that by using backquote which allows you to selectively evaluate parts of a list while keeping most of it quoted. In the above example, you write:

(setq mylist `("foo" ,(format "%s" "bar")))

Note the backquote (instead of a quote ') in front. That says "quote everything except whatever follows a comma" [1]. Each expression following a comma is evaluated and its value replaces the expression in the result. So the value of the above is ("foo" "bar").

Note that you can have more than one expression evaluated by adding a comma before each one:

(setq mylist `("foo" ,(format "%s" "bar") (format "%s" "baz" ,(format "%s" "hunoz")))

The value of mylist will be ("foo" "bar" (format "%s "baz" "hunoz") since the first and third format calls are evaluated because they are preceded by commas, but the second format call is not evaluated because it is not preceded by a comma. That's what I meant by "selective evaluation" above.

You should try evaluating these expressions in your *scratch* buffer to see the difference. You should also do the same with your setting of org-capture-templates to see what is happening.

I hope you can see what you need to do in your case to do the evaluation. You just change the ' quote to a backquote and add a comma before the (format ...) call (as I mentioned in my comment). Understanding what that does however will allow you to fix such problems in the future: it is well worth the effort.

[1] There is actually another wrinkle with backquote that I'm not covering here. See the link for the additional details.


Here's a partial list of questions whose answer is essentially the same as the answer above. The first one is often used as the paradigmatic example when asking to close such questions as duplicates. Note the variety of the questions: that's why I called it a "chameleon" before.

NickD
  • 27,023
  • 3
  • 23
  • 42