LedgerSplit vim function
I manage my finances using ledger. Periodically, I export my bank statements and push them through a make pipeline to get a ledger file. The conversion assigns transactions to accounts based on a set of rules, e.g: If the payee is “Foo Shop”, the account is going to be “Expenses:Food”:
2023-03-09 Foo Shop
Expenses:Food 1000 HUF
Assets:Card
However, sometimes I buy e.g: toothpaste in “Foo Shop”, that I don’t want to eat. I do not want to contaminate my ledger, so I save the receipt and mark the item. During the periodic export, I manually fix the ledger file in vim:
2023-03-09 Foo Shop
Expenses:Food 750 HUF
Expenses:Health 250 HUF
Assets:Card
Since I have an engineering degree, most of the time I get this subtraction right. For the same reason, I made a tiny vim script, that automates some of this. Standing on this line:
Expenses:Food 1000 HUF
Issuing this command:
:LedgerSplit 100+200
Modifies the posting like this:
Expenses:Food 700 HUF
Expenses:Food 300 HUF
It splits the given amount from the current posting, and moves it to the next line. It handles expressions (as shown) and decimal fractions. After this I just need to fix the second account name.
Installation
To .vimrc
, add:
au BufRead,BufNewFile *.ledger set filetype=ledger
To .vim/after/ftplugin/ledger.vim
:
function! LedgerSplit(amount) abort
let pat = "[0-9\\.]\\+"
let line = getline(".")
let old = str2float(matchstr(line, pat, 0))
let new = substitute(printf("%.2f", old-a:amount), "\\.00$", "", "")
let split = substitute(printf("%.2f", a:amount), "\\.00$", "", "")
call setline(".", substitute(line, pat, new, ""))
call append(".", substitute(line, pat, split, ""))
endfunction
command! -nargs=1 LedgerSplit call LedgerSplit(<args>)