Last update: January 18, 2010
umm web site!What's umm? It's Uwe's Money Mangler — errr,
Manager! umm is a tiny, minimal, command-line
accounting program. I was motivated to write it by a couple of things:
I had been using Quicken from Intuit for some years, and that had an
annoying failure mode every so often: an upgrade of computer hardware
or OS would cause Quicken to not run anymore, and some years of my
data would thus be trapped in a binary blob and lost. I'd chuck the
whole thing in frustration and stop keeping track of this (really
rather important) stuff for a year or two, and then I'd start over
again. Not ideal!
So... eventually I got tired of this, and I decided to try
something different. I had looked at gnucash, but the last time I looked
at it I was frankly intimidated... huge, with lots of
dependencies — although it's open-source, it was not going to be
as simple as I wanted. Recently I came across
ledger
and its haskell remix hledger, and I looked at
those. But there were a couple of minor things I didn't like so much,
and there were a couple of features I wanted that they were missing,
and anyway I needed a hacking project, so I decided to just take the
idea and write my own: umm.
The design criteria for this little program were fairly simple:
umm →
plain-text file formatumm is concernedledger and
hledger; it seems eminently sensible to me)utf8-string, to better handle the aforementioned currency
symbols;A few specific things I wanted the program to do:
umm doesn't care.umm can figure
it outumm can keep track of them and only bug me and thee when
it's time to do soledger, I didn't want umm to automatically
infer the names of new accounts or categories as I enter them:If you prefer a more GUI-oriented program, you should probably look elsewhere... but if you think this might work for you, then read on.
umm.exe
or something similarummumm from SourceYou'll need a working haskell compiler for this. I've used ghc 6.8.3
on an old iMac G3 running OSX 10.3.9,
ghc 6.10.{1,3,4} on x86 running a
slightly out-of-date version of Ubuntu Linux, and ghc 6.10.3 on
Windows XP. I've also tried ghc 6.12.1, but I haven't fully upgraded all
the libraries, so that didn't work. But I don't anticipate any significant
problems once libraries and cabal are updated.
Grab the source, above, unpack it, chdir into the source directory,
then run
cabal configure && cabal build
or
ghc -O2 --make -o umm UMM*.hs
ummWhether you built as per above, or you downloaded one of the pre-built
versions,
just move the umm executable to wherever you want,
and you're good to go!
Here's a complete small ledger file. See also sample1.dat in the source tarball, slightly tweaked from this to test some currency symbols.
ccs US$ "The Almighty Buck"
income cash
income interest
expense cash
account acc1 2009-9-1 "test account 1"
account acc2 2009-9-1 "test account 2"
group all acc1 acc2
ccs FOO "The Foo Companies"
ccs BAR "The Bar Companies"
ccs CLAM "Groupe Mollusque"
xfer 2009-9-1 cash acc1 100
buy 2009-9-1 acc1 10 FOO 15
xfer 2009-9-2 interest acc1 0.25
buy 2009-9-2 acc1 20 FOO 27
xfer 2009-9-3 acc1 cash 5.25
xfer 2009-9-1 cash acc2 100
buy 2009-9-1 acc2 10 BAR 25
xfer 2009-9-2 interest acc2 0.25
buy 2009-9-2 acc2 20 FOO 27
xfer 2009-9-3 acc2 cash 5.25
xfer 2009-9-4 acc1 acc2 25
xfer 2009-9-5 cash acc1 200
buy 2009-9-5 acc1 30 FOO 40
buy 2009-9-5 acc1 30 BAR 40
price 2009-9-5 FOO 1.5
xfer 2009-9-6 cash acc1 20 CLAM
price 2009-10-21 FOO 2.1
price 2009-10-24 FOO 2.4
price 2009-10-25 FOO 2.5
price 2009-10-23 FOO 2.3
price 2009-10-22 FOO 2.2
price 2009-10-25 BAR 3.25
price 2009-10-27 3 BAR 10
split 2009-11-5 CLAM 2 1
price 2009-11-11 CLAM 0.001
You run the program like so:
umm ledger-file command options
where command options is one of the following
balance [account-or-group] [date]register account [date] [date]reconcile [account] [date]change account-or-pseudo-account [date]
[date]price ccs [date]todo [date]list [all | accounts |
ccs | expenses | income |
groups]basis ccs [date]exportledger format —
only partially implementedledger
The commands may be shortened to the unique prefixes or anything
longer: 'bal', 'bala' etc, 'reg', 'regi' etc, but not 'r'.
If no command or options are specified, the default action is to show the
balances of all accounts as of the current date.
account is the name of an account, account-or-group
is the name of an account or an account group,
and
account-or-pseudo-account is the name of an account or an
income or expense pseudo-account.
ccs is the name of a currency, commodity, or security.
date defaults to the current date if not specified.
still under construction — see the actual program, which does have a description of each record type in its help listing.
umm is line-oriented, with each line of the ledger file
forming a separate record. There are 13 types of records in a ledger,
(mostly) indicated with keywords:
ccs
name [description] [amount] [name]income
name [description]expense
name [description]account
name [date] [description] [amount [name]]group
name [name...]price
date
[amount] name
amount [name]xfer
[rec-mark]
date name name
amount [name]
[description] [id]xfer
[rec-mark]
date name
{
name1 amount1 [name1],
name2 amount2 [name2],
...
} [description] [id]buy
[rec-mark]
date name
amount name
amount [name]
[description]sell
[rec-mark]
date name
amount name
amount [name]
[description]exch
[rec-mark]
date name
amount name
amount [name]
[description]split
date name
amount amounttodo
[rec-mark]
date description# comment
; commentBlank lines are also treated as comments, and leading and trailing
whitespace in any line is ignored. Also, all combinations (or mixtures)
of <CR> and <LF> characters are
accepted as line-end markers, so there should be no portability issues
between *nix and windows systems — the intent is that it should
Just Work... if it doesn't, shout at me!
Internally, not all of these are distinct: buy and
sell are just syntactic sugar for exch... but
you probably don't need to worry about that unless you want to hack on
umm. Also, internally there is another type of record, for
indicating parsing errors. These get printed out as
#err ccs 123bux
New in version 0.1.5 is the second form of the xfer
record: this allows specifications of multiple transfers from one
source account to multiple target accounts as one transaction. This is
to do things like specifying that a part of my salary goes to my savings
account, a part goes to my 401(k), etc. I don't have as compelling a use
case for the corresponding merge, ie multiple source accounts
to one target account, so I haven't implemented that.
Since split-transfer transactions can get somewhat long, I've also added the ability to split a record across multiple lines in version 0.1.5. This looks like so:
xfer 2038-1-19 salary {savings 100 GalCred,\
\ retirement 20 GalCred, taxes 80 GalCred}
The effect is to merge the two lines and annihilate the two backslashes and all the whitespace between them. Because there are two backslashes, you have exact control over other whitespace outside the backslashes; thus, this allows you to break a line in the middle of a string or indeed in the middle of an account or ccs name. This is not necessarily a good idea... don't abuse it.
Also, because of the order in which various operations get done inside the program, in order to comment out the above, you would add just one '#' at the beginning of the first line only:
# xfer 2038-1-19 salary {savings 100 GalCred,\
\ retirement 20 GalCred, taxes 80 GalCred}
There are five modules:
Main |
UMM.hs |
this is the main routine, plus most of the IO stuff |
UMMData |
UMMData.hs |
definitions of the various data types, plus routines to show them, plus a couple of utility routines |
UMMParser |
UMMParser.hs |
parsers for records, commands, dates — all built on Parsec, very easy to understand (if I do say so myself) |
UMMEval |
UMMEval.hs |
the main routines for processing records |
UMMHelp |
UMMHelp.hs |
one long string which is the help message |
Overall, it's about 1870 lines of code. The parser is pretty much all standard Parsec, and the help file is basically just a large string constant; so, leaving those out, there's not a huge amount of code to dig into.
Version 0.1.0 unleashed upon an unsuspecting world on 2009-11-18... muahahaha! Look out, Intuit, here I come! :-)
Version 0.1.1 released on 2009-11-22: added support for UTF-8 encoded Unicode currency symbols, plus made the date optional in an account record.
Version 0.1.2 released on 2009-11-27: turned check number into a more-general ID (first user-contributed patch — thanks, Nicolas!), plus added an optional "initial price" to ccs records. There's also a contributed vim syntax-highlighting mode from Nicolas!
Version 0.1.3 released on 2009-11-29:
no changes in functionality, just made it -Wall-clean.
Version 0.1.4 released on 2009-12-05:
wrote basis command, partially-working export
command to write out data in ledger format, cleaned up
a bunch of hlint suggestions.
Version 0.1.5 released on 2009-12-19: added code to allow records to continue across multiple lines if desired, and allow split-transfer records: in one transaction, transfer multiple chunks of loot from one source account to multiple destinations.
Version 0.1.6 released on 2010-01-18: added the ability to specify an optional initial amount in an account, plus work on price translation: specify ccs as either basic or derived, and allow specification of the base ccs into which any given derived ccs is to be translated.
If you have questions or comments about the stuff here, please contact me at korg@korgwal.com.
Enjoy! -- Uwe Hollerbach
Page last modified at 2010/1/18 20:00 US/Pacific