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.

This site is temporarily in read-only mode and not accepting new answers.

Not the answer you're looking for? Browse other questions tagged .