Hi, I have discovered that org-capture templates can't expand Lisp variabels with %(), only functions. Is that a bug or a feature?
In Emacs -q do:
#+begin_src emacs-lisp
(require 'org-capture)
(defun test1 ()
(with-temp-buffer
(org-capture-fill-template "%(default-directory)")))
;; => "%![Error: (void-function default-directory)]
;; "
(defun test2 ()
(with-temp-buffer
(org-capture-fill-template "%(buffer-name)")))
#+end_src
The manual says:
#+begin_quote
‘%(EXP)’
Evaluate Elisp expression EXP and replace it with the result. The
EXP form must return a string. Only placeholders pre-existing
within the template, or introduced with ‘%[file]’, are expanded
this way. Since this happens after expanding non-interactive
"%-escapes", those can be used to fill the expression.
#+end_quote
Symbolic expression are atoms or lists of symbolic expressions, so according to
documentation I would expect EXP to be
both variables and functions, and the pair of outer parenthesis not to be the
part of the expression itself. However, according
to current source code and the results, outer parenthesis are treated not as
markers where the expression starts and ends,
but as the part of the expression, which in my personal opinion is a bug.
Following rewrite of org-capture-expand-embedded-lisp treats outer parenthesis
not as a part of the expression:
#+being_src emacs-lisp
(defun org-capture-expand-embedded-elisp (&optional mark)
"Evaluate embedded elisp %(sexp) and replace with the result.
When optional MARK argument is non-nil, mark Sexp with a text
property (`org-embedded-elisp') for later evaluation. Only
marked Sexp are evaluated when this argument is nil."
(save-excursion
(goto-char (point-min))
(while (re-search-forward "%(" nil t)
(cond
((get-text-property (match-beginning 0) 'org-embedded-elisp)
(let ((template-start (match-beginning 0)))
(let* ((sexp (read (current-buffer)))
(result (org-eval
(org-capture--expand-keyword-in-embedded-elisp
sexp))))
(delete-region template-start (1+ (point)))
(cond
((not result) nil)
((stringp result) (insert result))
(t (error
"Capture template sexp `%s' must evaluate to string or nil"
sexp))))))
((not mark) nil)
;; Only mark valid and non-escaped sexp.
((org-capture-escaped-%) nil)
(t
(let ((end (with-syntax-table emacs-lisp-mode-syntax-table
(ignore-errors (scan-sexps (1- (point)) 1)))))
(when end
(put-text-property (- (point) 2) end 'org-embedded-elisp t))))))))
#+end_src
With patched function, test1 will now produce correct result, while the test2
now requires extra pair of parenthesis for the function call:
#+begin_src emacs-lisp
(defun test2 ()
(with-temp-buffer
(org-capture-fill-template "%((buffer-name))")))
#+end_src
Is that a change you could accept? It would be useful so we don't have to write
function wrappers for every variable we would to use
in a template. I would like to use capture templates to as a lite code
generator for some readme files and such.
I have attached a patch just because it is easier to see the differences, but I
can produce a better patch, if you can accept it, or
someone else patch it in, its probably faster.
0001-Let-evaluate-both-variables-and-functions.patch
Description: 0001-Let-evaluate-both-variables-and-functions.patch
