A long asked-for feature, pre-declarations, has now arrived! This feature comes with some breaking changes, even damaging backwards compatibility with 2.x. I believe it is worth it for the gain in consistency.
------------------------------------------------------------------------------ # BREAKING CHANGES ## 'account' directive In 2.x, you could enclose a group of transactions within a parent account: account My Master ... end account This is now done with "apply account" instead of "account": apply account My Master ... end apply You can also use "end apply account", and Ledger will verify that it matches an enclosing "apply account". ## 'tag' directive In 3.x, you could apply a tag to a group of transactions: tag Foo: Bar ... end tag This is now done with "apply tag" instead of "tag": apply tag Foo: Bar ... end apply tag ------------------------------------------------------------------------------ # NEW DIRECTIVES There are four all new directives: account payee commodity tag ## New 'account' directive You can now pre-declare account names. This only has effect if --strict or --pedantic is used (see below). account Expenses:Food account Expenses:Gas ### Account sub-directives The 'account' directive supports several optional sub-directives, if they immediately follow the account directive and if they begin with whitespace: account Expenses:Food note This account is all about the chicken! alias food payee ^(KFC|Popeyes)$ check commodity == "$" assert commodity == "$" eval print("Hello!") default The 'note' sub-directive associates a textual note with the account. This can be accessed later using the 'note' valexpr function in any account context. The 'alias' sub-directive, which can occur multiple times, allows the alias to be used in place of the full account name anywhere that account names are allowed. The 'payee' sub-directive, which can occur multiple times, provides regexps that identify the account if that payee is encountered and an account within its transaction ends in the name "Unknown". Example: 2012-02-27 KFC Expenses:Unknown $10.00 ; Read now as "Expenses:Food" Assets:Cash The 'check' and 'assert' directives warn or error (respectively) if the given value expression evaluates to false within the context of any posting. The 'eval' directive evaluates the value expression in the context of the account at the time of definition. At the moment this has little value. The 'default' directive specifies that this account should be used as the "balancing account" for any future transactions that contain only a single posting. ## New 'payee' directive You can now pre-declare payee names. This only has effect if --check-payees is used in addition to --strict or --pedantic (see below). payee KFC payee Payless ### Payee sub-directives The 'payee' directive supports one optional sub-directive, if it immediately follows the payee directive and if it begins with whitespace: payee KFC alias KENTUCKY FRIED CHICKEN The 'alias' directive provides a regexp which, if it matches a parsed payee, the declared payee name is substituted: 2012-02-27 KENTUCKY FRIED CHICKEN ; will be read as being 'KFC' ... ## New 'commodity' directive You can now pre-declare commodity names. This only has effect if --strict or --pedantic is used (see below). commodity $ commodity CAD ### Commodity sub-directives The 'commodity' directive supports several optional sub-directives, if they immediately follow the commodity directive and if they begin with whitespace: commodity $ note American Dollars format $1,000.00 nomarket default The 'note' sub-directive associates a textual note with the commodity. At present this has no value other than documentation. The 'format' directive gives you a way to tell Ledger how to format this commodity. In future using this directive will disable Ledger's observation of other ways that commodity is used, and will provide the "canonical" representation. The 'nomarket' directive states that the commodity's price should never be auto-downloaded. The 'default' directive marks this as the "default" commodity, in contexts where that applies (the same as the current 'D' directive). ## New 'tag' directive You can now pre-declare tag names. This only has effect if --strict or --pedantic is used (see below). tag Receipt tag CSV ### Tag sub-directives The 'tag' directive supports two optional sub-directives, if they immediately follow the tag directive and if they begin with whitespace: tag Receipt check value =~ /pattern/ assert value != "foobar" The 'check' and 'assert' directives warn or error (respectively) if the given value expression evaluates to false within the context of any use of the related tag. In such a context, "value" is bound to the value of the tag (which may not be a string if typed-metadata is used!). Such checks or assertions are not called if no value is given. ------------------------------------------------------------------------------ # "KNOWN" ENTITIES Normally, an account/payee/commodity/tag is considered "known" to Ledger if it: 1. Occurs within a predeclaration, using the directives above. 2. Occurs within a cleared or pending posting or transaction. Otherwise, if the account/payee/commodity/tag is first encountered in an uncleared posting or transaction, it is considered "unknown". By default, this distinction has no meaning whatsoever, and is not maintained for the sake of speed. It only has meaning if --strict or --pedantic is used (see next section). ------------------------------------------------------------------------------ # NEW OPTIONS ## --explicit When --explicit is given, *only* predeclarations establish the "known-ness" of parsed entities. I.e., if you didn't predeclare it, you don't expect to ever see it. ## --strict With --strict, referring to unknown entities causes a warning. ## --pedantic With --pedantic, referring to unknown entities causes an error. ## --check-payees By default, even with --strict or --pedantic, payees are not checked for known-ness because it is quite typical that new payees are used in uncleared transactions, or without declaring them. The --check-payees option enables --strict and --pedantic checking for payees as well. ------------------------------------------------------------------------------ # EXAMPLE Here's a real example from the baseline tests. Remember that options can be specified directly within your Ledger file! --explicit --pedantic commodity $ format $1,000.00 account Assets:Cash assert abs(amount) <= 20 check commodity == '$' account Expenses:Food alias food payee KFC 2012-02-27 KFC Expenses:Unknown $20.00 Assets:Cash 2012-02-28 KFC food $20.00 Assets:Cash test reg --strict 12-Feb-27 KFC Expenses:Food $20.00 $20.00 Assets:Cash $-20.00 0 12-Feb-28 KFC Expenses:Food $20.00 $20.00 Assets:Cash $-20.00 0 end test