9

I'm using org-capture to insert expenses into a Ledger file with this template, along with auto-completion for the various expense categories:

(setq ledger-expense-completions
    (list
     "" ;; needed for first | for mapconcat
     "Expenses:Food" "Expenses:Food:Restaurants" "Expenses:Food:Groceries"
     ))

(setq capture-expense-template
    "%%(org-read-date) * %%^{Description}
  %%^{Expense%s}  %%^{Amount}
  Account:Cash")

(defun return-capture-expense-template () 
    (let ((compstring
        (mapconcat 'identity ledger-expense-completions  "|" )))
            (format capture-expense-template compstring)))

(setq org-capture-templates
    (append '(("l" "Ledger entries")
              ("lc" "Cash" plain
              (file "~/Documents/journal.ledger")
              (function return-capture-expense-template)
              :empty-lines-before 1
              :empty-lines-after 1))
            org-capture-templates))

This works fine, however I'd like to modify return-capture-expense-template to make it a bit more dynamic so that I can pass in the account, e.g., "Account:Bank" or "Account:Cash", to support variations of this template without creating a separate capture-expense-template for each variation.

So here's how I modified things:

(setq ledger-expense-completions
    (list
     "" ;; needed for first | for mapconcat
     "Expenses:Food" "Expenses:Food:Restaurants" "Expenses:Food:Groceries"
     ))

(setq capture-expense-template
    "%%(org-read-date) * %%^{Description}
  %%^{Expense%s}  %%^{Amount}
  %s")


(defun return-capture-expense-template (account) 
    (let ((compstring
        (mapconcat 'identity ledger-expense-completions  "|" )))
            (format capture-expense-template compstring account)))

(setq org-capture-templates nil)
(setq org-capture-templates
    (append '(("l" "Ledger entries")
              ("lc" "Cash" plain
              (file "~/Documents/journal.ledger")
              (function return-capture-expense-template "Account:Bank")
              :empty-lines-before 1
              :empty-lines-after 1))
            org-capture-templates))

When I try evaluating (return-capture-expense-template "Account:Bank") on a separate line, that gives me the template output that I would expect (with "Account:Bank" dynamically inserted into the capture template), however when I run org-capture, I get Wrong number of arguments because the "Account:Bank" is not getting passed to return-capture-expense-template on this line: (function return-capture-expense-template "Account:Bank").

I reviewed the docs for Anonymous Functions and tried writing that line in various ways, but nothing I do seems to be working.

Is it not possible to pass a variable to a function when using the special form function?

2
  • 2
    The function needs to take zero arguments. Just move "Account:Bank" into the function.
    – abo-abo
    Jun 4, 2015 at 17:25
  • 1
    I think I am trying the same thing as you do at the moment, but even with sachas answer I couldn't make it work (I am just learning to read emacs-lisp). Could you share your working solution, please?
    – Kaligule
    Jun 22, 2017 at 15:43

2 Answers 2

16

You can specify your own properties in the property list for the template, and then you can access those properties with plist-get and org-capture-plist. Here's a brief example:

(defun my/expense-template ()
  (format "Hello world %s" (plist-get org-capture-plist :account)))
(setq org-capture-templates '(("x" "Test entry 1" plain
                               (file "~/tmp/test.txt")
                               (function my/expense-template)
                               :account "Account:Bank")
                              ("y" "Test entry 2" plain
                               (file "~/tmp/test.txt")
                               (function my/expense-template)
                               :account "Account:AnotherBank")))

I hope that helps!

2
  • 1
    Yes!! Thank you so much, Sacha! :-) That is exactly what I was looking for.
    – Raam Dev
    Jun 6, 2015 at 21:01
  • Hah, this problem was driving me nuts. Reading your emacs configuration file convinced me that good org-capture templates are an utter necessity, so it's appropriate that you happen to be the one who finally provides the answer!
    – Dodgie
    Feb 8, 2016 at 7:58
1

An alternative to Sacha's my/expense-template is:

(defun my/expense-template ()
  (format "Hello world %s" (org-capture-get :account)))

We spare some code by using the org-specialised org-capture-get.

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.