Emacs: Recording ledger entries with org-capture-templates

Updated 2014-05-26: Thanks to Greg for the updated link to https://github.com/ledger/ledger/wiki !

I use John Wiegley’s ledger program to keep track of my personal finances. It’s quick, it’s light, and it lets me slice-and-dice my data however I want. I enjoy opening my ledger file and adding transactions to it. (Particularly if it involves income!) Yes, I’m that kind of weird.

I wanted to make it even easier to add entries. Instead of using C-x C-f to find the file, using ESC > to go to the end of the buffer, and typing in the transactions, I decided to add some of my common transactions to org-capture-templates. Here’s the relevant snippet:

(setq org-capture-templates
      (append '(("l" "Ledger entries")
                ("lm" "MBNA" plain
                 (file "~/personal/ledger")
                 "%(org-read-date) %^{Payee}
  Liabilities:MBNA  
  Expenses:%^{Account}  %^{Amount}
")
                ("lc" "Cash" plain
                (file "~/personal/ledger")
	        "%(org-read-date) * %^{Payee}
  Expenses:Cash 
  Expenses:%^{Account}  %^{Amount}
"))
       org-capture-templates))

I’ve bound org-capture to C-c r using (global-set-key (kbd "C-c r") 'org-capture), so now I can use C-c r l m to create an entry for my MBNA Mastercard. This keyboard shortcut might not seem short to you, but if you think about it as C-c remember ledger Mastercard, it makes perfect sense. =) (Besides, org-capture prompts me just in case I forget.)

Hooray for org-capture!

One Pingback/Trackback

  • lgh

    nil? :)

  • http://www.kurup.org Vinod Kurup

    Wow, I know elisp is concise, but that is really concise! ;-)

    So many of my transactions are near-identical repeats of previous ones, so I created a little elisp snippet to copy the current transaction (where the cursor is) to the bottom of my ledger file.

    WARNING: elisp newbie here… https://gist.github.com/231520

    I bound it to C-c C-v in ‘ledger-mode’, so now I just search for the transaction (C-r), then hit C-c C-v and make whatever edits are necessary.

  • http://sachachua.com Sacha Chua

    Hah, oops! =D Fixed. Must find out why Org isn’t exporting my example or src regions properly.

    Vinod – Good idea! ledger-add-entry (C-c C-a) runs the Ledger entry command, I think, and that takes advantage of Ledger magic to do something similar. (http://joyful.com/repos/ledger/doc/ledger/Commands.html#Commands) I haven’t gotten the hang of using that, though.

  • http://www.newartisans.com John Wiegley

    I’m not sure if I did this in 2.6 or just the upcoming 3.0 version, but if you type C-TAB after entering a payee name, it will auto-complete the whole entry for you based on the last transaction you had relating to that payee, and then put your cursor on the amount for a quick change. This is basically how I create new entries.

  • http://sachachua.com Sacha Chua

    Oooooooh. Really? I would never have found out about that feature if you hadn’t mentioned it. I really should read release notes and source code more often if you’re going to keep adding cool things like that. =)

  • Dave

    Hi Sacha –

    I’m an experienced Windows user who is trying to learn Org-Mode as a direct result of some of your postings about it. I’ve downloaded and have been learning Emacs, but am struggling to find a way to update to the latest Org without needing to install and learn Elisp (at least not yet!). There is a posting on the Emacs Wiki at http://orgmode.org/worg/org-hacks.php and also at http://thread.gmane.org/gmane.emacs.orgmode/15264 that describes updating Org from the older version packages with Emacs.

    I tried copying the elisp function code listed on the Worg site listed above, changing the my/org-lisp-directory path to the directory where I downloaded the lastest Org Elisp files, and then using M-x my/compile-org RET. But everytime I do this, I get a “No Match” message in the minibuffer. Since I’m so new to Elisp and Emacs, I don’t even know where to start to try to figure out what I’m doing wrong (which I’m pretty sure is just a simple newbie mistake). Any ideas? My Emacs is pretty “out of the box” without customizations except the .emacs file additions needed for org-mode…

  • http://sachachua.com Sacha Chua

    Dave: Don’t worry too much about Emacs Lisp (elisp). It’s part of the system, and you’ll have much more fun with Org and Emacs if you’re okay with copying and occasionally modifying other people’s Emacs Lisp snippets. =)

    The easy way to update to the latest Org is to download the standard distribution from the Org Mode website, unpack it somewhere, and add it to your load path. You don’t need to worry about bytecompiling anything unless you want the extra performance boost, actually – you can run things just fine without bytecompiling. I think I haven’t gotten around to compiling the Org files on my Windows system. <laugh>

    Enjoy!

  • http://steelman.jogger.pl steelman

    I’ve tried using Org 6.x remember thingy to enter data ledger because of Org’s awesome date entry widget. In Org i usually enter dates from the future so I’ve set org-read-date-prefer-future to `t’, recording receipts for ledger on the other hand is deeply immersed in the past.

    The next problem is the date format. Although Org’s default one is quite human and machine readable it is not exactly compatible with ledger’s.

    Yet another feature is completion, Emacs would not be what it is without it and I’ve got quite a few accounts. So with all this requirements my org-remember (the old, pre 7.x, system) template for expenses looks as follows:


    '("Expense" ?e
    (concat
    "%(format-time-string \"%Y-%m-%d\" (stl/org-read-date nil 'to-time)) "
    "%(stl/org-ledger-ask-cleared)%(stl/org-ledger-read-invoice)%^{Description}\n"
    " %^{Credit||Assets:Checking|Expense:Cash|Expense:Food:Dinner|Expense:Food:Groceries|Expense:Supplies}\t%^{Amount} PLN"
    " %^{Debit||Assets:Checking|Expense:Cash|Income:Salary|Income:Scholarship|Liabilities:Visa}%!")
    "~/ledger.dat" bottom)

    To be 100% complete the function referred above is just a wrapper as simple as:


    (defun stl/org-read-date (&optional with-time to-time from-string
    prompt default-time default-input
    prefer-future)

    What was wrong with org- remember (org-capture probably does share this drawback) is that it didn’t allow empty lines below or above the captured text so the ledger file became slightly unreadable.

    I’ve stopped using org-remember after I learnt how to use ledger-add-entry in the ledger’s own Emacs major mode which in my case is even faster because I’ve got quite a lot receipts from only few places by YMMV.

    Best regards.

    PS. Dear blog owner, could you provide us, humble readers with some nifty feature for code formatting (and highlighting?). Like for example: http://qbnz.com/highlighter/index.php

  • http://sachachua.com Sacha Chua

    steelman: Good point. %(let ((org-read-date-prefer-future nil)) (org-read-date)) defaults to past dates. yyyy-mm-dd dates seem to work fine with my Ledger, but maybe that’s the way I’ve got mine set up. But yes, I really should just learn how to use ledger-add-entry. Thanks for sharing your config! =)

    As for code formatting: using Org mode in Emacs will let you do things like

    #+BEGIN_SRC emacs-lisp

    #+END_SRC

    which you can then use with M-x org-export-region-as-html or org2blog.el, although I forgot to do it this time. =) Or do you mean highlighting in comments too, which would be cool considering how people like sharing their configs?

  • http://steelman.jogger.pl steelman

    Both, your code and comments too. Let’s try (C-x b buf RET [scribble] C-x h C-e R [some moves] ) e voilà:

    (defun format-number (n)
    (format “%d” 1))

    Look cute :-) but I had to add the :exports option.

    #+BEGIN_SRC emacs-lisp :exports code

    But using GeSHi for comments would enable those who don’t use org-mode (?).

  • Markus

    Stumbled across this post. Thanks for the tip. I found two work arounds for the issues steelman mentioned. You can get the ledger type date YYYY/MM/DD from the org mode date YYYY-MM-DD by wrapping org-read-date like this


    (defun my-read-date ()
    "Parse date for capturing ledger entries via org mode"
    (replace-regexp-in-string "-" "/" (org-read-date)))

    And newer versions of org-mode let you insert one empty line above and below the entry by adding a


    :empty-lines 1

    at the last element of the list that defines the template.

    • http://sachachua.com sachac

      Great, thanks for sharing! =)

  • Pingback: Ledger – *nix cli bookkeeping | Bills Blog()

  • Greg Tucker-Kellogg

    That wiki link is outdated. Should be https://github.com/ledger/ledger/wiki

    • http://sachachua.com sachac

      Awesome, thanks!