hledger-lib 1.12 → 1.13
raw patch · 32 files changed
+1892/−1429 lines, 32 filesdep +file-embeddep +heredep +template-haskellPVP ok
version bump matches the API change (PVP)
Dependencies added: file-embed, here, template-haskell
API changes (from Hackage documentation)
- Hledger.Data.Account: accountSetDeclarationOrder :: Journal -> Account -> Account
- Hledger.Data.Transaction: showPostingLine :: Posting -> String
- Hledger.Data.TransactionModifier: transactionModifierToFunction :: TransactionModifier -> Transaction -> Transaction
- Hledger.Data.Types: [adeclarationorder] :: Account -> Maybe Int
- Hledger.Data.Types: [amultiplier] :: Amount -> Bool
- Hledger.Data.Types: [tpreceding_comment_lines] :: Transaction -> Text
- Hledger.Read.Common: applyTransactionModifiers :: Journal -> Journal
- Hledger.Read.Common: pushDeclaredAccount :: AccountName -> JournalParser m ()
+ Hledger.Data.Account: accountSetDeclarationInfo :: Journal -> Account -> Account
+ Hledger.Data.Amount: setFullPrecision :: Amount -> Amount
+ Hledger.Data.Amount: setMinimalPrecision :: Amount -> Amount
+ Hledger.Data.Journal: journalModifyTransactions :: Journal -> Journal
+ Hledger.Data.TransactionModifier: modifyTransactions :: [TransactionModifier] -> [Transaction] -> [Transaction]
+ Hledger.Data.Types: AccountDeclarationInfo :: Text -> [Tag] -> Int -> AccountDeclarationInfo
+ Hledger.Data.Types: [adeclarationinfo] :: Account -> Maybe AccountDeclarationInfo
+ Hledger.Data.Types: [adicomment] :: AccountDeclarationInfo -> Text
+ Hledger.Data.Types: [adideclarationorder] :: AccountDeclarationInfo -> Int
+ Hledger.Data.Types: [aditags] :: AccountDeclarationInfo -> [Tag]
+ Hledger.Data.Types: [aismultiplier] :: Amount -> Bool
+ Hledger.Data.Types: [tprecedingcomment] :: Transaction -> Text
+ Hledger.Data.Types: data AccountDeclarationInfo
+ Hledger.Data.Types: instance Control.DeepSeq.NFData Hledger.Data.Types.AccountDeclarationInfo
+ Hledger.Data.Types: instance Data.Data.Data Hledger.Data.Types.AccountDeclarationInfo
+ Hledger.Data.Types: instance GHC.Classes.Eq Hledger.Data.Types.AccountDeclarationInfo
+ Hledger.Data.Types: instance GHC.Generics.Generic Hledger.Data.Types.AccountDeclarationInfo
+ Hledger.Data.Types: instance GHC.Show.Show Hledger.Data.Types.AccountDeclarationInfo
+ Hledger.Data.Types: nullaccountdeclarationinfo :: AccountDeclarationInfo
+ Hledger.Reports.ReportOptions: [transpose_] :: ReportOpts -> Bool
+ Hledger.Utils: embedFileRelative :: FilePath -> Q Exp
+ Hledger.Utils: hereFileRelative :: FilePath -> Q Exp
+ Hledger.Utils.Test: expectParseStateOn :: (HasCallStack, Monoid st, Eq b, Show b) => StateT st (ParsecT CustomErr Text IO) a -> Text -> (st -> b) -> b -> Test ()
- Hledger.Data.Types: Account :: AccountName -> Maybe Int -> MixedAmount -> [Account] -> Int -> MixedAmount -> Maybe Account -> Bool -> Account
+ Hledger.Data.Types: Account :: AccountName -> Maybe AccountDeclarationInfo -> [Account] -> Maybe Account -> Bool -> Int -> MixedAmount -> MixedAmount -> Account
- Hledger.Data.Types: Amount :: CommoditySymbol -> Quantity -> Price -> AmountStyle -> Bool -> Amount
+ Hledger.Data.Types: Amount :: CommoditySymbol -> Quantity -> Bool -> AmountStyle -> Price -> Amount
- Hledger.Data.Types: Journal :: Maybe Year -> Maybe (CommoditySymbol, AmountStyle) -> [AccountName] -> [AccountAlias] -> [TimeclockEntry] -> [FilePath] -> [AccountName] -> Map AccountType [AccountName] -> Map CommoditySymbol Commodity -> Map CommoditySymbol AmountStyle -> [MarketPrice] -> [TransactionModifier] -> [PeriodicTransaction] -> [Transaction] -> Text -> [(FilePath, Text)] -> ClockTime -> Journal
+ Hledger.Data.Types: Journal :: Maybe Year -> Maybe (CommoditySymbol, AmountStyle) -> [AccountName] -> [AccountAlias] -> [TimeclockEntry] -> [FilePath] -> [(AccountName, AccountDeclarationInfo)] -> Map AccountType [AccountName] -> Map CommoditySymbol Commodity -> Map CommoditySymbol AmountStyle -> [MarketPrice] -> [TransactionModifier] -> [PeriodicTransaction] -> [Transaction] -> Text -> [(FilePath, Text)] -> ClockTime -> Journal
- Hledger.Data.Types: Transaction :: Integer -> GenericSourcePos -> Day -> Maybe Day -> Status -> Text -> Text -> Text -> [Tag] -> [Posting] -> Text -> Transaction
+ Hledger.Data.Types: Transaction :: Integer -> Text -> GenericSourcePos -> Day -> Maybe Day -> Status -> Text -> Text -> Text -> [Tag] -> [Posting] -> Transaction
- Hledger.Data.Types: [jdeclaredaccounts] :: Journal -> [AccountName]
+ Hledger.Data.Types: [jdeclaredaccounts] :: Journal -> [(AccountName, AccountDeclarationInfo)]
- Hledger.Read: readJournalFiles :: InputOpts -> [FilePath] -> IO (Either String Journal)
+ Hledger.Read: readJournalFiles :: InputOpts -> [PrefixedFilePath] -> IO (Either String Journal)
- Hledger.Reports.BudgetReport: budgetReport :: ReportOpts -> Bool -> Bool -> DateSpan -> Day -> Journal -> BudgetReport
+ Hledger.Reports.BudgetReport: budgetReport :: ReportOpts -> Bool -> DateSpan -> Day -> Journal -> BudgetReport
- Hledger.Reports.ReportOptions: ReportOpts :: Period -> Interval -> [Status] -> Bool -> Maybe Int -> Maybe DisplayExp -> Bool -> Bool -> Bool -> Bool -> Maybe FormatStr -> String -> Bool -> Bool -> BalanceType -> AccountListMode -> Int -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Maybe NormalSign -> Bool -> Bool -> ReportOpts
+ Hledger.Reports.ReportOptions: ReportOpts :: Period -> Interval -> [Status] -> Bool -> Maybe Int -> Maybe DisplayExp -> Bool -> Bool -> Bool -> Bool -> Maybe FormatStr -> String -> Bool -> Bool -> BalanceType -> AccountListMode -> Int -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Maybe NormalSign -> Bool -> Bool -> Bool -> ReportOpts
Files
- CHANGES +0/−613
- CHANGES.md +619/−0
- Hledger/Data/Account.hs +21/−17
- Hledger/Data/Amount.hs +21/−2
- Hledger/Data/Journal.hs +79/−51
- Hledger/Data/Timeclock.hs +1/−1
- Hledger/Data/Transaction.hs +51/−48
- Hledger/Data/TransactionModifier.hs +9/−3
- Hledger/Data/Types.hs +40/−22
- Hledger/Read.hs +1/−1
- Hledger/Read/Common.hs +34/−30
- Hledger/Read/CsvReader.hs +1/−1
- Hledger/Read/JournalReader.hs +113/−39
- Hledger/Reports/BalanceReport.hs +1/−1
- Hledger/Reports/BudgetReport.hs +23/−8
- Hledger/Reports/MultiBalanceReports.hs +1/−1
- Hledger/Reports/ReportOptions.hs +3/−0
- Hledger/Utils.hs +16/−0
- Hledger/Utils/Test.hs +16/−2
- hledger-lib.cabal +13/−4
- hledger_csv.5 +21/−20
- hledger_csv.info +26/−26
- hledger_csv.txt +4/−4
- hledger_journal.5 +247/−162
- hledger_journal.info +259/−153
- hledger_journal.txt +257/−205
- hledger_timeclock.5 +4/−4
- hledger_timeclock.info +1/−1
- hledger_timeclock.txt +1/−1
- hledger_timedot.5 +7/−7
- hledger_timedot.info +1/−1
- hledger_timedot.txt +1/−1
− CHANGES
@@ -1,613 +0,0 @@-Developer-ish changes in the hledger-lib package.-User-visible changes are noted in the hledger package changelog instead.---# 1.12 (2018/12/02)--* switch to megaparsec 7 (Alex Chen)- We now track the stack of include files in Journal ourselves, since- megaparsec dropped this feature.--* add 'ExceptT' layer to our parser monad again (Alex Chen)- We previously had a parser type, 'type ErroringJournalParser = ExceptT- String ...' for throwing parse errors without allowing further- backtracking. This parser type was removed under the assumption that it- would be possible to write our parser without this capability. However,- after a hairy backtracking bug, we would now prefer to have the option to- prevent backtracking.-- - Define a 'FinalParseError' type specifically for the 'ExceptT' layer- - Any parse error can be raised as a "final" parse error- - Tracks the stack of include files for parser errors, anticipating the- removal of the tracking of stacks of include files in megaparsec 7- - Although a stack of include files is also tracked in the 'StateT- Journal' layer of the parser, it seems easier to guarantee correct- error messages in the 'ExceptT FinalParserError' layer- - This does not make the 'StateT Journal' stack redundant because the- 'ExceptT FinalParseError' stack cannot be used to detect cycles of- include files--* more support for location-aware parse errors when re-parsing (Alex Chen)--* make 'includedirectivep' an 'ErroringJournalParser' (Alex Chen)--* drop Ord instance breaking GHC 8.6 build (Peter Simons)--* flip the arguments of (divide|multiply)[Mixed]Amount--* showTransaction: fix a case showing multiple missing amounts- showTransaction could sometimes hide the last posting's amount even if- one of the other posting amounts was already implcit, producing invalid- transaction output.--* plog, plogAt: add missing newline--* split up journalFinalise, reorder journal finalisation steps (#893) (Jesse Rosenthal)- The `journalFinalise` function has been split up, allowing more granular- control.--* journalSetTime --> journalSetLastReadTime--* journalSetFilePath has been removed, use journalAddFile instead---# 1.11.1 (2018/10/06)--* add, lib: fix wrong transaction rendering in balance assertion errors- and when using the add command--# 1.11 (2018/9/30)--* compilation now works when locale is unset (#849)--* all unit tests have been converted from HUnit+test-framework to easytest--* doctests now run quicker by default, by skipping reloading between tests. - This can be disabled by passing --slow to the doctests test suite- executable.--* doctests test suite executable now supports --verbose, which shows- progress output as tests are run if doctest 0.16.0+ is installed- (and hopefully is harmless otherwise).--* doctests now support file pattern arguments, provide more informative output.- Limiting to just the file(s) you're interested can make doctest start- much quicker. With one big caveat: you can limit the starting files,- but it always imports and tests all other local files those import.--* a bunch of custom Show instances have been replaced with defaults,- for easier troubleshooting. These were sometimes obscuring- important details, eg in test failure output. Our new policy is:- stick with default derived Show instances as far as possible, but- when necessary adjust them to valid haskell syntax so pretty-show- can pretty-print them (eg when they contain Day values, cf- https://github.com/haskell/time/issues/101). By convention, when- fields are shown in less than full detail, and/or in double-quoted- pseudo syntax, we show a double period (..) in the output.--* Amount has a new Show instance. Amount's show instance hid- important details by default, and showing more details required- increasing the debug level, which was inconvenient. Now it has a- single show instance which shows more information, is fairly- compact, and is pretty-printable.-- ghci> usd 1- OLD:- Amount {acommodity="$", aquantity=1.00, ..}- NEW:- Amount {acommodity = "$", aquantity = 1.00, aprice = NoPrice, astyle = AmountStyle "L False 2 Just '.' Nothing..", amultiplier = False}-- MixedAmount's show instance is unchanged, but showMixedAmountDebug- is affected by this change:-- ghci> putStrLn $ showMixedAmountDebug $ Mixed [usd 1]- OLD:- Mixed [Amount {acommodity="$", aquantity=1.00, aprice=, astyle=AmountStyle {ascommodityside = L, ascommodityspaced = False, asprecision = 2, asdecimalpoint = Just '.', asdigitgroups = Nothing}}]- NEW:- Mixed [Amount {acommodity="$", aquantity=1.00, aprice=, astyle=AmountStyle "L False 2 Just '.' Nothing.."}]--* Same-line & next-line comments of transactions, postings, etc.- are now parsed a bit more precisely (followingcommentp). - Previously, parsing no comment gave the same result as an empty- comment (a single newline); now it gives an empty string. - Also, and perhaps as a consequence of the above, when there's no- same-line comment but there is a next-line comment, we'll insert an- empty first line, since otherwise next-line comments would get moved- up to the same line when rendered.--* Hledger.Utils.Test exports HasCallStack--* queryDateSpan, queryDateSpan' now intersect date AND'ed date spans- instead of unioning them, and docs are clearer.--* pushAccount -> pushDeclaredAccount--* jaccounts -> jdeclaredaccounts--* AutoTransaction.hs -> PeriodicTransaction.hs & TransactionModifier.hs--* Hledger.Utils.Debug helpers have been renamed/cleaned up---# 1.10 (2018/6/30)--* build cleanly with all supported GHC versions again (7.10 to 8.4)--* support/use latest base-compat (#794)--* support/require megaparsec 6.4+--* extensive refactoring and cleanup of parsers and related types and utilities--* readJournalFile(s) cleanup, these now use InputOpts--* doctests now run a bit faster (#802)---# 1.9.1 (2018/4/30)--* new generic PeriodicReport, and some report-related type aliases--* new BudgetReport--* make (readJournal|tryReader)s?WithOpts the default api, dropping "WithOpts"--* automated postings and command line account aliases happen earlier- in journal processing (see hledger changelog)---# 1.9 (2018/3/31)--* support ghc 8.4, latest deps--* when the system text encoding is UTF-8, ignore any UTF-8 BOM prefix-found when reading files.--* CompoundBalanceReport amounts are now normally positive.-The bs/bse/cf/is commands now show normal income, liability and equity-balances as positive. Negative numbers now indicate a contra-balance-(eg an overdrawn checking account), a net loss, a negative net worth,-etc. This makes these reports more like conventional financial-statements, and easier to read and share with others. (experimental)--* splitSpan now returns no spans for an empty datespan--* don't count periodic/modifier txns in Journal debug output--* lib/ui/web/api: move embedded manual files to extra-source-files--* Use skipMany/skipSome for parsing spacenonewline (Moritz Kiefer)-This avoids allocating the list of space characters only to then-discard it.--* rename, clarify purpose of balanceReportFromMultiBalanceReport--* fix some hlint warnings--* add some easytest tests---# 1.5 (2017/12/31)--* -V/--value uses today's market prices by default, not those of last transaction date. #683, #648)--* csv: allow balance assignment (balance assertion only, no amount) in csv records (Nadrieril)--* journal: allow space as digit group separator character, #330 (Mykola Orliuk)--* journal: balance assertion errors now show line of failed assertion posting, #481 (Sam Jeeves)--* journal: better errors for directives, #402 (Mykola Orliuk)--* journal: better errors for included files, #660 (Mykola Orliuk)--* journal: commodity directives in parent files are inherited by included files, #487 (Mykola Orliuk)--* journal: commodity directives limits precision even after -B, #509 (Mykola Orliuk)--* journal: decimal point/digit group separator chars are now inferred from an applicable commodity directive or default commodity directive. #399, #487 (Mykola Orliuk)--* journal: numbers are parsed more strictly (Mykola Orliuk)--* journal: support Ledger-style automated postings, enabled with --auto flag (Dmitry Astapov)--* journal: support Ledger-style periodic transactions, enabled with --forecast flag (Dmitry Astapov)--* period expressions: fix "nth day of {week,month}", which could generate wrong intervals (Dmitry Astapov)--* period expressions: month names are now case-insensitive (Dmitry Astapov)--* period expressions: stricter checking for invalid expressions (Mykola Orliuk)--* period expressions: support "every 11th Nov" (Dmitry Astapov)--* period expressions: support "every 2nd Thursday of month" (Dmitry Astapov)--* period expressions: support "every Tuesday", short for "every <n>th day of week" (Dmitry Astapov)--* remove upper bounds on all but hledger* and base (experimental)- It's rare that my deps break their api or that newer versions must- be avoided, and very common that they release new versions which I- must tediously and promptly test and release hackage revisions for- or risk falling out of stackage. Trying it this way for a bit.---# 1.4 (2017/9/30)--* add readJournalFile[s]WithOpts, with simpler arguments and support-for detecting new transactions since the last read.--* query: add payee: and note: query terms, improve description/payee/note docs (Jakub Zárybnický, Simon Michael, #598, #608)--* journal, cli: make trailing whitespace significant in regex account aliases-Trailing whitespace in the replacement part of a regular expression-account alias is now significant. Eg, converting a parent account to-just an account name prefix: --alias '/:acct:/=:acct '--* timedot: allow a quantity of seconds, minutes, days, weeks, months- or years to be logged as Ns, Nm, Nd, Nw, Nmo, Ny--* csv: switch the order of generated postings, so account1 is first.-This simplifies things and facilitates future improvements.--* csv: show the "creating/using rules file" message only with --debug--* csv: fix multiple includes in one rules file--* csv: add "newest-first" rule for more robust same-day ordering--* deps: allow ansi-terminal 0.7--* deps: add missing parsec lower bound, possibly related to #596, fpco/stackage#2835--* deps: drop oldtime flag, require time 1.5+--* deps: remove ghc < 7.6 support, remove obsolete CPP conditionals--* deps: fix test suite with ghc 8.2---# 1.3.1 (2017/8/25)--* Fix a bug with -H showing nothing for empty periods (#583, Nicholas Niro)-This patch fixes a bug that happened when using the -H option on-a period without any transaction. Previously, the behavior was no-output at all even though it should have shown the previous ending balances-of past transactions. (This is similar to previously using -H with -E,-but with the extra advantage of not showing empty accounts)--* allow megaparsec 6 (#594)--* allow megaparsec-6.1 (Hans-Peter Deifel)--* fix test suite with Cabal 2 (#596)---# 1.3 (2017/6/30)--journal: The "uncleared" transaction/posting status, and associated UI flags-and keys, have been renamed to "unmarked" to remove ambiguity and-confusion. This means that we have dropped the `--uncleared` flag,-and our `-U` flag now matches only unmarked things and not pending-ones. See the issue and linked mail list discussion for more-background. (#564)--csv: assigning to the "balance" field name creates balance-assertions (#537, Dmitry Astapov).--csv: Doubled minus signs are handled more robustly (fixes #524, Nicolas Wavrant, Simon Michael)--Multiple "status:" query terms are now OR'd together. (#564)--deps: allow megaparsec 5.3.---# 1.2 (2017/3/31)--## journal format--A pipe character can optionally be used to delimit payee names in-transaction descriptions, for more accurate querying and pivoting by-payee. Eg, for a description like `payee name | additional notes`,-the two parts will be accessible as pseudo-fields/tags named `payee`-and `note`.--Some journal parse errors now show the range of lines involved, not just the first.--## ledger format--The experimental `ledger:` reader based on the WIP ledger4 project has-been disabled, reducing build dependencies.--## Misc--Fix a bug when tying the knot between postings and their parent transaction, reducing memory usage by about 10% (#483) (Mykola Orliuk)--Fix a few spaceleaks (#413) (Moritz Kiefer)--Add Ledger.Parse.Text to package.yaml, fixing a potential build failure.--Allow megaparsec 5.2 (#503)--Rename optserror -> usageError, consolidate with other error functions---# 1.1 (2016/12/31)--## journal format--- balance assignments are now supported (#438, #129, #157, #288)-- This feature also brings a slight performance drop (~5%);- optimisations welcome.--- also recognise `*.hledger` files as hledger journal format--## ledger format--- use ledger-parse from the ledger4 project as an alternate reader for C++ Ledger journals- - The idea is that some day we might get better compatibility with Ledger files this way.- Right now this reader is not very useful and will be used only if you explicitly select it with a `ledger:` prefix.- It parses transaction dates, descriptions, accounts and amounts, and ignores everything else.- Amount parsing is delegated to hledger's journal parser, and malformed amounts might be silently ignored.-- This adds at least some of the following as new dependencies for hledger-lib:- parsers, parsec, attoparsec, trifecta.--## misc--- update base lower bound to enforce GHC 7.10+- - hledger-lib had a valid install plan with GHC 7.8, but currently requires GHC 7.10 to compile.- Now we require base 4.8+ everywhere to ensure the right GHC version at the start.- -- Hledger.Read api cleanups--- rename dbgIO to dbg0IO, consistent with dbg0, and document a bug in dbg*IO--- make readJournalFiles [f] equivalent to readJournalFile f (#437)--- more general parser types enabling reuse outside of IO (#439)---# 1.0.1 (2016/10/27)--- allow megaparsec 5.0 or 5.1---# 1.0 (2016/10/26)--## timedot format--- new "timedot" format for retroactive/approximate time logging.-- Timedot is a plain text format for logging dated, categorised- quantities (eg time), supported by hledger. It is convenient- for approximate and retroactive time logging, eg when the- real-time clock-in/out required with a timeclock file is too- precise or too interruptive. It can be formatted like a bar- chart, making clear at a glance where time was spent.--## timeclock format--- renamed "timelog" format to "timeclock", matching the emacs package--- sessions can no longer span file boundaries (unclocked-out-- sessions will be auto-closed at the end of the file).--- transaction ids now count up rather than down (#394)--- timeclock files no longer support default year directives--- removed old code for appending timeclock transactions to journal transactions.-- A holdover from the days when both were allowed in one file.--## csv format--- fix empty field assignment parsing, rule parse errors after megaparsec port (#407) (Hans-Peter Deifel)--## journal format--- journal files can now include timeclock or timedot files (#320)-- (but not yet CSV files).--- fixed an issue with ordering of same-date transactions included from other files--- the "commodity" directive and "format" subdirective are now supported, allowing-- full control of commodity style (#295) The commodity directive's- format subdirective can now be used to override the inferred- style for a commodity, eg to increase or decrease the- precision. This is at least a good workaround for #295.--- Ledger-style "apply account"/"end apply account" directives are now used to set a default parent account.--- the Ledger-style "account" directive is now accepted (and ignored).--- bracketed posting dates are more robust (#304)-- Bracketed posting dates were fragile; they worked only if you- wrote full 10-character dates. Also some semantics were a bit- unclear. Now they should be robust, and have been documented- more clearly. This is a legacy undocumented Ledger syntax, but- it improves compatibility and might be preferable to the more- verbose "date:" tags if you write posting dates often (as I do).- Internally, bracketed posting dates are no longer considered to- be tags. Journal comment, tag, and posting date parsers have- been reworked, all with doctests.--- balance assertion failure messages are clearer--- with --debug=2, more detail about balance assertions is shown.--## misc--- file parsers have been ported from Parsec to Megaparsec \o/ (#289, #366) (Alexey Shmalko, Moritz Kiefer)--- most hledger types have been converted from String to Text, reducing memory usage by 30%+ on large files--- file parsers have been simplified for easier troubleshooting (#275).-- The journal/timeclock/timedot parsers, instead of constructing- opaque journal update functions which are later applied to build- the journal, now construct the journal directly by modifying the- parser state. This is easier to understand and debug. It also- rules out the possibility of journal updates being a space- leak. (They weren't, in fact this change increased memory usage- slightly, but that has been addressed in other ways). The- ParsedJournal type alias has been added to distinguish- "being-parsed" journals and "finalised" journals.--- file format detection is more robust.-- The Journal, Timelog and Timedot readers' detectors now check- each line in the sample data, not just the first one. I think the- sample data is only about 30 chars right now, but even so this- fixed a format detection issue I was seeing. - Also, we now always try parsing stdin as journal format (not just sometimes).--- all file formats now produce transaction ids, not just journal (#394)--- git clone of the hledger repo on windows now works (#345)--- added missing benchmark file (#342)--- our stack.yaml files are more compatible across stack versions (#300)--- use newer file-embed to fix ghci working directory dependence (<https://github.com/snoyberg/file-embed/issues/18>)--- report more accurate dates in account transaction report when postings have their own dates-- (affects hledger-ui and hledger-web registers).- The newly-named "transaction register date" is the date to be- displayed for that transaction in a transaction register, for- some current account and filter query. It is either the- transaction date from the journal ("transaction general date"),- or if postings to the current account and matched by the- register's filter query have their own dates, the earliest of- those posting dates.--- simplify account transactions report's running total.-- The account transactions report used for hledger-ui and -web- registers now gives either the "period total" or "historical- total", depending strictly on the --historical flag. It doesn't- try to indicate whether the historical total is the accurate- historical balance (which depends on the user's report query).--- reloading a file now preserves the effect of options, query arguments etc.--- reloading a journal should now reload all included files as well.--- the Hledger.Read.\* modules have been reorganised for better reuse.-- Hledger.Read.Utils has been renamed Hledger.Read.Common- and holds low-level parsers & utilities; high-level read- utilities are now in Hledger.Read.--- clarify amount display style canonicalisation code and terminology a bit.-- Individual amounts still have styles; from these we derive- the standard "commodity styles". In user docs, we might call- these "commodity formats" since they can be controlled by the- "format" subdirective in journal files.--- Journal is now a monoid--- expandPath now throws a proper IO error--- more unit tests, start using doctest-----0.27 (2015/10/30)--- The main hledger types now derive NFData, which makes it easier to- time things with criterion.--- Utils has been split up more.--- Utils.Regex: regular expression compilation has been memoized, and- memoizing versions of regexReplace[CI] have been added, since- compiling regular expressions every time seems to be quite- expensive (#244).- -- Utils.String: strWidth is now aware of multi-line strings (#242).--- Read: parsers now use a consistent p suffix.--- New dependencies: deepseq, uglymemo.--- All the hledger packages' cabal files are now generated from- simpler, less redundant yaml files by hpack, in principle. In- practice, manual fixups are still needed until hpack gets better,- but it's still a win.--0.26 (2015/7/12)--- allow year parser to handle arbitrarily large years-- Journal's Show instance reported one too many accounts-- some cleanup of debug trace helpers-- tighten up some date and account name parsers (don't accept leading spaces; hadddocks)-- drop regexpr dependency--0.25.1 (2015/4/29)--- support/require base-compat >0.8 (#245)--0.25 (2015/4/7)---- GHC 7.10 compatibility (#239)--0.24.1 (2015/3/15)--- fix JournalReader "ctx" compilation warning-- add some type signatures in Utils to help make ghci-web--0.24 (2014/12/25)--- fix combineJournalUpdates folding order-- fix a regexReplaceCI bug-- fix a splitAtElement bug with adjacent separators-- mostly replace slow regexpr with regex-tdfa (fixes #189)-- use the modern Text.Parsec API-- allow transformers 0.4*-- regexReplace now supports backreferences-- Transactions now remember their parse location in the journal file-- export Regexp types, disambiguate CsvReader's similarly-named type-- export failIfInvalidMonth/Day (fixes #216)-- track the commodity of zero amounts when possible- (useful eg for hledger-web's multi-commodity charts)-- show posting dates in debug output-- more debug helpers--0.23.3 (2014/9/12)--- allow transformers 0.4*--0.23.2 (2014/5/8)--- postingsReport: also fix date sorting of displayed postings (#184)--0.23.1 (2014/5/7)--- postingsReport: with disordered journal entries, postings before the- report start date could get wrongly included. (#184)--0.23 (2014/5/1)--- orDatesFrom -> spanDefaultsFrom--0.22.2 (2014/4/16)--- display years before 1000 with four digits, not three-- avoid pretty-show to build with GHC < 7.4-- allow text 1.1, drop data-pprint to build with GHC 7.8.x--0.22.1 (2014/1/6) and older: see http://hledger.org/release-notes or doc/CHANGES.md.
+ CHANGES.md view
@@ -0,0 +1,619 @@+Internal/api/developer-ish changes in the hledger-lib (and hledger) packages.+For user-visible changes, see the hledger package changelog.++# 1.13 (2019/02/01)++- in Journal's jtxns field, forecasted txns are appended rather than prepended++- API changes:++ added:+ +setFullPrecision+ +setMinimalPrecision+ +expectParseStateOn+ +embedFileRelative+ +hereFileRelative++ changed:+ - amultiplier -> aismultiplier+ - Amount fields reordered for clearer debug output+ - tpreceding_comment_lines -> tprecedingcomment, reordered+ - Hledger.Data.TransactionModifier.transactionModifierToFunction -> modifyTransactions+ - Hledger.Read.Common.applyTransactionModifiers -> Hledger.Data.Journal.journalModifyTransactions++ - HelpTemplate -> CommandDoc+++# 1.12 (2018/12/02)++- switch to megaparsec 7 (Alex Chen)+ We now track the stack of include files in Journal ourselves, since+ megaparsec dropped this feature.++- add 'ExceptT' layer to our parser monad again (Alex Chen)+ We previously had a parser type, 'type ErroringJournalParser = ExceptT+ String ...' for throwing parse errors without allowing further+ backtracking. This parser type was removed under the assumption that it+ would be possible to write our parser without this capability. However,+ after a hairy backtracking bug, we would now prefer to have the option to+ prevent backtracking.++ - Define a 'FinalParseError' type specifically for the 'ExceptT' layer+ - Any parse error can be raised as a "final" parse error+ - Tracks the stack of include files for parser errors, anticipating the+ removal of the tracking of stacks of include files in megaparsec 7+ - Although a stack of include files is also tracked in the 'StateT+ Journal' layer of the parser, it seems easier to guarantee correct+ error messages in the 'ExceptT FinalParserError' layer+ - This does not make the 'StateT Journal' stack redundant because the+ 'ExceptT FinalParseError' stack cannot be used to detect cycles of+ include files++- more support for location-aware parse errors when re-parsing (Alex Chen)++- make 'includedirectivep' an 'ErroringJournalParser' (Alex Chen)++- drop Ord instance breaking GHC 8.6 build (Peter Simons)++- flip the arguments of (divide\|multiply)\[Mixed\]Amount++- showTransaction: fix a case showing multiple missing amounts+ showTransaction could sometimes hide the last posting's amount even if+ one of the other posting amounts was already implcit, producing invalid+ transaction output.++- plog, plogAt: add missing newline++- split up journalFinalise, reorder journal finalisation steps (#893) (Jesse Rosenthal)+ The `journalFinalise` function has been split up, allowing more granular+ control.++- journalSetTime --> journalSetLastReadTime++- journalSetFilePath has been removed, use journalAddFile instead++# 1.11.1 (2018/10/06)++- add, lib: fix wrong transaction rendering in balance assertion errors+ and when using the add command++# 1.11 (2018/9/30)++- compilation now works when locale is unset (#849)++- all unit tests have been converted from HUnit+test-framework to easytest++- doctests now run quicker by default, by skipping reloading between tests.+ This can be disabled by passing --slow to the doctests test suite+ executable.++- doctests test suite executable now supports --verbose, which shows+ progress output as tests are run if doctest 0.16.0+ is installed+ (and hopefully is harmless otherwise).++- doctests now support file pattern arguments, provide more informative output.+ Limiting to just the file(s) you're interested can make doctest start+ much quicker. With one big caveat: you can limit the starting files,+ but it always imports and tests all other local files those import.++- a bunch of custom Show instances have been replaced with defaults,+ for easier troubleshooting. These were sometimes obscuring+ important details, eg in test failure output. Our new policy is:+ stick with default derived Show instances as far as possible, but+ when necessary adjust them to valid haskell syntax so pretty-show+ can pretty-print them (eg when they contain Day values, cf+ https://github.com/haskell/time/issues/101). By convention, when+ fields are shown in less than full detail, and/or in double-quoted+ pseudo syntax, we show a double period (..) in the output.++- Amount has a new Show instance. Amount's show instance hid+ important details by default, and showing more details required+ increasing the debug level, which was inconvenient. Now it has a+ single show instance which shows more information, is fairly+ compact, and is pretty-printable.++ ghci> usd 1+ OLD:+ Amount {acommodity="$", aquantity=1.00, ..}+ NEW:+ Amount {acommodity = "$", aquantity = 1.00, aprice = NoPrice, astyle = AmountStyle "L False 2 Just '.' Nothing..", amultiplier = False}++ MixedAmount's show instance is unchanged, but showMixedAmountDebug+ is affected by this change:++ ghci> putStrLn $ showMixedAmountDebug $ Mixed [usd 1]+ OLD:+ Mixed [Amount {acommodity="$", aquantity=1.00, aprice=, astyle=AmountStyle {ascommodityside = L, ascommodityspaced = False, asprecision = 2, asdecimalpoint = Just '.', asdigitgroups = Nothing}}]+ NEW:+ Mixed [Amount {acommodity="$", aquantity=1.00, aprice=, astyle=AmountStyle "L False 2 Just '.' Nothing.."}]++- Same-line & next-line comments of transactions, postings, etc.+ are now parsed a bit more precisely (followingcommentp).+ Previously, parsing no comment gave the same result as an empty+ comment (a single newline); now it gives an empty string.\+ Also, and perhaps as a consequence of the above, when there's no+ same-line comment but there is a next-line comment, we'll insert an+ empty first line, since otherwise next-line comments would get moved+ up to the same line when rendered.++- Hledger.Utils.Test exports HasCallStack++- queryDateSpan, queryDateSpan' now intersect date AND'ed date spans+ instead of unioning them, and docs are clearer.++- pushAccount -> pushDeclaredAccount++- jaccounts -> jdeclaredaccounts++- AutoTransaction.hs -> PeriodicTransaction.hs & TransactionModifier.hs++- Hledger.Utils.Debug helpers have been renamed/cleaned up++# 1.10 (2018/6/30)++- build cleanly with all supported GHC versions again (7.10 to 8.4)++- support/use latest base-compat (#794)++- support/require megaparsec 6.4+++- extensive refactoring and cleanup of parsers and related types and utilities++- readJournalFile(s) cleanup, these now use InputOpts++- doctests now run a bit faster (#802)++# 1.9.1 (2018/4/30)++- new generic PeriodicReport, and some report-related type aliases++- new BudgetReport++- make (readJournal\|tryReader)s?WithOpts the default api, dropping "WithOpts"++- automated postings and command line account aliases happen earlier+ in journal processing (see hledger changelog)++# 1.9 (2018/3/31)++- support ghc 8.4, latest deps++- when the system text encoding is UTF-8, ignore any UTF-8 BOM prefix+ found when reading files.++- CompoundBalanceReport amounts are now normally positive.+ The bs/bse/cf/is commands now show normal income, liability and equity+ balances as positive. Negative numbers now indicate a contra-balance+ (eg an overdrawn checking account), a net loss, a negative net worth,+ etc. This makes these reports more like conventional financial+ statements, and easier to read and share with others. (experimental)++- splitSpan now returns no spans for an empty datespan++- don't count periodic/modifier txns in Journal debug output++- lib/ui/web/api: move embedded manual files to extra-source-files++- Use skipMany/skipSome for parsing spacenonewline (Moritz Kiefer)+ This avoids allocating the list of space characters only to then+ discard it.++- rename, clarify purpose of balanceReportFromMultiBalanceReport++- fix some hlint warnings++- add some easytest tests++# 1.5 (2017/12/31)++- -V/--value uses today's market prices by default, not those of last transaction date. #683, #648)++- csv: allow balance assignment (balance assertion only, no amount) in csv records (Nadrieril)++- journal: allow space as digit group separator character, #330 (Mykola Orliuk)++- journal: balance assertion errors now show line of failed assertion posting, #481 (Sam Jeeves)++- journal: better errors for directives, #402 (Mykola Orliuk)++- journal: better errors for included files, #660 (Mykola Orliuk)++- journal: commodity directives in parent files are inherited by included files, #487 (Mykola Orliuk)++- journal: commodity directives limits precision even after -B, #509 (Mykola Orliuk)++- journal: decimal point/digit group separator chars are now inferred from an applicable commodity directive or default commodity directive. #399, #487 (Mykola Orliuk)++- journal: numbers are parsed more strictly (Mykola Orliuk)++- journal: support Ledger-style automated postings, enabled with --auto flag (Dmitry Astapov)++- journal: support Ledger-style periodic transactions, enabled with --forecast flag (Dmitry Astapov)++- period expressions: fix "nth day of {week,month}", which could generate wrong intervals (Dmitry Astapov)++- period expressions: month names are now case-insensitive (Dmitry Astapov)++- period expressions: stricter checking for invalid expressions (Mykola Orliuk)++- period expressions: support "every 11th Nov" (Dmitry Astapov)++- period expressions: support "every 2nd Thursday of month" (Dmitry Astapov)++- period expressions: support "every Tuesday", short for "every <n>th day of week" (Dmitry Astapov)++- remove upper bounds on all but hledger* and base (experimental)+ It's rare that my deps break their api or that newer versions must+ be avoided, and very common that they release new versions which I+ must tediously and promptly test and release hackage revisions for+ or risk falling out of stackage. Trying it this way for a bit.++# 1.4 (2017/9/30)++- add readJournalFile\[s\]WithOpts, with simpler arguments and support+ for detecting new transactions since the last read.++- query: add payee: and note: query terms, improve description/payee/note docs (Jakub Zárybnický, Simon Michael, #598, #608)++- journal, cli: make trailing whitespace significant in regex account aliases+ Trailing whitespace in the replacement part of a regular expression+ account alias is now significant. Eg, converting a parent account to+ just an account name prefix: --alias '/:acct:/=:acct'++- timedot: allow a quantity of seconds, minutes, days, weeks, months+ or years to be logged as Ns, Nm, Nd, Nw, Nmo, Ny++- csv: switch the order of generated postings, so account1 is first.+ This simplifies things and facilitates future improvements.++- csv: show the "creating/using rules file" message only with --debug++- csv: fix multiple includes in one rules file++- csv: add "newest-first" rule for more robust same-day ordering++- deps: allow ansi-terminal 0.7++- deps: add missing parsec lower bound, possibly related to #596, fpco/stackage#2835++- deps: drop oldtime flag, require time 1.5+++- deps: remove ghc < 7.6 support, remove obsolete CPP conditionals++- deps: fix test suite with ghc 8.2++# 1.3.1 (2017/8/25)++- Fix a bug with -H showing nothing for empty periods (#583, Nicholas Niro)+ This patch fixes a bug that happened when using the -H option on+ a period without any transaction. Previously, the behavior was no+ output at all even though it should have shown the previous ending balances+ of past transactions. (This is similar to previously using -H with -E,+ but with the extra advantage of not showing empty accounts)++- allow megaparsec 6 (#594)++- allow megaparsec-6.1 (Hans-Peter Deifel)++- fix test suite with Cabal 2 (#596)++# 1.3 (2017/6/30)++journal: The "uncleared" transaction/posting status, and associated UI flags+and keys, have been renamed to "unmarked" to remove ambiguity and+confusion. This means that we have dropped the `--uncleared` flag,+and our `-U` flag now matches only unmarked things and not pending+ones. See the issue and linked mail list discussion for more+background. (#564)++csv: assigning to the "balance" field name creates balance+assertions (#537, Dmitry Astapov).++csv: Doubled minus signs are handled more robustly (fixes #524, Nicolas Wavrant, Simon Michael)++Multiple "status:" query terms are now OR'd together. (#564)++deps: allow megaparsec 5.3.++# 1.2 (2017/3/31)++## journal format++A pipe character can optionally be used to delimit payee names in+transaction descriptions, for more accurate querying and pivoting by+payee. Eg, for a description like `payee name | additional notes`,+the two parts will be accessible as pseudo-fields/tags named `payee`+and `note`.++Some journal parse errors now show the range of lines involved, not just the first.++## ledger format++The experimental `ledger:` reader based on the WIP ledger4 project has+been disabled, reducing build dependencies.++## Misc++Fix a bug when tying the knot between postings and their parent transaction, reducing memory usage by about 10% (#483) (Mykola Orliuk)++Fix a few spaceleaks (#413) (Moritz Kiefer)++Add Ledger.Parse.Text to package.yaml, fixing a potential build failure.++Allow megaparsec 5.2 (#503)++Rename optserror -> usageError, consolidate with other error functions++# 1.1 (2016/12/31)++## journal format++- balance assignments are now supported (#438, #129, #157, #288)++ This feature also brings a slight performance drop (\~5%);+ optimisations welcome.++- also recognise `*.hledger` files as hledger journal format++## ledger format++- use ledger-parse from the ledger4 project as an alternate reader for C++ Ledger journals++ The idea is that some day we might get better compatibility with Ledger files this way.+ Right now this reader is not very useful and will be used only if you explicitly select it with a `ledger:` prefix.+ It parses transaction dates, descriptions, accounts and amounts, and ignores everything else.+ Amount parsing is delegated to hledger's journal parser, and malformed amounts might be silently ignored.++ This adds at least some of the following as new dependencies for hledger-lib:+ parsers, parsec, attoparsec, trifecta.++## misc++- update base lower bound to enforce GHC 7.10+++ hledger-lib had a valid install plan with GHC 7.8, but currently requires GHC 7.10 to compile.+ Now we require base 4.8+ everywhere to ensure the right GHC version at the start.++- Hledger.Read api cleanups++- rename dbgIO to dbg0IO, consistent with dbg0, and document a bug in dbg*IO++- make readJournalFiles \[f\] equivalent to readJournalFile f (#437)++- more general parser types enabling reuse outside of IO (#439)++# 1.0.1 (2016/10/27)++- allow megaparsec 5.0 or 5.1++# 1.0 (2016/10/26)++## timedot format++- new "timedot" format for retroactive/approximate time logging.++ Timedot is a plain text format for logging dated, categorised+ quantities (eg time), supported by hledger. It is convenient+ for approximate and retroactive time logging, eg when the+ real-time clock-in/out required with a timeclock file is too+ precise or too interruptive. It can be formatted like a bar+ chart, making clear at a glance where time was spent.++## timeclock format++- renamed "timelog" format to "timeclock", matching the emacs package++- sessions can no longer span file boundaries (unclocked-out++ sessions will be auto-closed at the end of the file).++- transaction ids now count up rather than down (#394)++- timeclock files no longer support default year directives++- removed old code for appending timeclock transactions to journal transactions.++ A holdover from the days when both were allowed in one file.++## csv format++- fix empty field assignment parsing, rule parse errors after megaparsec port (#407) (Hans-Peter Deifel)++## journal format++- journal files can now include timeclock or timedot files (#320)++ (but not yet CSV files).++- fixed an issue with ordering of same-date transactions included from other files++- the "commodity" directive and "format" subdirective are now supported, allowing++ full control of commodity style (#295) The commodity directive's+ format subdirective can now be used to override the inferred+ style for a commodity, eg to increase or decrease the+ precision. This is at least a good workaround for #295.++- Ledger-style "apply account"/"end apply account" directives are now used to set a default parent account.++- the Ledger-style "account" directive is now accepted (and ignored).++- bracketed posting dates are more robust (#304)++ Bracketed posting dates were fragile; they worked only if you+ wrote full 10-character dates. Also some semantics were a bit+ unclear. Now they should be robust, and have been documented+ more clearly. This is a legacy undocumented Ledger syntax, but+ it improves compatibility and might be preferable to the more+ verbose "date:" tags if you write posting dates often (as I do).+ Internally, bracketed posting dates are no longer considered to+ be tags. Journal comment, tag, and posting date parsers have+ been reworked, all with doctests.++- balance assertion failure messages are clearer++- with --debug=2, more detail about balance assertions is shown.++## misc++- file parsers have been ported from Parsec to Megaparsec \o/ (#289, #366) (Alexey Shmalko, Moritz Kiefer)++- most hledger types have been converted from String to Text, reducing memory usage by 30%+ on large files++- file parsers have been simplified for easier troubleshooting (#275).++ The journal/timeclock/timedot parsers, instead of constructing+ opaque journal update functions which are later applied to build+ the journal, now construct the journal directly by modifying the+ parser state. This is easier to understand and debug. It also+ rules out the possibility of journal updates being a space+ leak. (They weren't, in fact this change increased memory usage+ slightly, but that has been addressed in other ways). The+ ParsedJournal type alias has been added to distinguish+ "being-parsed" journals and "finalised" journals.++- file format detection is more robust.++ The Journal, Timelog and Timedot readers' detectors now check+ each line in the sample data, not just the first one. I think the+ sample data is only about 30 chars right now, but even so this+ fixed a format detection issue I was seeing.+ Also, we now always try parsing stdin as journal format (not just sometimes).++- all file formats now produce transaction ids, not just journal (#394)++- git clone of the hledger repo on windows now works (#345)++- added missing benchmark file (#342)++- our stack.yaml files are more compatible across stack versions (#300)++- use newer file-embed to fix ghci working directory dependence (<https://github.com/snoyberg/file-embed/issues/18>)++- report more accurate dates in account transaction report when postings have their own dates++ (affects hledger-ui and hledger-web registers).+ The newly-named "transaction register date" is the date to be+ displayed for that transaction in a transaction register, for+ some current account and filter query. It is either the+ transaction date from the journal ("transaction general date"),+ or if postings to the current account and matched by the+ register's filter query have their own dates, the earliest of+ those posting dates.++- simplify account transactions report's running total.++ The account transactions report used for hledger-ui and -web+ registers now gives either the "period total" or "historical+ total", depending strictly on the --historical flag. It doesn't+ try to indicate whether the historical total is the accurate+ historical balance (which depends on the user's report query).++- reloading a file now preserves the effect of options, query arguments etc.++- reloading a journal should now reload all included files as well.++- the Hledger.Read.* modules have been reorganised for better reuse.++ Hledger.Read.Utils has been renamed Hledger.Read.Common+ and holds low-level parsers & utilities; high-level read+ utilities are now in Hledger.Read.++- clarify amount display style canonicalisation code and terminology a bit.++ Individual amounts still have styles; from these we derive+ the standard "commodity styles". In user docs, we might call+ these "commodity formats" since they can be controlled by the+ "format" subdirective in journal files.++- Journal is now a monoid++- expandPath now throws a proper IO error++- more unit tests, start using doctest++0.27 (2015/10/30)++- The main hledger types now derive NFData, which makes it easier to+ time things with criterion.++- Utils has been split up more.++- Utils.Regex: regular expression compilation has been memoized, and+ memoizing versions of regexReplace\[CI\] have been added, since+ compiling regular expressions every time seems to be quite+ expensive (#244).++- Utils.String: strWidth is now aware of multi-line strings (#242).++- Read: parsers now use a consistent p suffix.++- New dependencies: deepseq, uglymemo.++- All the hledger packages' cabal files are now generated from+ simpler, less redundant yaml files by hpack, in principle. In+ practice, manual fixups are still needed until hpack gets better,+ but it's still a win.++0.26 (2015/7/12)++- allow year parser to handle arbitrarily large years+- Journal's Show instance reported one too many accounts+- some cleanup of debug trace helpers+- tighten up some date and account name parsers (don't accept leading spaces; hadddocks)+- drop regexpr dependency++0.25.1 (2015/4/29)++- support/require base-compat >0.8 (#245)++0.25 (2015/4/7)++- GHC 7.10 compatibility (#239)++0.24.1 (2015/3/15)++- fix JournalReader "ctx" compilation warning+- add some type signatures in Utils to help make ghci-web++0.24 (2014/12/25)++- fix combineJournalUpdates folding order+- fix a regexReplaceCI bug+- fix a splitAtElement bug with adjacent separators+- mostly replace slow regexpr with regex-tdfa (fixes #189)+- use the modern Text.Parsec API+- allow transformers 0.4*+- regexReplace now supports backreferences+- Transactions now remember their parse location in the journal file+- export Regexp types, disambiguate CsvReader's similarly-named type+- export failIfInvalidMonth/Day (fixes #216)+- track the commodity of zero amounts when possible+ (useful eg for hledger-web's multi-commodity charts)+- show posting dates in debug output+- more debug helpers++0.23.3 (2014/9/12)++- allow transformers 0.4*++0.23.2 (2014/5/8)++- postingsReport: also fix date sorting of displayed postings (#184)++0.23.1 (2014/5/7)++- postingsReport: with disordered journal entries, postings before the+ report start date could get wrongly included. (#184)++0.23 (2014/5/1)++- orDatesFrom -> spanDefaultsFrom++0.22.2 (2014/4/16)++- display years before 1000 with four digits, not three+- avoid pretty-show to build with GHC < 7.4+- allow text 1.1, drop data-pprint to build with GHC 7.8.x++0.22.1 (2014/1/6) and older: see http://hledger.org/release-notes or doc/CHANGES.md.
Hledger/Data/Account.hs view
@@ -45,14 +45,14 @@ -- ] nullacct = Account- { aname = ""- , adeclarationorder = Nothing- , aparent = Nothing- , asubs = []- , anumpostings = 0- , aebalance = nullmixedamt- , aibalance = nullmixedamt- , aboring = False+ { aname = ""+ , adeclarationinfo = Nothing+ , asubs = []+ , aparent = Nothing+ , aboring = False+ , anumpostings = 0+ , aebalance = nullmixedamt+ , aibalance = nullmixedamt } -- | Derive 1. an account tree and 2. each account's total exclusive@@ -83,7 +83,11 @@ accountTree rootname as = nullacct{aname=rootname, asubs=map (uncurry accountTree') $ M.assocs m } where T m = treeFromPaths $ map expandAccountName as :: FastTree AccountName- accountTree' a (T m) = nullacct{aname=a, asubs=map (uncurry accountTree') $ M.assocs m}+ accountTree' a (T m) =+ nullacct{+ aname=a+ ,asubs=map (uncurry accountTree') $ M.assocs m+ } -- | Tie the knot so all subaccounts' parents are set correctly. tieAccountParents :: Account -> Account@@ -204,12 +208,11 @@ maybeflip | normalsign==NormallyNegative = id | otherwise = flip --- | Look up an account's declaration order, if any, from the Journal and set it.--- This is the relative position of its account directive --- among the other account directives.-accountSetDeclarationOrder :: Journal -> Account -> Account-accountSetDeclarationOrder j a@Account{..} = - a{adeclarationorder = findIndex (==aname) (jdeclaredaccounts j)}+-- | Add extra info for this account derived from the Journal's+-- account directives, if any (comment, tags, declaration order..).+accountSetDeclarationInfo :: Journal -> Account -> Account+accountSetDeclarationInfo j a@Account{..} =+ a{ adeclarationinfo=lookup aname $ jdeclaredaccounts j } -- | Sort account names by the order in which they were declared in -- the journal, at each level of the account tree (ie within each@@ -227,7 +230,7 @@ drop 1 $ -- drop the root node that was added flattenAccounts $ -- convert to an account list sortAccountTreeByDeclaration $ -- sort by declaration order (and name)- mapAccounts (accountSetDeclarationOrder j) $ -- add declaration order info + mapAccounts (accountSetDeclarationInfo j) $ -- add declaration order info accountTree "root" -- convert to an account tree as @@ -243,9 +246,10 @@ map sortAccountTreeByDeclaration $ asubs a } +accountDeclarationOrderAndName :: Account -> (Int, AccountName) accountDeclarationOrderAndName a = (adeclarationorder', aname a) where- adeclarationorder' = fromMaybe maxBound (adeclarationorder a)+ adeclarationorder' = maybe maxBound adideclarationorder $ adeclarationinfo a -- | Search an account list by name. lookupAccount :: AccountName -> [Account] -> Maybe Account
Hledger/Data/Amount.hs view
@@ -75,6 +75,8 @@ maxprecisionwithpoint, setAmountPrecision, withPrecision,+ setFullPrecision,+ setMinimalPrecision, setAmountInternalPrecision, withInternalPrecision, setAmountDecimalPoint,@@ -124,7 +126,7 @@ ) where import Data.Char (isDigit)-import Data.Decimal (roundTo)+import Data.Decimal (roundTo, decimalPlaces, normalizeDecimal) import Data.Function (on) import Data.List import Data.Map (findWithDefault)@@ -166,7 +168,7 @@ -- | The empty simple amount. amount, nullamt :: Amount-amount = Amount{acommodity="", aquantity=0, aprice=NoPrice, astyle=amountstyle, amultiplier=False}+amount = Amount{acommodity="", aquantity=0, aprice=NoPrice, astyle=amountstyle, aismultiplier=False} nullamt = amount -- | A temporary value for parsed transactions which had no amount specified.@@ -277,6 +279,23 @@ -- | Set an amount's display precision, flipped. withPrecision :: Amount -> Int -> Amount withPrecision = flip setAmountPrecision++-- | Increase an amount's display precision, if necessary, enough so+-- that it will be shown exactly, with all significant decimal places+-- (excluding trailing zeros).+setFullPrecision :: Amount -> Amount+setFullPrecision a = setAmountPrecision p a+ where+ p = max displayprecision normalprecision+ displayprecision = asprecision $ astyle a+ normalprecision = fromIntegral $ decimalPlaces $ normalizeDecimal $ aquantity a++-- | Set an amount's display precision to just enough so that it will+-- be shown exactly, with all significant decimal places.+setMinimalPrecision :: Amount -> Amount+setMinimalPrecision a = setAmountPrecision normalprecision a+ where+ normalprecision = fromIntegral $ decimalPlaces $ normalizeDecimal $ aquantity a -- | Get a string representation of an amount for debugging, -- appropriate to the current debug level. 9 shows maximum detail.
Hledger/Data/Journal.hs view
@@ -1,5 +1,7 @@ {-# LANGUAGE Rank2Types #-}-{-# LANGUAGE StandaloneDeriving, OverloadedStrings #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE CPP #-} {-|@@ -67,6 +69,7 @@ journalCheckBalanceAssertions, journalNumberAndTieTransactions, journalUntieTransactions,+ journalModifyTransactions, -- * Tests samplejournal, tests_Journal,@@ -105,6 +108,7 @@ import Hledger.Data.Amount import Hledger.Data.Dates import Hledger.Data.Transaction+import Hledger.Data.TransactionModifier import Hledger.Data.Posting import Hledger.Query @@ -262,7 +266,7 @@ -- | Sorted unique account names declared by account directives in this journal. journalAccountNamesDeclared :: Journal -> [AccountName]-journalAccountNamesDeclared = nub . sort . jdeclaredaccounts+journalAccountNamesDeclared = nub . sort . map fst . jdeclaredaccounts -- | Sorted unique account names declared by account directives or posted to -- by transactions in this journal.@@ -555,6 +559,11 @@ journalUntieTransactions :: Transaction -> Transaction journalUntieTransactions t@Transaction{tpostings=ps} = t{tpostings=map (\p -> p{ptransaction=Nothing}) ps} +-- | Apply any transaction modifier rules in the journal +-- (adding automated postings to transactions, eg).+journalModifyTransactions :: Journal -> Journal+journalModifyTransactions j = j{ jtxns = modifyTransactions (jtxnmodifiers j) (jtxns j) }+ -- | Check any balance assertions in the journal and return an error -- message if any of them fail. journalCheckBalanceAssertions :: Journal -> Either String Journal@@ -569,54 +578,71 @@ -- | Check a posting's balance assertion and return an error if it -- fails. checkBalanceAssertion :: Posting -> MixedAmount -> Either String ()-checkBalanceAssertion p@Posting{ pbalanceassertion = Just ass } bal =- foldl' fold (Right ()) amts- where fold (Right _) cass = checkBalanceAssertionCommodity p cass bal- fold err _ = err- amt = baamount ass- amts = amt : if baexact ass- then map (\a -> a{ aquantity = 0 }) $ amounts $ filterMixedAmount (\a -> acommodity a /= assertedcomm) bal- else []- assertedcomm = acommodity amt+checkBalanceAssertion p@Posting{pbalanceassertion=Just (BalanceAssertion{baamount,baexact})} actualbal =+ foldl' f (Right ()) assertedamts+ where+ f (Right _) assertedamt = checkBalanceAssertionCommodity p assertedamt actualbal+ f err _ = err+ assertedamts = baamount : otheramts+ where+ assertedcomm = acommodity baamount+ otheramts | baexact = map (\a -> a{ aquantity = 0 }) $ amounts $ filterMixedAmount (\a -> acommodity a /= assertedcomm) actualbal+ | otherwise = [] checkBalanceAssertion _ _ = Right () +-- | Are the asserted balance and the actual balance+-- exactly equal (disregarding display precision) ?+-- The posting is used for creating an error message. checkBalanceAssertionCommodity :: Posting -> Amount -> MixedAmount -> Either String ()-checkBalanceAssertionCommodity p amt bal- | isReallyZeroAmount diff = Right ()- | True = Left err- where assertedcomm = acommodity amt- actualbal = fromMaybe nullamt $ find ((== assertedcomm) . acommodity) (amounts bal)- diff = amt - actualbal- diffplus | isNegativeAmount diff == False = "+"- | otherwise = ""- err = printf (unlines- [ "balance assertion error%s",- "after posting:",- "%s",- "balance assertion details:",- "date: %s",- "account: %s",- "commodity: %s",- "calculated: %s",- "asserted: %s (difference: %s)"- ])- (case ptransaction p of- Nothing -> ":" -- shouldn't happen- Just t -> printf " in %s:\nin transaction:\n%s"- (showGenericSourcePos pos) (chomp $ showTransaction t) :: String- where pos = baposition $ fromJust $ pbalanceassertion p)- (showPostingLine p)- (showDate $ postingDate p)- (T.unpack $ paccount p) -- XXX pack- assertedcomm- (showAmount actualbal)- (showAmount amt)- (diffplus ++ showAmount diff)+checkBalanceAssertionCommodity p assertedamt actualbal+ | pass = Right ()+ | otherwise = Left err+ where+ assertedcomm = acommodity assertedamt+ actualbalincommodity = fromMaybe nullamt $ find ((== assertedcomm) . acommodity) (amounts actualbal)+ pass =+ aquantity+ -- traceWith (("asserted:"++).showAmountDebug)+ assertedamt ==+ aquantity+ -- traceWith (("actual:"++).showAmountDebug)+ actualbalincommodity+ diff = aquantity assertedamt - aquantity actualbalincommodity+ err = printf (unlines+ [ "balance assertion: %s",+ "\nassertion details:",+ "date: %s",+ "account: %s",+ "commodity: %s",+ -- "display precision: %d",+ "calculated: %s", -- (at display precision: %s)",+ "asserted: %s", -- (at display precision: %s)",+ "difference: %s"+ ])+ (case ptransaction p of+ Nothing -> "?" -- shouldn't happen+ Just t -> printf "%s\ntransaction:\n%s"+ (showGenericSourcePos pos)+ (chomp $ showTransaction t)+ :: String+ where+ pos = baposition $ fromJust $ pbalanceassertion p+ )+ (showDate $ postingDate p)+ (T.unpack $ paccount p) -- XXX pack+ assertedcomm+ -- (asprecision $ astyle actualbalincommodity) -- should be the standard display precision I think+ (show $ aquantity actualbalincommodity)+ -- (showAmount actualbalincommodity)+ (show $ aquantity assertedamt)+ -- (showAmount assertedamt)+ (show diff) -- | Fill in any missing amounts and check that all journal transactions--- balance, or return an error message. This is done after parsing all--- amounts and applying canonical commodity styles, since balancing--- depends on display precision. Reports only the first error encountered.+-- balance and all balance assertions pass, or return an error message.+-- This is done after parsing all amounts and applying canonical+-- commodity styles, since balancing depends on display precision.+-- Reports only the first error encountered. journalBalanceTransactions :: Bool -> Journal -> Either String Journal journalBalanceTransactions assrt j = runST $ journalBalanceTransactionsST @@ -627,6 +653,8 @@ (fmap (\txns -> j{ jtxns = txns}) . getElems) -- summarise state -- | Helper used by 'journalBalanceTransactions' and 'journalCheckBalanceAssertions'.+-- Balances transactions, applies balance assignments, and checks balance assertions+-- at the same time. journalBalanceTransactionsST :: Bool -> Journal@@ -1063,7 +1091,7 @@ ["assets:bank:checking" `post` usd 1 ,"income:salary" `post` missingamt ],- tpreceding_comment_lines=""+ tprecedingcomment="" } , txnTieKnot $ Transaction {@@ -1080,7 +1108,7 @@ ["assets:bank:checking" `post` usd 1 ,"income:gifts" `post` missingamt ],- tpreceding_comment_lines=""+ tprecedingcomment="" } , txnTieKnot $ Transaction {@@ -1097,7 +1125,7 @@ ["assets:bank:saving" `post` usd 1 ,"assets:bank:checking" `post` usd (-1) ],- tpreceding_comment_lines=""+ tprecedingcomment="" } , txnTieKnot $ Transaction {@@ -1114,7 +1142,7 @@ ,"expenses:supplies" `post` usd 1 ,"assets:cash" `post` missingamt ],- tpreceding_comment_lines=""+ tprecedingcomment="" } , txnTieKnot $ Transaction {@@ -1130,7 +1158,7 @@ tpostings=["assets:bank:checking" `post` usd 1 ,"liabilities:debts" `post` usd (-1) ],- tpreceding_comment_lines=""+ tprecedingcomment="" } , txnTieKnot $ Transaction {@@ -1146,7 +1174,7 @@ tpostings=["liabilities:debts" `post` usd 1 ,"assets:bank:checking" `post` usd (-1) ],- tpreceding_comment_lines=""+ tprecedingcomment="" } ] }
Hledger/Data/Timeclock.hs view
@@ -95,7 +95,7 @@ tcomment = "", ttags = [], tpostings = ps,- tpreceding_comment_lines=""+ tprecedingcomment="" } itime = tldatetime i otime = tldatetime o
Hledger/Data/Transaction.hs view
@@ -35,7 +35,7 @@ showTransaction, showTransactionUnelided, showTransactionUnelidedOneLineAmounts,- showPostingLine,+ -- showPostingLine, showPostingLines, -- * GenericSourcePos sourceFilePath,@@ -90,7 +90,7 @@ tcomment="", ttags=[], tpostings=[],- tpreceding_comment_lines=""+ tprecedingcomment="" } {-|@@ -246,14 +246,17 @@ case renderCommentLines (pcomment p) of [] -> ("",[]) c:cs -> (c,cs) --- | Show a posting's status, account name and amount on one line. --- Used in balance assertion errors.-showPostingLine p =- indent $- if pstatus p == Cleared then "* " else "" ++- showAccountName Nothing (ptype p) (paccount p) ++- " " ++- showMixedAmountOneLine (pamount p)+-- | Render a posting, simply. Used in balance assertion errors.+-- showPostingLine p =+-- indent $+-- if pstatus p == Cleared then "* " else "" ++ -- XXX show !+-- showAccountName Nothing (ptype p) (paccount p) +++-- " " +++-- showMixedAmountOneLine (pamount p) +++-- assertion+-- where+-- -- XXX extract, handle ==+-- assertion = maybe "" ((" = " ++) . showAmountWithZeroCommodity . baamount) $ pbalanceassertion p -- | Render a posting, at the appropriate width for aligning with -- its siblings if any. Used by the rewrite command. @@ -689,10 +692,10 @@ ,tests "showTransaction" [ test "show a balanced transaction, eliding last amount" $- let t = Transaction 0 nullsourcepos (parsedate "2007/01/28") Nothing Unmarked "" "coopportunity" "" []+ let t = Transaction 0 "" nullsourcepos (parsedate "2007/01/28") Nothing Unmarked "" "coopportunity" "" [] [posting{paccount="expenses:food:groceries", pamount=Mixed [usd 47.18], ptransaction=Just t} ,posting{paccount="assets:checking", pamount=Mixed [usd (-47.18)], ptransaction=Just t}- ] ""+ ] in showTransaction t `is`@@ -704,10 +707,10 @@ ] ,test "show a balanced transaction, no eliding" $- (let t = Transaction 0 nullsourcepos (parsedate "2007/01/28") Nothing Unmarked "" "coopportunity" "" []+ (let t = Transaction 0 "" nullsourcepos (parsedate "2007/01/28") Nothing Unmarked "" "coopportunity" "" [] [posting{paccount="expenses:food:groceries", pamount=Mixed [usd 47.18], ptransaction=Just t} ,posting{paccount="assets:checking", pamount=Mixed [usd (-47.18)], ptransaction=Just t}- ] ""+ ] in showTransactionUnelided t) `is` (unlines@@ -720,10 +723,10 @@ -- document some cases that arise in debug/testing: ,test "show an unbalanced transaction, should not elide" $ (showTransaction- (txnTieKnot $ Transaction 0 nullsourcepos (parsedate "2007/01/28") Nothing Unmarked "" "coopportunity" "" []+ (txnTieKnot $ Transaction 0 "" nullsourcepos (parsedate "2007/01/28") Nothing Unmarked "" "coopportunity" "" [] [posting{paccount="expenses:food:groceries", pamount=Mixed [usd 47.18]} ,posting{paccount="assets:checking", pamount=Mixed [usd (-47.19)]}- ] ""))+ ])) `is` (unlines ["2007/01/28 coopportunity"@@ -734,9 +737,9 @@ ,test "show an unbalanced transaction with one posting, should not elide" $ (showTransaction- (txnTieKnot $ Transaction 0 nullsourcepos (parsedate "2007/01/28") Nothing Unmarked "" "coopportunity" "" []+ (txnTieKnot $ Transaction 0 "" nullsourcepos (parsedate "2007/01/28") Nothing Unmarked "" "coopportunity" "" [] [posting{paccount="expenses:food:groceries", pamount=Mixed [usd 47.18]}- ] ""))+ ])) `is` (unlines ["2007/01/28 coopportunity"@@ -746,9 +749,9 @@ ,test "show a transaction with one posting and a missing amount" $ (showTransaction- (txnTieKnot $ Transaction 0 nullsourcepos (parsedate "2007/01/28") Nothing Unmarked "" "coopportunity" "" []+ (txnTieKnot $ Transaction 0 "" nullsourcepos (parsedate "2007/01/28") Nothing Unmarked "" "coopportunity" "" [] [posting{paccount="expenses:food:groceries", pamount=missingmixedamt}- ] ""))+ ])) `is` (unlines ["2007/01/28 coopportunity"@@ -758,10 +761,10 @@ ,test "show a transaction with a priced commodityless amount" $ (showTransaction- (txnTieKnot $ Transaction 0 nullsourcepos (parsedate "2010/01/01") Nothing Unmarked "" "x" "" []+ (txnTieKnot $ Transaction 0 "" nullsourcepos (parsedate "2010/01/01") Nothing Unmarked "" "x" "" [] [posting{paccount="a", pamount=Mixed [num 1 `at` (usd 2 `withPrecision` 0)]} ,posting{paccount="b", pamount= missingmixedamt}- ] ""))+ ])) `is` (unlines ["2010/01/01 x"@@ -774,95 +777,95 @@ ,tests "balanceTransaction" [ test "detect unbalanced entry, sign error" $ (expectLeft $ balanceTransaction Nothing- (Transaction 0 nullsourcepos (parsedate "2007/01/28") Nothing Unmarked "" "test" "" []+ (Transaction 0 "" nullsourcepos (parsedate "2007/01/28") Nothing Unmarked "" "test" "" [] [posting{paccount="a", pamount=Mixed [usd 1]} ,posting{paccount="b", pamount=Mixed [usd 1]}- ] ""))+ ])) ,test "detect unbalanced entry, multiple missing amounts" $ (expectLeft $ balanceTransaction Nothing- (Transaction 0 nullsourcepos (parsedate "2007/01/28") Nothing Unmarked "" "test" "" []+ (Transaction 0 "" nullsourcepos (parsedate "2007/01/28") Nothing Unmarked "" "test" "" [] [posting{paccount="a", pamount=missingmixedamt} ,posting{paccount="b", pamount=missingmixedamt}- ] ""))+ ])) ,test "one missing amount is inferred" $ (pamount . last . tpostings <$> balanceTransaction Nothing- (Transaction 0 nullsourcepos (parsedate "2007/01/28") Nothing Unmarked "" "" "" []+ (Transaction 0 "" nullsourcepos (parsedate "2007/01/28") Nothing Unmarked "" "" "" [] [posting{paccount="a", pamount=Mixed [usd 1]} ,posting{paccount="b", pamount=missingmixedamt}- ] ""))+ ])) `is` Right (Mixed [usd (-1)]) ,test "conversion price is inferred" $ (pamount . head . tpostings <$> balanceTransaction Nothing- (Transaction 0 nullsourcepos (parsedate "2007/01/28") Nothing Unmarked "" "" "" []+ (Transaction 0 "" nullsourcepos (parsedate "2007/01/28") Nothing Unmarked "" "" "" [] [posting{paccount="a", pamount=Mixed [usd 1.35]} ,posting{paccount="b", pamount=Mixed [eur (-1)]}- ] ""))+ ])) `is` Right (Mixed [usd 1.35 @@ (eur 1 `withPrecision` maxprecision)]) ,test "balanceTransaction balances based on cost if there are unit prices" $ expectRight $- balanceTransaction Nothing (Transaction 0 nullsourcepos (parsedate "2011/01/01") Nothing Unmarked "" "" "" []+ balanceTransaction Nothing (Transaction 0 "" nullsourcepos (parsedate "2011/01/01") Nothing Unmarked "" "" "" [] [posting{paccount="a", pamount=Mixed [usd 1 `at` eur 2]} ,posting{paccount="a", pamount=Mixed [usd (-2) `at` eur 1]}- ] "")+ ]) ,test "balanceTransaction balances based on cost if there are total prices" $ expectRight $- balanceTransaction Nothing (Transaction 0 nullsourcepos (parsedate "2011/01/01") Nothing Unmarked "" "" "" []+ balanceTransaction Nothing (Transaction 0 "" nullsourcepos (parsedate "2011/01/01") Nothing Unmarked "" "" "" [] [posting{paccount="a", pamount=Mixed [usd 1 @@ eur 1]} ,posting{paccount="a", pamount=Mixed [usd (-2) @@ eur 1]}- ] "")+ ]) ] ,tests "isTransactionBalanced" [ test "detect balanced" $ expect $- isTransactionBalanced Nothing $ Transaction 0 nullsourcepos (parsedate "2009/01/01") Nothing Unmarked "" "a" "" []+ isTransactionBalanced Nothing $ Transaction 0 "" nullsourcepos (parsedate "2009/01/01") Nothing Unmarked "" "a" "" [] [posting{paccount="b", pamount=Mixed [usd 1.00]} ,posting{paccount="c", pamount=Mixed [usd (-1.00)]}- ] ""+ ] ,test "detect unbalanced" $ expect $- not $ isTransactionBalanced Nothing $ Transaction 0 nullsourcepos (parsedate "2009/01/01") Nothing Unmarked "" "a" "" []+ not $ isTransactionBalanced Nothing $ Transaction 0 "" nullsourcepos (parsedate "2009/01/01") Nothing Unmarked "" "a" "" [] [posting{paccount="b", pamount=Mixed [usd 1.00]} ,posting{paccount="c", pamount=Mixed [usd (-1.01)]}- ] ""+ ] ,test "detect unbalanced, one posting" $ expect $- not $ isTransactionBalanced Nothing $ Transaction 0 nullsourcepos (parsedate "2009/01/01") Nothing Unmarked "" "a" "" []+ not $ isTransactionBalanced Nothing $ Transaction 0 "" nullsourcepos (parsedate "2009/01/01") Nothing Unmarked "" "a" "" [] [posting{paccount="b", pamount=Mixed [usd 1.00]}- ] ""+ ] ,test "one zero posting is considered balanced for now" $ expect $- isTransactionBalanced Nothing $ Transaction 0 nullsourcepos (parsedate "2009/01/01") Nothing Unmarked "" "a" "" []+ isTransactionBalanced Nothing $ Transaction 0 "" nullsourcepos (parsedate "2009/01/01") Nothing Unmarked "" "a" "" [] [posting{paccount="b", pamount=Mixed [usd 0]}- ] ""+ ] ,test "virtual postings don't need to balance" $ expect $- isTransactionBalanced Nothing $ Transaction 0 nullsourcepos (parsedate "2009/01/01") Nothing Unmarked "" "a" "" []+ isTransactionBalanced Nothing $ Transaction 0 "" nullsourcepos (parsedate "2009/01/01") Nothing Unmarked "" "a" "" [] [posting{paccount="b", pamount=Mixed [usd 1.00]} ,posting{paccount="c", pamount=Mixed [usd (-1.00)]} ,posting{paccount="d", pamount=Mixed [usd 100], ptype=VirtualPosting}- ] ""+ ] ,test "balanced virtual postings need to balance among themselves" $ expect $- not $ isTransactionBalanced Nothing $ Transaction 0 nullsourcepos (parsedate "2009/01/01") Nothing Unmarked "" "a" "" []+ not $ isTransactionBalanced Nothing $ Transaction 0 "" nullsourcepos (parsedate "2009/01/01") Nothing Unmarked "" "a" "" [] [posting{paccount="b", pamount=Mixed [usd 1.00]} ,posting{paccount="c", pamount=Mixed [usd (-1.00)]} ,posting{paccount="d", pamount=Mixed [usd 100], ptype=BalancedVirtualPosting}- ] ""+ ] ,test "balanced virtual postings need to balance among themselves (2)" $ expect $- isTransactionBalanced Nothing $ Transaction 0 nullsourcepos (parsedate "2009/01/01") Nothing Unmarked "" "a" "" []+ isTransactionBalanced Nothing $ Transaction 0 "" nullsourcepos (parsedate "2009/01/01") Nothing Unmarked "" "a" "" [] [posting{paccount="b", pamount=Mixed [usd 1.00]} ,posting{paccount="c", pamount=Mixed [usd (-1.00)]} ,posting{paccount="d", pamount=Mixed [usd 100], ptype=BalancedVirtualPosting} ,posting{paccount="3", pamount=Mixed [usd (-100)], ptype=BalancedVirtualPosting}- ] ""+ ] ]
Hledger/Data/TransactionModifier.hs view
@@ -8,7 +8,7 @@ -} module Hledger.Data.TransactionModifier (- transactionModifierToFunction+ modifyTransactions ) where @@ -32,6 +32,12 @@ -- >>> import Hledger.Data.Transaction -- >>> import Hledger.Data.Journal +-- | Apply all the given transaction modifiers, in turn, to each transaction.+modifyTransactions :: [TransactionModifier] -> [Transaction] -> [Transaction]+modifyTransactions tmods ts = map applymods ts+ where+ applymods = foldr (flip (.) . transactionModifierToFunction) id tmods+ -- | Converts a 'TransactionModifier' to a 'Transaction'-transforming function, -- which applies the modification(s) specified by the TransactionModifier. -- Currently this means adding automated postings when certain other postings are present.@@ -47,7 +53,7 @@ -- 0000/01/01 -- ping $1.00 -- <BLANKLINE>--- >>> putStr $ showTransaction $ transactionModifierToFunction (TransactionModifier "ping" ["pong" `post` amount{amultiplier=True, aquantity=3}]) nulltransaction{tpostings=["ping" `post` usd 2]}+-- >>> putStr $ showTransaction $ transactionModifierToFunction (TransactionModifier "ping" ["pong" `post` amount{aismultiplier=True, aquantity=3}]) nulltransaction{tpostings=["ping" `post` usd 2]} -- 0000/01/01 -- ping $2.00 -- pong $6.00@@ -111,7 +117,7 @@ postingRuleMultiplier :: TMPostingRule -> Maybe Quantity postingRuleMultiplier p = case amounts $ pamount p of- [a] | amultiplier a -> Just $ aquantity a+ [a] | aismultiplier a -> Just $ aquantity a _ -> Nothing renderPostingCommentDates :: Posting -> Posting
Hledger/Data/Types.hs view
@@ -201,12 +201,12 @@ instance NFData Commodity data Amount = Amount {- acommodity :: CommoditySymbol,- aquantity :: Quantity,- aprice :: Price, -- ^ the (fixed) price for this amount, if any+ acommodity :: CommoditySymbol, -- commodity symbol, or special value "AUTO"+ aquantity :: Quantity, -- numeric quantity, or zero in case of "AUTO"+ aismultiplier :: Bool, -- ^ kludge: a flag marking this amount and posting as a multiplier+ -- in a TMPostingRule. In a regular Posting, should always be false. astyle :: AmountStyle,- amultiplier :: Bool -- ^ kludge: a flag marking this amount and posting as a multiplier- -- in a TMPostingRule. In a regular Posting, should always be false.+ aprice :: Price -- ^ the (fixed, transaction-specific) price for this amount, if any } deriving (Eq,Ord,Typeable,Data,Generic,Show) instance NFData Amount@@ -302,8 +302,9 @@ -- prevents the constraint ‘(Data p0)’ from being solved. -- Probable fix: use a type annotation to specify what ‘p0’ should be. data Transaction = Transaction {- tindex :: Integer, -- ^ this transaction's 1-based position in the input stream, or 0 when not available- tsourcepos :: GenericSourcePos,+ tindex :: Integer, -- ^ this transaction's 1-based position in the transaction stream, or 0 when not available+ tprecedingcomment :: Text, -- ^ any comment lines immediately preceding this transaction+ tsourcepos :: GenericSourcePos, -- ^ the file position where the date starts tdate :: Day, tdate2 :: Maybe Day, tstatus :: Status,@@ -311,8 +312,7 @@ tdescription :: Text, tcomment :: Text, -- ^ this transaction's comment lines, as a single non-indented multi-line string ttags :: [Tag], -- ^ tag names and values, extracted from the comment- tpostings :: [Posting], -- ^ this transaction's postings- tpreceding_comment_lines :: Text -- ^ any comment lines immediately preceding this transaction+ tpostings :: [Posting] -- ^ this transaction's postings } deriving (Eq,Typeable,Data,Generic,Show) instance NFData Transaction@@ -336,7 +336,7 @@ -- | A transaction modifier transformation, which adds an extra posting -- to the matched posting's transaction.--- Can be like a regular posting, or the amount can have the amultiplier flag set,+-- Can be like a regular posting, or the amount can have the aismultiplier flag set, -- indicating that it's a multiplier for the matched posting's amount. type TMPostingRule = Posting @@ -410,7 +410,7 @@ ,jparsetimeclockentries :: [TimeclockEntry] -- ^ timeclock sessions which have not been clocked out ,jincludefilestack :: [FilePath] -- principal data- ,jdeclaredaccounts :: [AccountName] -- ^ Accounts declared by account directives, in parse order (after journal finalisation) + ,jdeclaredaccounts :: [(AccountName,AccountDeclarationInfo)] -- ^ Accounts declared by account directives, in parse order (after journal finalisation) ,jdeclaredaccounttypes :: M.Map AccountType [AccountName] -- ^ Accounts whose type has been declared in account directives (usually 5 top-level accounts) ,jcommodities :: M.Map CommoditySymbol Commodity -- ^ commodities and formats declared by commodity directives ,jinferredcommodities :: M.Map CommoditySymbol AmountStyle -- ^ commodities and formats inferred from journal amounts TODO misnamed - jusedstyles@@ -439,18 +439,36 @@ -- The --output-format option selects one of these for output. type StorageFormat = String --- | An account, with name, balances and links to parent/subaccounts--- which let you walk up or down the account tree.+-- | Extra information about an account that can be derived from+-- its account directive (and the other account directives).+data AccountDeclarationInfo = AccountDeclarationInfo {+ adicomment :: Text -- ^ any comment lines following an account directive for this account+ ,aditags :: [Tag] -- ^ tags extracted from the account comment, if any+ ,adideclarationorder :: Int -- ^ the order in which this account was declared,+ -- relative to other account declarations, during parsing (1..)+} deriving (Eq,Show,Data,Generic)++instance NFData AccountDeclarationInfo++nullaccountdeclarationinfo = AccountDeclarationInfo {+ adicomment = ""+ ,aditags = []+ ,adideclarationorder = 0+}++-- | An account, with its balances, parent/subaccount relationships, etc.+-- Only the name is required; the other fields are added when needed. data Account = Account {- aname :: AccountName, -- ^ this account's full name- adeclarationorder :: Maybe Int , -- ^ the relative position of this account's account directive, if any. Normally a natural number. - aebalance :: MixedAmount, -- ^ this account's balance, excluding subaccounts- asubs :: [Account], -- ^ sub-accounts- anumpostings :: Int, -- ^ number of postings to this account- -- derived from the above :- aibalance :: MixedAmount, -- ^ this account's balance, including subaccounts- aparent :: Maybe Account, -- ^ parent account- aboring :: Bool -- ^ used in the accounts report to label elidable parents+ aname :: AccountName -- ^ this account's full name+ ,adeclarationinfo :: Maybe AccountDeclarationInfo -- ^ optional extra info from account directives+ -- relationships in the tree+ ,asubs :: [Account] -- ^ this account's sub-accounts+ ,aparent :: Maybe Account -- ^ parent account+ ,aboring :: Bool -- ^ used in the accounts report to label elidable parents+ -- balance information+ ,anumpostings :: Int -- ^ the number of postings to this account+ ,aebalance :: MixedAmount -- ^ this account's balance, excluding subaccounts+ ,aibalance :: MixedAmount -- ^ this account's balance, including subaccounts } deriving (Typeable, Data, Generic) -- | Whether an account's balance is normally a positive number (in
Hledger/Read.hs view
@@ -171,7 +171,7 @@ -- directives & aliases do not affect subsequent sibling or parent files. -- They do affect included child files though. -- Also the final parse state saved in the Journal does span all files.-readJournalFiles :: InputOpts -> [FilePath] -> IO (Either String Journal)+readJournalFiles :: InputOpts -> [PrefixedFilePath] -> IO (Either String Journal) readJournalFiles iopts = (right mconcat1 . sequence <$>) . mapM (readJournalFile iopts) where
Hledger/Read/Common.hs view
@@ -33,7 +33,6 @@ rejp, genericSourcePos, journalSourcePos,- applyTransactionModifiers, parseAndFinaliseJournal, parseAndFinaliseJournal', setYear,@@ -42,7 +41,6 @@ getDefaultCommodityAndStyle, getDefaultAmountStyle, getAmountStyle,- pushDeclaredAccount, addDeclaredAccountType, pushParentAccount, popParentAccount,@@ -229,14 +227,6 @@ | otherwise = unPos $ sourceLine p' -- might be at end of file withat last new-line --- | Apply any transaction modifier rules in the journal --- (adding automated postings to transactions, eg).-applyTransactionModifiers :: Journal -> Journal-applyTransactionModifiers j = j { jtxns = map applyallmodifiers $ jtxns j }- where- applyallmodifiers = - foldr (flip (.) . transactionModifierToFunction) id (jtxnmodifiers j)- -- | Given a megaparsec ParsedJournal parser, input options, file -- path and file content: parse and post-process a Journal, or give an error. parseAndFinaliseJournal :: ErroringJournalParser IO ParsedJournal -> InputOpts@@ -264,14 +254,24 @@ -- time. If we are only running once, we reorder and follow -- the options for checking assertions. let fj = if auto_ iopts && (not . null . jtxnmodifiers) pj- then applyTransactionModifiers <$>- (journalBalanceTransactions False $- journalReverse $- journalApplyCommodityStyles pj) >>=- (\j -> journalBalanceTransactions (not $ ignore_assertions_ iopts) $- journalAddFile (f, txt) $- journalSetLastReadTime t $- j)++ -- transaction modifiers are active+ then+ -- first pass, doing most of the work+ (+ (journalModifyTransactions <$>) $ -- add auto postings after balancing ? #893b fails+ journalBalanceTransactions False $+ -- journalModifyTransactions <$> -- add auto postings before balancing ? probably #893a, #928, #938 fail+ journalReverse $+ journalAddFile (f, txt) $+ journalApplyCommodityStyles pj)+ -- second pass, checking balance assertions+ >>= (\j ->+ journalBalanceTransactions (not $ ignore_assertions_ iopts) $+ journalSetLastReadTime t $+ j)++ -- transaction modifiers are not active else journalBalanceTransactions (not $ ignore_assertions_ iopts) $ journalReverse $ journalAddFile (f, txt) $@@ -283,6 +283,8 @@ Right j -> return j Left e -> throwError e +-- Like parseAndFinaliseJournal but takes a (non-Erroring) JournalParser.+-- Used for timeclock/timedot. XXX let them use parseAndFinaliseJournal instead parseAndFinaliseJournal' :: JournalParser IO ParsedJournal -> InputOpts -> FilePath -> Text -> ExceptT String IO Journal parseAndFinaliseJournal' parser iopts f txt = do@@ -303,7 +305,7 @@ -- time. If we are only running once, we reorder and follow the -- options for checking assertions. let fj = if auto_ iopts && (not . null . jtxnmodifiers) pj- then applyTransactionModifiers <$>+ then journalModifyTransactions <$> (journalBalanceTransactions False $ journalReverse $ journalApplyCommodityStyles pj) >>=@@ -352,9 +354,6 @@ let effectiveStyle = listToMaybe $ catMaybes [specificStyle, defaultStyle] return effectiveStyle -pushDeclaredAccount :: AccountName -> JournalParser m ()-pushDeclaredAccount acct = modify' (\j -> j{jdeclaredaccounts = acct : jdeclaredaccounts j})- addDeclaredAccountType :: AccountName -> AccountType -> JournalParser m () addDeclaredAccountType acct atype = modify' (\j -> j{jdeclaredaccounttypes = M.insertWith (++) atype [acct] (jdeclaredaccounttypes j)})@@ -630,7 +629,7 @@ let numRegion = (offBeforeNum, offAfterNum) (q,prec,mdec,mgrps) <- lift $ interpretNumber numRegion suggestedStyle ambiguousRawNum mExponent let s = amountstyle{ascommodityside=L, ascommodityspaced=commodityspaced, asprecision=prec, asdecimalpoint=mdec, asdigitgroups=mgrps}- return $ Amount c (sign (sign2 q)) NoPrice s mult+ return $ nullamt{acommodity=c, aquantity=sign (sign2 q), aismultiplier=mult, astyle=s, aprice=NoPrice} rightornosymbolamountp :: Bool -> (Decimal -> Decimal) -> JournalParser m Amount rightornosymbolamountp mult sign = label "amount" $ do@@ -646,7 +645,7 @@ suggestedStyle <- getAmountStyle c (q,prec,mdec,mgrps) <- lift $ interpretNumber numRegion suggestedStyle ambiguousRawNum mExponent let s = amountstyle{ascommodityside=R, ascommodityspaced=commodityspaced, asprecision=prec, asdecimalpoint=mdec, asdigitgroups=mgrps}- return $ Amount c (sign q) NoPrice s mult+ return $ nullamt{acommodity=c, aquantity=sign q, aismultiplier=mult, astyle=s, aprice=NoPrice} -- no symbol amount Nothing -> do suggestedStyle <- getDefaultAmountStyle@@ -657,7 +656,7 @@ let (c,s) = case (mult, defcs) of (False, Just (defc,defs)) -> (defc, defs{asprecision=max (asprecision defs) prec}) _ -> ("", amountstyle{asprecision=prec, asdecimalpoint=mdec, asdigitgroups=mgrps})- return $ Amount c (sign q) NoPrice s mult+ return $ nullamt{acommodity=c, aquantity=sign q, aismultiplier=mult, astyle=s, aprice=NoPrice} -- For reducing code duplication. Doesn't parse anything. Has the type -- of a parser only in order to throw parse errors (for convenience).@@ -721,7 +720,7 @@ priceConstructor <- char '@' *> pure TotalPrice <|> pure UnitPrice lift (skipMany spacenonewline)- priceAmount <- amountwithoutpricep <?> "amount (as a price)"+ priceAmount <- amountwithoutpricep <?> "unpriced amount (specifying a price)" pure $ priceConstructor priceAmount @@ -731,14 +730,19 @@ char '=' exact <- optional $ try $ char '=' lift (skipMany spacenonewline)- a <- amountp <?> "amount (for a balance assertion or assignment)" -- XXX should restrict to a simple amount+ -- this amount can have a price; balance assertions ignore it,+ -- but balance assignments will use it+ a <- amountp <?> "amount (for a balance assertion or assignment)" return BalanceAssertion { baamount = a , baexact = isJust exact , baposition = sourcepos } --- http://ledger-cli.org/3.0/doc/ledger3.html#Fixing-Lot-Prices+-- Parse a Ledger-style fixed lot price: {=PRICE}+-- https://www.ledger-cli.org/3.0/doc/ledger3.html#Fixing-Lot-Prices .+-- Currently we ignore these (hledger's @ PRICE is equivalent),+-- and we don't parse a Ledger-style {PRICE} (equivalent to Ledger's @ PRICE). fixedlotpricep :: JournalParser m (Maybe Amount) fixedlotpricep = optional $ do try $ do@@ -747,7 +751,7 @@ lift (skipMany spacenonewline) char '=' lift (skipMany spacenonewline)- a <- amountp -- XXX should restrict to a simple amount+ a <- amountwithoutpricep <?> "unpriced amount (for an ignored ledger-style fixed lot price)" lift (skipMany spacenonewline) char '}' return a@@ -1297,7 +1301,7 @@ tests_Common = tests "Common" [ - tests "amountp" [+ tests "amountp" [ test "basic" $ expectParseEq amountp "$47.18" (usd 47.18) ,test "ends with decimal mark" $ expectParseEq amountp "$1." (usd 1 `withPrecision` 0) ,test "unit price" $ expectParseEq amountp "$10 @ €0.5"
Hledger/Read/CsvReader.hs view
@@ -746,7 +746,7 @@ tcode = T.pack code, tdescription = T.pack description, tcomment = T.pack comment,- tpreceding_comment_lines = T.pack precomment,+ tprecedingcomment = T.pack precomment, tpostings = [posting {paccount=account1, pamount=amount1, ptransaction=Just t, pbalanceassertion=toAssertion <$> balance} ,posting {paccount=account2, pamount=amount2, ptransaction=Just t}
Hledger/Read/JournalReader.hs view
@@ -66,9 +66,8 @@ import "base-compat-batteries" Prelude.Compat hiding (readFile) import qualified Control.Exception as C import Control.Monad-import Control.Monad.Except (ExceptT(..))+import Control.Monad.Except (ExceptT(..), runExceptT) import Control.Monad.State.Strict-import Data.Maybe import qualified Data.Map.Strict as M import Data.Text (Text) import Data.String@@ -253,36 +252,81 @@ Right res -> pure res Left errMsg -> fail errMsg +-- Parse an account directive, adding its info to the journal's+-- list of account declarations. accountdirectivep :: JournalParser m () accountdirectivep = do+ off <- getOffset -- XXX figure out a more precise position later+ string "account" lift (skipSome spacenonewline)+ -- the account name, possibly modified by preceding alias or apply account directives acct <- modifiedaccountnamep- -- and maybe something else after two or more spaces ?- matype :: Maybe AccountType <- lift $ fmap (fromMaybe Nothing) $ optional $ try $ do++ -- maybe an account type code (ALERX) after two or more spaces+ -- XXX added in 1.11, deprecated in 1.13, remove in 1.14+ mtypecode :: Maybe Char <- lift $ optional $ try $ do skipSome spacenonewline -- at least one more space in addition to the one consumed by modifiedaccountp - choice [- -- a numeric account code, as supported in 1.9-1.10 ? currently ignored- some digitChar >> return Nothing- -- a letter account type code (ALERX), as added in 1.11 ?- ,char 'A' >> return (Just Asset) - ,char 'L' >> return (Just Liability) - ,char 'E' >> return (Just Equity) - ,char 'R' >> return (Just Revenue) - ,char 'X' >> return (Just Expense) - ]- -- and maybe a comment on this and/or following lines ? (ignore for now)- (_cmt, _tags) <- lift transactioncommentp- -- and maybe Ledger-style subdirectives ? (ignore)+ choice $ map char "ALERX"++ -- maybe a comment, on this and/or following lines+ (cmt, tags) <- lift transactioncommentp+ + -- maybe Ledger-style subdirectives (ignored) skipMany indentedlinep + -- an account type may have been set by account type code or a tag;+ -- the latter takes precedence+ let+ mtypecode' :: Maybe Text = maybe+ (T.singleton <$> mtypecode)+ Just+ $ lookup accountTypeTagName tags+ metype = parseAccountTypeCode <$> mtypecode'+ -- update the journal- case matype of- Nothing -> return ()- Just atype -> addDeclaredAccountType acct atype- pushDeclaredAccount acct+ addAccountDeclaration (acct, cmt, tags)+ case metype of+ Nothing -> return ()+ Just (Right t) -> addDeclaredAccountType acct t+ Just (Left err) -> customFailure $ parseErrorAt off err +-- The special tag used for declaring account type. XXX change to "class" ?+accountTypeTagName = "type"++parseAccountTypeCode :: Text -> Either String AccountType+parseAccountTypeCode s =+ case T.toLower s of+ "asset" -> Right Asset+ "a" -> Right Asset+ "liability" -> Right Liability+ "l" -> Right Liability+ "equity" -> Right Equity+ "e" -> Right Equity+ "revenue" -> Right Revenue+ "r" -> Right Revenue+ "expense" -> Right Expense+ "x" -> Right Expense+ _ -> Left err+ where+ err = "invalid account type code "++T.unpack s++", should be one of " +++ (intercalate ", " $ ["A","L","E","R","X","ASSET","LIABILITY","EQUITY","REVENUE","EXPENSE"])++-- Add an account declaration to the journal, auto-numbering it.+addAccountDeclaration :: (AccountName,Text,[Tag]) -> JournalParser m ()+addAccountDeclaration (a,cmt,tags) =+ modify' (\j ->+ let+ decls = jdeclaredaccounts j+ d = (a, nullaccountdeclarationinfo{+ adicomment = cmt+ ,aditags = tags+ ,adideclarationorder = length decls + 1+ })+ in+ j{jdeclaredaccounts = d:decls})+ indentedlinep :: JournalParser m String indentedlinep = lift (skipSome spacenonewline) >> (rstrip <$> lift restofline) @@ -525,23 +569,18 @@ customFailure $ parseErrorAtRegion offset1 offset2 $ "remainder of period expression cannot be parsed" <> "\nperhaps you need to terminate the period expression with a double space?"+ <> "\na double space is required between period expression and description/comment" pure pexp -- In periodic transactions, the period expression has an additional constraint: case checkPeriodicTransactionStartDate interval span periodtxt of Just e -> customFailure $ parseErrorAt off e Nothing -> pure ()- -- The line can end here, or it can continue with one or more spaces- -- and then zero or more of the following fields. A bit awkward.- (status, code, description, (comment, tags)) <- lift $- (<|>) (eolof >> return (Unmarked, "", "", ("", []))) $ do- skipSome spacenonewline- s <- statusp- c <- codep- desc <- T.strip <$> descriptionp- (cmt, ts) <- transactioncommentp- return (s,c,desc,(cmt,ts))-+ + status <- lift statusp <?> "cleared status"+ code <- lift codep <?> "transaction code"+ description <- lift $ T.strip <$> descriptionp+ (comment, tags) <- lift transactioncommentp -- next lines; use same year determined above postings <- postingsp (Just $ first3 $ toGregorian refdate) @@ -573,7 +612,7 @@ postings <- postingsp (Just year) endpos <- getSourcePos let sourcepos = journalSourcePos startpos endpos- return $ txnTieKnot $ Transaction 0 sourcepos date edate status code description comment tags postings ""+ return $ txnTieKnot $ Transaction 0 "" sourcepos date edate status code description comment tags postings --- ** postings @@ -693,6 +732,19 @@ ,ptcomment = "" } + ,test "Just date, no description" $ expectParseEq periodictransactionp+ "~ 2019-01-04\n"+ nullperiodictransaction {+ ptperiodexpr = "2019-01-04"+ ,ptinterval = NoInterval+ ,ptspan = DateSpan (Just $ fromGregorian 2019 1 4) (Just $ fromGregorian 2019 1 5)+ ,ptdescription = ""+ ,ptcomment = ""+ }++ ,test "Just date, no description + empty transaction comment" $ expectParse periodictransactionp+ "~ 2019-01-04\n ;\n a 1\n b\n"+ ] ,tests "postingp" [@@ -760,7 +812,7 @@ ]) nulltransaction{ tsourcepos=JournalSourcePos "" (1,7), -- XXX why 7 here ?- tpreceding_comment_lines="",+ tprecedingcomment="", tdate=fromGregorian 2012 5 14, tdate2=Just $ fromGregorian 2012 5 15, tstatus=Unmarked,@@ -800,7 +852,16 @@ ," b" ," " ]- ++ ,test "transactionp parses an empty transaction comment following whitespace line" $+ expect $ isRight $ rjp transactionp $ T.unlines+ ["2012/1/1"+ ," ;"+ ," a 1"+ ," b"+ ," "+ ]+ ,test "comments everywhere, two postings parsed" $ expectParseEqOn transactionp (T.unlines@@ -824,11 +885,16 @@ ] ,test "accountdirectivep" $ do- test "with-comment" $ expectParse accountdirectivep "account a:b ; a comment\n"+ test "with-comment" $ expectParse accountdirectivep "account a:b ; a comment\n" test "does-not-support-!" $ expectParseError accountdirectivep "!account a:b\n" ""- test "account-sort-code" $ expectParse accountdirectivep "account a:b 1000\n"- test "account-type-code" $ expectParse accountdirectivep "account a:b A\n"- test "account-type-tag" $ expectParse accountdirectivep "account a:b ; type:asset\n"+ test "account-type-code" $ expectParse accountdirectivep "account a:b A\n"+ test "account-type-tag" $ expectParseStateOn accountdirectivep "account a:b ; type:asset\n"+ jdeclaredaccounts+ [("a:b", AccountDeclarationInfo{adicomment = "type:asset\n"+ ,aditags = [("type","asset")]+ ,adideclarationorder = 1+ })+ ] ,test "commodityconversiondirectivep" $ do expectParse commodityconversiondirectivep "C 1h = $50.00\n"@@ -868,5 +934,13 @@ ,tests "journalp" [ test "empty file" $ expectParseEqE journalp "" nulljournal ]++ -- these are defined here rather than in Common so they can use journalp+ ,tests "parseAndFinaliseJournal" [+ test "basic" $ do+ ej <- io $ runExceptT $ parseAndFinaliseJournal journalp definputopts "" "2019-1-1\n"+ let Right j = ej+ expectEqPP [""] $ journalFilePaths j+ ] ]
Hledger/Reports/BalanceReport.hs view
@@ -198,7 +198,7 @@ [posting {paccount="assets:bank:checking", pamount=Mixed [usd 1]} ,posting {paccount="income:salary", pamount=missingmixedamt} ],- tpreceding_comment_lines=""+ tprecedingcomment="" } ] }
Hledger/Reports/BudgetReport.hs view
@@ -64,12 +64,18 @@ -- actual balance changes from the regular transactions, -- and compare these to get a 'BudgetReport'. -- Unbudgeted accounts may be hidden or renamed (see budgetRollup).-budgetReport :: ReportOpts -> Bool -> Bool -> DateSpan -> Day -> Journal -> BudgetReport-budgetReport ropts assrt showunbudgeted reportspan d j =+budgetReport :: ReportOpts -> Bool -> DateSpan -> Day -> Journal -> BudgetReport+budgetReport ropts' assrt reportspan d j = let+ -- Budget report demands ALTree mode to ensure subaccounts and subaccount budgets are properly handled+ -- and that reports with and without --empty make sense when compared side by side+ ropts = ropts' { accountlistmode_ = ALTree }+ showunbudgeted = empty_ ropts q = queryFromOpts d ropts budgetedaccts = dbg2 "budgetedacctsinperiod" $+ nub $ + concatMap expandAccountName $ accountNamesFromPostings $ concatMap tpostings $ concatMap (flip runPeriodicTransaction reportspan) $ @@ -77,7 +83,7 @@ actualj = dbg1 "actualj" $ budgetRollUp budgetedaccts showunbudgeted j budgetj = dbg1 "budgetj" $ budgetJournal assrt ropts reportspan j actualreport@(MultiBalanceReport (actualspans, _, _)) = dbg1 "actualreport" $ multiBalanceReport ropts q actualj- budgetgoalreport@(MultiBalanceReport (_, budgetgoalitems, budgetgoaltotals)) = dbg1 "budgetgoalreport" $ multiBalanceReport ropts q budgetj+ budgetgoalreport@(MultiBalanceReport (_, budgetgoalitems, budgetgoaltotals)) = dbg1 "budgetgoalreport" $ multiBalanceReport (ropts{empty_=True}) q budgetj budgetgoalreport' -- If no interval is specified: -- budgetgoalreport's span might be shorter actualreport's due to periodic txns; @@ -157,7 +163,7 @@ -- -- 2. subaccounts with no budget goal are merged with their closest parent account -- with a budget goal, so that only budgeted accounts are shown. --- This can be disabled by --show-unbudgeted.+-- This can be disabled by --empty. -- budgetRollUp :: [AccountName] -> Bool -> Journal -> Journal budgetRollUp budgetedaccts showunbudgeted j = j { jtxns = remapTxn <$> jtxns j }@@ -262,18 +268,24 @@ -- | Render a budget report as plain text suitable for console output. budgetReportAsText :: ReportOpts -> BudgetReport -> String-budgetReportAsText ropts budgetr =+budgetReportAsText ropts budgetr@(PeriodicReport ( _, rows, _)) = printf "Budget performance in %s:\n\n" (showDateSpan $ budgetReportSpan budgetr) ++ - tableAsText ropts showcell (budgetReportAsTable ropts budgetr)+ tableAsText ropts showcell (maybetranspose $ budgetReportAsTable ropts budgetr) where+ actualwidth =+ maximum [ maybe 0 (length . showMixedAmountOneLineWithoutPrice) amt+ | (_, _, _, amtandgoals, _, _) <- rows+ , (amt, _) <- amtandgoals ]+ budgetwidth =+ maximum [ maybe 0 (length . showMixedAmountOneLineWithoutPrice) goal+ | (_, _, _, amtandgoals, _, _) <- rows+ , (_, goal) <- amtandgoals ] -- XXX lay out actual, percentage and/or goal in the single table cell for now, should probably use separate cells showcell :: (Maybe Change, Maybe BudgetGoal) -> String showcell (mactual, mbudget) = actualstr ++ " " ++ budgetstr where- actualwidth = 7 percentwidth = 4- budgetwidth = 5 actual = fromMaybe 0 mactual actualstr = printf ("%"++show actualwidth++"s") (showamt actual) budgetstr = case mbudget of@@ -307,6 +319,9 @@ -- don't show the budget amount in color, it messes up alignment showbudgetamt = showMixedAmountOneLineWithoutPrice++ maybetranspose | transpose_ ropts = \(Table rh ch vals) -> Table ch rh (transpose vals)+ | otherwise = id -- | Build a 'Table' from a multi-column balance report. budgetReportAsTable :: ReportOpts -> BudgetReport -> Table String String (Maybe MixedAmount, Maybe MixedAmount)
Hledger/Reports/MultiBalanceReports.hs view
@@ -314,7 +314,7 @@ (map showw aitems) `is` (map showw eitems) ((\(_, b, _) -> showMixedAmountDebug b) atotal) `is` (showMixedAmountDebug etotal) -- we only check the sum of the totals usd0 = usd 0- amount0 = Amount {acommodity="$", aquantity=0, aprice=NoPrice, astyle=AmountStyle {ascommodityside = L, ascommodityspaced = False, asprecision = 2, asdecimalpoint = Just '.', asdigitgroups = Nothing}, amultiplier=False}+ amount0 = Amount {acommodity="$", aquantity=0, aprice=NoPrice, astyle=AmountStyle {ascommodityside = L, ascommodityspaced = False, asprecision = 2, asdecimalpoint = Just '.', asdigitgroups = Nothing}, aismultiplier=False} in tests "multiBalanceReport" [ test "null journal" $
Hledger/Reports/ReportOptions.hs view
@@ -112,6 +112,7 @@ -- normally positive for a more conventional display. ,color_ :: Bool ,forecast_ :: Bool+ ,transpose_ :: Bool } deriving (Show, Data, Typeable) instance Default ReportOpts where def = defreportopts@@ -144,6 +145,7 @@ def def def+ def rawOptsToReportOpts :: RawOpts -> IO ReportOpts rawOptsToReportOpts rawopts = checkReportOpts <$> do@@ -176,6 +178,7 @@ ,pretty_tables_ = boolopt "pretty-tables" rawopts' ,color_ = color ,forecast_ = boolopt "forecast" rawopts'+ ,transpose_ = boolopt "transpose" rawopts' } -- | Do extra validation of raw option values, raising an error if there's a problem.
Hledger/Utils.hs view
@@ -37,15 +37,19 @@ import Control.Monad (liftM, when) -- import Data.Char import Data.Default+import Data.FileEmbed (makeRelativeToProject, embedFile) import Data.List -- import Data.Maybe -- import Data.PPrint+import Data.String.Here (hereFile) import Data.Text (Text) import qualified Data.Text.IO as T import Data.Time.Clock import Data.Time.LocalTime -- import Data.Text (Text) -- import qualified Data.Text as T+import Language.Haskell.TH.Quote (QuasiQuoter(..))+import Language.Haskell.TH.Syntax (Q, Exp) import System.Directory (getHomeDirectory) import System.FilePath((</>), isRelative) import System.IO@@ -220,6 +224,18 @@ mapM' :: Monad f => (a -> f b) -> [a] -> f [b] mapM' f = sequence' . map f +-- | Like embedFile, but takes a path relative to the package directory.+-- Similar to hereFileRelative ?+embedFileRelative :: FilePath -> Q Exp+embedFileRelative f = makeRelativeToProject f >>= embedFile++-- | Like hereFile, but takes a path relative to the package directory.+-- Similar to embedFileRelative ?+hereFileRelative :: FilePath -> Q Exp+hereFileRelative f = makeRelativeToProject f >>= hereFileExp+ where+ QuasiQuoter{quoteExp=hereFileExp} = hereFile+ tests_Utils = tests "Utils" [ tests_Text ]
Hledger/Utils/Test.hs view
@@ -23,12 +23,13 @@ ,expectParseEqE ,expectParseEqOn ,expectParseEqOnE+ ,expectParseStateOn ) where import Control.Exception import Control.Monad.Except (ExceptT, runExceptT)-import Control.Monad.State.Strict (StateT, evalStateT)+import Control.Monad.State.Strict (StateT, evalStateT, execStateT) #if !(MIN_VERSION_base(4,11,0)) import Data.Monoid ((<>)) #endif@@ -106,7 +107,6 @@ -- | Test that this stateful parser runnable in IO successfully parses -- all of the given input text, showing the parse error if it fails. - -- Suitable for hledger's JournalParser parsers. expectParse :: (Monoid st, Eq a, Show a, HasCallStack) => StateT st (ParsecT CustomErr T.Text IO) a -> T.Text -> E.Test ()@@ -216,3 +216,17 @@ (expectEqPP expected . f) ep +-- | Run a stateful parser in IO like expectParse, then compare the+-- final state (the wrapped state, not megaparsec's internal state),+-- transformed by the given function, with the given expected value.+expectParseStateOn :: (HasCallStack, Monoid st, Eq b, Show b) =>+ StateT st (ParsecT CustomErr T.Text IO) a+ -> T.Text+ -> (st -> b)+ -> b+ -> E.Test ()+expectParseStateOn parser input f expected = do+ es <- E.io $ runParserT (execStateT (parser <* eof) mempty) "" input+ case es of+ Left err -> fail $ (++"\n") $ ("\nparse error at "++) $ customErrorBundlePretty err+ Right s -> expectEqPP expected $ f s
hledger-lib.cabal view
@@ -1,13 +1,13 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.31.0.+-- This file has been generated from package.yaml by hpack version 0.31.1. -- -- see: https://github.com/sol/hpack ----- hash: 8e0ce73c7c86c909a78d4d06e8566f8b66bc1df89f508da0b05df073c4ecd7c9+-- hash: c17b44c345a89a13650ca3efcba7d7e8311e9312acfd08dff5f2716e70ca29d7 name: hledger-lib-version: 1.12+version: 1.13 synopsis: Core data types, parsers and functionality for the hledger accounting tools description: This is a reusable library containing hledger's core functionality. .@@ -28,7 +28,7 @@ tested-with: GHC==7.10.3, GHC==8.0.2, GHC==8.2.2, GHC==8.4.3 build-type: Simple extra-source-files:- CHANGES+ CHANGES.md README hledger_csv.5 hledger_csv.txt@@ -121,8 +121,10 @@ , directory , easytest , extra+ , file-embed >=0.0.10 , filepath , hashtables >=1.2.3.1+ , here , megaparsec >=7.0.0 && <8 , mtl , mtl-compat@@ -134,6 +136,7 @@ , safe >=0.2 , split >=0.1 , tabular >=0.2+ , template-haskell , text >=1.2 , time >=1.5 , transformers >=0.2@@ -221,8 +224,10 @@ , doctest >=0.16 , easytest , extra+ , file-embed >=0.0.10 , filepath , hashtables >=1.2.3.1+ , here , megaparsec >=7.0.0 && <8 , mtl , mtl-compat@@ -234,6 +239,7 @@ , safe >=0.2 , split >=0.1 , tabular >=0.2+ , template-haskell , text >=1.2 , time >=1.5 , transformers >=0.2@@ -320,8 +326,10 @@ , directory , easytest , extra+ , file-embed >=0.0.10 , filepath , hashtables >=1.2.3.1+ , here , hledger-lib , megaparsec >=7.0.0 && <8 , mtl@@ -334,6 +342,7 @@ , safe >=0.2 , split >=0.1 , tabular >=0.2+ , template-haskell , text >=1.2 , time >=1.5 , transformers >=0.2
hledger_csv.5 view
@@ -1,5 +1,5 @@ -.TH "hledger_csv" "5" "December 2018" "hledger 1.12" "hledger User Manuals"+.TH "hledger_csv" "5" "February 2019" "hledger 1.13" "hledger User Manuals" @@ -29,7 +29,7 @@ directory. You can override this with the \f[C]\-\-rules\-file\f[] option. If the rules file does not exist, hledger will auto\-create one with-some example rules, which you'll need to adjust.+some example rules, which you\[aq]ll need to adjust. .PP At minimum, the rules file must identify the \f[C]date\f[] and \f[C]amount\f[] fields.@@ -90,7 +90,7 @@ \f[C]skip\f[]\f[I]\f[CI]N\f[I]\f[] .PP Skip this number of CSV records at the beginning.-You'll need this whenever your CSV data contains header lines.+You\[aq]ll need this whenever your CSV data contains header lines. Eg: .IP .nf@@ -104,23 +104,23 @@ \f[C]date\-format\f[]\f[I]\f[CI]DATEFMT\f[I]\f[] .PP When your CSV date fields are not formatted like \f[C]YYYY/MM/DD\f[] (or-\f[C]YYYY\-MM\-DD\f[] or \f[C]YYYY.MM.DD\f[]), you'll need to specify-the format.+\f[C]YYYY\-MM\-DD\f[] or \f[C]YYYY.MM.DD\f[]), you\[aq]ll need to+specify the format. DATEFMT is a strptime\-like date parsing pattern, which must parse the date field values completely. Examples: .IP .nf \f[C]-#\ for\ dates\ like\ "6/11/2013":-date\-format\ %\-d/%\-m/%Y+#\ for\ dates\ like\ "11/06/2013":+date\-format\ %m/%d/%Y \f[] .fi .IP .nf \f[C]-#\ for\ dates\ like\ "11/06/2013":-date\-format\ %m/%d/%Y+#\ for\ dates\ like\ "6/11/2013"\ (note\ the\ \-\ to\ make\ leading\ zeros\ optional):+date\-format\ %\-d/%\-m/%Y \f[] .fi .IP@@ -140,7 +140,7 @@ .SS field list .PP \f[C]fields\f[]\f[I]\f[CI]FIELDNAME1\f[I]\f[],-\f[I]\f[CI]FIELDNAME2\f[I]\f[]\&...+\f[I]\f[CI]FIELDNAME2\f[I]\f[]... .PP This (a) names the CSV fields, in order (names may not contain whitespace; uninteresting names may be left blank), and (b) assigns them@@ -192,7 +192,7 @@ .PD 0 .P .PD-\ \ \ \ \f[I]\f[CI]FIELDASSIGNMENTS\f[I]\f[]\&...+\ \ \ \ \f[I]\f[CI]FIELDASSIGNMENTS\f[I]\f[]... .PP \f[C]if\f[] .PD 0@@ -202,16 +202,16 @@ .PD 0 .P .PD-\f[I]\f[CI]PATTERN\f[I]\f[]\&...+\f[I]\f[CI]PATTERN\f[I]\f[]... .PD 0 .P .PD-\ \ \ \ \f[I]\f[CI]FIELDASSIGNMENTS\f[I]\f[]\&...+\ \ \ \ \f[I]\f[CI]FIELDASSIGNMENTS\f[I]\f[]... .PP This applies one or more field assignments, only to those CSV records matched by one of the PATTERNs. The patterns are case\-insensitive regular expressions which match-anywhere within the whole CSV record (it's not yet possible to match+anywhere within the whole CSV record (it\[aq]s not yet possible to match within a specific field). When there are multiple patterns they can be written on separate lines, unindented.@@ -244,7 +244,7 @@ .PP Include another rules file at this point. \f[C]RULESFILE\f[] is either an absolute file path or a path relative to-the current file's directory.+the current file\[aq]s directory. Eg: .IP .nf@@ -261,9 +261,9 @@ processing just one day of data, your CSV records are in reverse chronological order (newest first), and you care about preserving the order of same\-day transactions.-It usually isn't needed, because hledger autodetects the CSV order, but-when all CSV records have the same date it will assume they are oldest-first.+It usually isn\[aq]t needed, because hledger autodetects the CSV order,+but when all CSV records have the same date it will assume they are+oldest first. .SH CSV TIPS .SS CSV ordering .PP@@ -274,8 +274,9 @@ .PP Each journal entry will have two postings, to \f[C]account1\f[] and \f[C]account2\f[] respectively.-It's not yet possible to generate entries with more than two postings.-It's conventional and recommended to use \f[C]account1\f[] for the+It\[aq]s not yet possible to generate entries with more than two+postings.+It\[aq]s conventional and recommended to use \f[C]account1\f[] for the account whose CSV we are reading. .SS CSV amounts .PP
hledger_csv.info view
@@ -3,7 +3,7 @@ File: hledger_csv.info, Node: Top, Next: CSV RULES, Up: (dir) -hledger_csv(5) hledger 1.12+hledger_csv(5) hledger 1.13 *************************** hledger can read CSV (comma-separated value) files as if they were@@ -113,12 +113,12 @@ DATEFMT is a strptime-like date parsing pattern, which must parse the date field values completely. Examples: -# for dates like "6/11/2013":-date-format %-d/%-m/%Y- # for dates like "11/06/2013": date-format %m/%d/%Y +# for dates like "6/11/2013" (note the - to make leading zeros optional):+date-format %-d/%-m/%Y+ # for dates like "2013-Nov-06": date-format %Y-%h-%d @@ -323,27 +323,27 @@ Ref: #skip2627 Node: date-format2799 Ref: #date-format2926-Node: field list3432-Ref: #field-list3569-Node: field assignment4274-Ref: #field-assignment4429-Node: conditional block4933-Ref: #conditional-block5087-Node: include5983-Ref: #include6113-Node: newest-first6344-Ref: #newest-first6458-Node: CSV TIPS6869-Ref: #csv-tips6963-Node: CSV ordering7081-Ref: #csv-ordering7199-Node: CSV accounts7380-Ref: #csv-accounts7518-Node: CSV amounts7772-Ref: #csv-amounts7918-Node: CSV balance assertions8693-Ref: #csv-balance-assertions8875-Node: Reading multiple CSV files9080-Ref: #reading-multiple-csv-files9250+Node: field list3476+Ref: #field-list3613+Node: field assignment4318+Ref: #field-assignment4473+Node: conditional block4977+Ref: #conditional-block5131+Node: include6027+Ref: #include6157+Node: newest-first6388+Ref: #newest-first6502+Node: CSV TIPS6913+Ref: #csv-tips7007+Node: CSV ordering7125+Ref: #csv-ordering7243+Node: CSV accounts7424+Ref: #csv-accounts7562+Node: CSV amounts7816+Ref: #csv-amounts7962+Node: CSV balance assertions8737+Ref: #csv-balance-assertions8919+Node: Reading multiple CSV files9124+Ref: #reading-multiple-csv-files9294 End Tag Table
hledger_csv.txt view
@@ -88,12 +88,12 @@ is a strptime-like date parsing pattern, which must parse the date field values completely. Examples: - # for dates like "6/11/2013":- date-format %-d/%-m/%Y- # for dates like "11/06/2013": date-format %m/%d/%Y + # for dates like "6/11/2013" (note the - to make leading zeros optional):+ date-format %-d/%-m/%Y+ # for dates like "2013-Nov-06": date-format %Y-%h-%d @@ -249,4 +249,4 @@ -hledger 1.12 December 2018 hledger_csv(5)+hledger 1.13 February 2019 hledger_csv(5)
hledger_journal.5 view
@@ -1,34 +1,36 @@ .\"t -.TH "hledger_journal" "5" "December 2018" "hledger 1.12" "hledger User Manuals"+.TH "hledger_journal" "5" "February 2019" "hledger 1.13" "hledger User Manuals" .SH NAME .PP-Journal \- hledger's default file format, representing a General Journal+Journal \- hledger\[aq]s default file format, representing a General+Journal .SH DESCRIPTION .PP-hledger's usual data source is a plain text file containing journal+hledger\[aq]s usual data source is a plain text file containing journal entries in hledger journal format. This file represents a standard accounting general journal.-I use file names ending in \f[C]\&.journal\f[], but that's not required.+I use file names ending in \f[C]\&.journal\f[], but that\[aq]s not+required. The journal file contains a number of transaction entries, each describing a transfer of money (or any commodity) between two or more named accounts, in a simple format readable by both hledger and humans. .PP-hledger's journal format is a compatible subset, mostly, of ledger's-journal format, so hledger can work with compatible ledger journal files-as well.-It's safe, and encouraged, to run both hledger and ledger on the same-journal file, eg to validate the results you're getting.+hledger\[aq]s journal format is a compatible subset, mostly, of+ledger\[aq]s journal format, so hledger can work with compatible ledger+journal files as well.+It\[aq]s safe, and encouraged, to run both hledger and ledger on the+same journal file, eg to validate the results you\[aq]re getting. .PP You can use hledger without learning any more about this file; just use the add or web commands to create and update it. Many users, though, also edit the journal file directly with a text editor, perhaps assisted by the helper modes for emacs or vim. .PP-Here's an example:+Here\[aq]s an example: .IP .nf \f[C]@@ -81,7 +83,7 @@ semicolon until end of line) .PP Then comes zero or more (but usually at least 2) indented lines-representing\&...+representing... .SS Postings .PP A posting is an addition of some amount to, or removal of some amount@@ -134,12 +136,12 @@ on the right, is used when the \f[C]\-\-date2\f[] flag is specified (\f[C]\-\-aux\-date\f[] or \f[C]\-\-effective\f[] also work). .PP-The meaning of secondary dates is up to you, but it's best to follow a-consistent rule.-Eg write the bank's clearing date as primary, and when needed, the date-the transaction was initiated as secondary.+The meaning of secondary dates is up to you, but it\[aq]s best to follow+a consistent rule.+Eg write the bank\[aq]s clearing date as primary, and when needed, the+date the transaction was initiated as secondary. .PP-Here's an example.+Here\[aq]s an example. Note that a secondary date will use the year of the primary date if unspecified. .IP@@ -203,14 +205,14 @@ .fi .PP DATE should be a simple date; if the year is not specified it will use-the year of the transaction's date.+the year of the transaction\[aq]s date. You can set the secondary date similarly, with \f[C]date2:DATE2\f[]. The \f[C]date:\f[] or \f[C]date2:\f[] tags must have a valid simple date value if they are present, eg a \f[C]date:\f[] tag with no value is not allowed. .PP-Ledger's earlier, more compact bracketed date syntax is also supported:-\f[C][DATE]\f[], \f[C][DATE=DATE2]\f[] or \f[C][=DATE2]\f[].+Ledger\[aq]s earlier, more compact bracketed date syntax is also+supported: \f[C][DATE]\f[], \f[C][DATE=DATE2]\f[] or \f[C][=DATE2]\f[]. hledger will attempt to parse any square\-bracketed sequence of the \f[C]0123456789/\-.=\f[] characters in this way. With this syntax, DATE infers its year from the transaction and DATE2@@ -254,11 +256,11 @@ \f[C]status:!\f[], and \f[C]status:*\f[] queries; or the U, P, C keys in hledger\-ui. .PP-Note, in Ledger and in older versions of hledger, the \[lq]unmarked\[rq]-state is called \[lq]uncleared\[rq].+Note, in Ledger and in older versions of hledger, the "unmarked" state+is called "uncleared". As of hledger 1.3 we have renamed it to unmarked for clarity. .PP-To replicate Ledger and old hledger's behaviour of also matching+To replicate Ledger and old hledger\[aq]s behaviour of also matching pending, combine \-U and \-P. .PP Status marks are optional, but can be helpful eg for reconciling with@@ -268,9 +270,8 @@ Eg in Emacs ledger\-mode, you can toggle transaction status with C\-c C\-e, or posting status with C\-c C\-c. .PP-What \[lq]uncleared\[rq], \[lq]pending\[rq], and \[lq]cleared\[rq]-actually mean is up to you.-Here's one suggestion:+What "uncleared", "pending", and "cleared" actually mean is up to you.+Here\[aq]s one suggestion: .PP .TS tab(@);@@ -304,10 +305,10 @@ up\-to\-date state of your finances. .SS Description .PP-A transaction's description is the rest of the line following the date-and status mark (or until a comment begins).-Sometimes called the \[lq]narration\[rq] in traditional bookkeeping, it-can be used for whatever you wish, or left blank.+A transaction\[aq]s description is the rest of the line following the+date and status mark (or until a comment begins).+Sometimes called the "narration" in traditional bookkeeping, it can be+used for whatever you wish, or left blank. Transaction descriptions can be queried, unlike comments. .SS Payee and note .PP@@ -380,8 +381,8 @@ .PP As you can see, the amount format is somewhat flexible: .IP \[bu] 2-amounts are a number (the \[lq]quantity\[rq]) and optionally a currency-symbol/commodity name (the \[lq]commodity\[rq]).+amounts are a number (the "quantity") and optionally a currency+symbol/commodity name (the "commodity"). .IP \[bu] 2 the commodity is a symbol, word, or phrase, on the left or right, with or without a separating space.@@ -400,8 +401,8 @@ .IP \[bu] 2 scientific E\-notation is allowed. Be careful not to use a digit group separator character in scientific-notation, as it's not supported and it might get mistaken for a decimal-point.+notation, as it\[aq]s not supported and it might get mistaken for a+decimal point. (Declaring the digit group separator character explicitly with a commodity directive will prevent this.) .PP@@ -439,13 +440,13 @@ or if there are no such amounts in the journal, a default format is used (like \f[C]$1000.00\f[]). .PP-Price amounts and amounts in \f[C]D\f[] directives usually don't affect-amount format inference, but in some situations they can do so+Price amounts and amounts in \f[C]D\f[] directives usually don\[aq]t+affect amount format inference, but in some situations they can do so indirectly.-(Eg when D's default commodity is applied to a commodity\-less amount,-or when an amountless posting is balanced using a price's commodity, or-when \-V is used.) If you find this causing problems, set the desired-format with a commodity directive.+(Eg when D\[aq]s default commodity is applied to a commodity\-less+amount, or when an amountless posting is balanced using a price\[aq]s+commodity, or when \-V is used.) If you find this causing problems, set+the desired format with a commodity directive. .SS Virtual Postings .PP When you parenthesise the account name in a posting, we call that a@@ -456,7 +457,7 @@ it is excluded from reports when the \f[C]\-\-real/\-R\f[] flag is used, or the \f[C]real:1\f[] query. .PP-You could use this, eg, to set an account's opening balance without+You could use this, eg, to set an account\[aq]s opening balance without needing to use the \f[C]equity:opening\ balances\f[] account: .IP .nf@@ -490,7 +491,8 @@ .SS Balance Assertions .PP hledger supports Ledger\-style balance assertions in journal files.-These look like \f[C]=EXPECTEDBALANCE\f[] following a posting's amount.+These look like \f[C]=EXPECTEDBALANCE\f[] following a posting\[aq]s+amount. Eg in this example we assert the expected dollar balance in accounts a and b after each posting: .IP@@ -515,7 +517,7 @@ troubleshooting or for reading Ledger files. .SS Assertions and ordering .PP-hledger sorts an account's postings and assertions first by date and+hledger sorts an account\[aq]s postings and assertions first by date and then (for postings on the same day) by parse order. Note this is different from Ledger, which sorts assertions only by parse order.@@ -534,31 +536,31 @@ With included files, things are a little more complicated. Including preserves the ordering of postings and assertions. If you have multiple postings to an account on the same day, split-across different files, and you also want to assert the account's-balance on the same day, you'll have to put the assertion in the right-file.+across different files, and you also want to assert the account\[aq]s+balance on the same day, you\[aq]ll have to put the assertion in the+right file. .SS Assertions and multiple \-f options .PP-Balance assertions don't work well across files specified with multiple-\-f options.+Balance assertions don\[aq]t work well across files specified with+multiple \-f options. Use include or concatenate the files instead. .SS Assertions and commodities .PP The asserted balance must be a simple single\-commodity amount, and in-fact the assertion checks only this commodity's balance within the+fact the assertion checks only this commodity\[aq]s balance within the (possibly multi\-commodity) account balance. .PD 0 .P .PD This is how assertions work in Ledger also.-We could call this a \[lq]partial\[rq] balance assertion.+We could call this a "partial" balance assertion. .PP To assert the balance of more than one commodity in an account, you can-write multiple postings, each asserting one commodity's balance.+write multiple postings, each asserting one commodity\[aq]s balance. .PP You can make a stronger kind of balance assertion, by writing a double equals sign (\f[C]==EXPECTEDBALANCE\f[]).-This \[lq]complete\[rq] balance assertion asserts the absence of other+This "complete" balance assertion asserts the absence of other commodities (or, that their balance is 0, which to hledger is equivalent.) .IP@@ -581,8 +583,8 @@ \f[] .fi .PP-It's not yet possible to make a complete assertion about a balance that-has multiple commodities.+It\[aq]s not yet possible to make a complete assertion about a balance+that has multiple commodities. One workaround is to isolate each commodity into its own subaccount: .IP .nf@@ -598,10 +600,27 @@ \ \ a:euro\ \ \ 0\ ==\ \ 1€ \f[] .fi+.SS Assertions and prices+.PP+Balance assertions ignore transaction prices, and should normally be+written without one:+.IP+.nf+\f[C]+2019/1/1+\ \ (a)\ \ \ \ \ $1\ \@\ €1\ =\ $1+\f[]+.fi+.PP+We do allow prices to be written there, however, and print shows them,+even though they don\[aq]t affect whether the assertion passes or fails.+This is for backward compatibility (hledger\[aq]s close command used to+generate balance assertions with prices), and because balance+\f[I]assignments\f[] do use them (see below). .SS Assertions and subaccounts .PP Balance assertions do not count the balance from subaccounts; they check-the posted account's exclusive balance.+the posted account\[aq]s exclusive balance. For example: .IP .nf@@ -613,7 +632,7 @@ \f[] .fi .PP-The balance report's flat mode shows these exclusive balances more+The balance report\[aq]s flat mode shows these exclusive balances more clearly: .IP .nf@@ -631,6 +650,13 @@ virtual. They are not affected by the \f[C]\-\-real/\-R\f[] flag or \f[C]real:\f[] query.+.SS Assertions and precision+.PP+Balance assertions compare the exactly calculated amounts, which are not+always what is shown by reports.+Eg a commodity directive may limit the display precision, but this will+not affect balance assertions.+Balance assertion failure messages show exact amounts. .SS Balance Assignments .PP Ledger\-style balance assignments are also supported.@@ -662,16 +688,35 @@ \f[] .fi .PP-The calculated amount depends on the account's balance in the commodity-at that point (which depends on the previously\-dated postings of the-commodity to that account since the last balance assertion or+The calculated amount depends on the account\[aq]s balance in the+commodity at that point (which depends on the previously\-dated postings+of the commodity to that account since the last balance assertion or assignment). Note that using balance assignments makes your journal a little less explicit; to know the exact amount posted, you have to run hledger or do the calculations yourself, instead of just reading it.+.SS Balance assignments and prices+.PP+A transaction price in a balance assignment will cause the calculated+amount to have that price attached:+.IP+.nf+\f[C]+2019/1/1+\ \ (a)\ \ \ \ \ \ \ \ \ \ \ \ \ =\ $1\ \@\ €2+\f[]+.fi+.IP+.nf+\f[C]+$\ hledger\ print\ \-\-explicit+2019/01/01+\ \ \ \ (a)\ \ \ \ \ \ \ \ \ $1\ \@\ €2\ =\ $1\ \@\ €2+\f[]+.fi .SS Transaction prices .PP-Within a transaction, you can note an amount's price in another+Within a transaction, you can note an amount\[aq]s price in another commodity. This can be used to document the cost (in a purchase) or selling price (in a sale).@@ -725,8 +770,8 @@ \f[C]{=UNITPRICE}\f[], which hledger currently ignores). .PP Use the \f[C]\-B/\-\-cost\f[] flag to convert amounts to their-transaction price's commodity, if any.-(mnemonic: \[lq]B\[rq] is from \[lq]cost Basis\[rq], as in Ledger).+transaction price\[aq]s commodity, if any.+(mnemonic: "B" is from "cost Basis", as in Ledger). Eg here is how \-B affects the balance report for the example above: .IP .nf@@ -743,7 +788,7 @@ Note \-B is sensitive to the order of postings when a transaction price is inferred: the inferred price will be in the commodity of the last amount.-So if example 3's postings are reversed, while the transaction is+So if example 3\[aq]s postings are reversed, while the transaction is equivalent, \-B shows something different: .IP .nf@@ -826,7 +871,8 @@ \f[] .fi .PP-Note this means hledger's tag values can not contain commas or newlines.+Note this means hledger\[aq]s tag values can not contain commas or+newlines. Ending at commas means you can write multiple short tags on one line, comma separated: .IP@@ -838,13 +884,12 @@ .PP Here, .IP \[bu] 2-\[lq]\f[C]a\ comment\ containing\f[]\[rq] is just comment text, not a-tag+"\f[C]a\ comment\ containing\f[]" is just comment text, not a tag .IP \[bu] 2-\[lq]\f[C]tag1\f[]\[rq] is a tag with no value+"\f[C]tag1\f[]" is a tag with no value .IP \[bu] 2-\[lq]\f[C]tag2\f[]\[rq] is another tag, whose value is-\[lq]\f[C]some\ value\ ...\f[]\[rq]+"\f[C]tag2\f[]" is another tag, whose value is+"\f[C]some\ value\ ...\f[]" .PP Tags in a transaction comment affect the transaction and all of its postings, while tags in a posting comment affect only that posting.@@ -860,18 +905,19 @@ \f[] .fi .PP-Tags are like Ledger's metadata feature, except hledger's tag values are-simple strings.+Tags are like Ledger\[aq]s metadata feature, except hledger\[aq]s tag+values are simple strings. .SS Directives .PP A directive is a line in the journal beginning with a special keyword, that influences how the journal is processed.-hledger's directives are based on a subset of Ledger's, but there are-many differences (and also some differences between hledger versions).+hledger\[aq]s directives are based on a subset of Ledger\[aq]s, but+there are many differences (and also some differences between hledger+versions). .PP-Directives' behaviour and interactions can get a little bit complex, so-here is a table summarising the directives and their effects, with links-to more detailed docs.+Directives\[aq] behaviour and interactions can get a little bit complex,+so here is a table summarising the directives and their effects, with+links to more detailed docs. .PP .TS tab(@);@@ -1053,8 +1099,8 @@ It can include journal, timeclock or timedot files, but not CSV files. .SS Default year .PP-You can set a default year to be used for subsequent dates which don't-specify a year.+You can set a default year to be used for subsequent dates which+don\[aq]t specify a year. This is a line beginning with \f[C]Y\f[] followed by the year. Eg: .IP@@ -1094,7 +1140,7 @@ \f[] .fi .PP-or on multiple lines, using the \[lq]format\[rq] subdirective.+or on multiple lines, using the "format" subdirective. In this case the commodity symbol appears twice and should be the same in both places: .IP@@ -1123,7 +1169,7 @@ .PP The \f[C]D\f[] directive sets a default commodity (and display format), to be used for amounts without a commodity symbol (ie, plain numbers).-(Note this differs from Ledger's default commodity directive.) The+(Note this differs from Ledger\[aq]s default commodity directive.) The commodity and display format will be applied to all subsequent commodity\-less amounts, or until the next \f[C]D\f[] directive. .IP@@ -1145,9 +1191,9 @@ .PP The \f[C]P\f[] directive declares a market price, which is an exchange rate between two commodities on a certain date.-(In Ledger, they are called \[lq]historical prices\[rq].) These are-often obtained from a stock exchange, cryptocurrency exchange, or the-foreign exchange market.+(In Ledger, they are called "historical prices".) These are often+obtained from a stock exchange, cryptocurrency exchange, or the foreign+exchange market. .PP Here is the format: .IP@@ -1178,8 +1224,7 @@ to another commodity using these prices. .SS Declaring accounts .PP-\f[C]account\f[] directives can be used to pre\-declare some or all-accounts.+\f[C]account\f[] directives can be used to pre\-declare accounts. Though not required, they can provide several benefits: .IP \[bu] 2 They can document your intended chart of accounts, providing a@@ -1188,7 +1233,7 @@ They can store extra information about accounts (account numbers, notes, etc.) .IP \[bu] 2-They can help hledger know your accounts' types (asset, liability,+They can help hledger know your accounts\[aq] types (asset, liability, equity, revenue, expense), useful for reports like balancesheet and incomestatement. .IP \[bu] 2@@ -1198,41 +1243,89 @@ They help with account name completion in the add command, hledger\-iadd, hledger\-web, ledger\-mode etc. .PP-Here is the full syntax:+The simplest form is just the word \f[C]account\f[] followed by a+hledger\-style account name, eg: .IP .nf \f[C]-account\ ACCTNAME\ \ [ACCTTYPE]-\ \ [COMMENTS]+account\ assets:bank:checking \f[] .fi+.SS Account comments .PP-The simplest form just declares a hledger\-style account name, eg:+Comments, beginning with a semicolon, optionally including tags, can be+written after the account name, and/or on following lines.+Eg: .IP .nf \f[C]+account\ assets:bank:checking\ \ ;\ a\ comment+\ \ ;\ another\ comment+\ \ ;\ acctno:12345,\ a\ tag+\f[]+.fi+.PP+Tip: comments on the same line require hledger 1.12+.+If you need your journal to be compatible with older hledger versions,+write comments on the next line instead.+.SS Account subdirectives+.PP+We also allow (and ignore) Ledger\-style indented subdirectives, just+for compatibility.:+.IP+.nf+\f[C] account\ assets:bank:checking+\ \ format\ blah\ blah\ \ ;\ <\-\ subdirective,\ ignored \f[] .fi+.PP+Here is the full syntax of account directives:+.IP+.nf+\f[C]+account\ ACCTNAME\ \ [ACCTTYPE]\ [;COMMENT]+\ \ [;COMMENTS]+\ \ [LEDGER\-STYLE\ SUBDIRECTIVES,\ IGNORED]+\f[]+.fi .SS Account types .PP-hledger recognises five types of account: asset, liability, equity,-revenue, expense.-This is useful for certain accounting\-aware reports, in particular-balancesheet, incomestatement and cashflow.+hledger recognises five types (or classes) of account: Asset, Liability,+Equity, Revenue, Expense.+This is used by a few accounting\-aware reports such as balancesheet,+incomestatement and cashflow.+.SS Auto\-detected account types .PP If you name your top\-level accounts with some variation of \f[C]assets\f[], \f[C]liabilities\f[]/\f[C]debts\f[], \f[C]equity\f[], \f[C]revenues\f[]/\f[C]income\f[], or \f[C]expenses\f[], their types are detected automatically.+.SS Account types declared with tags .PP-More generally, you can declare an account's type by adding one of the-letters \f[C]ALERX\f[] to its account directive, separated from the-account name by two or more spaces.-Eg:+More generally, you can declare an account\[aq]s type with an account+directive, by writing a \f[C]type:\f[] tag in a comment, followed by one+of the words \f[C]Asset\f[], \f[C]Liability\f[], \f[C]Equity\f[],+\f[C]Revenue\f[], \f[C]Expense\f[], or one of the letters \f[C]ALERX\f[]+(case insensitive): .IP .nf \f[C]+account\ assets\ \ \ \ \ \ \ ;\ type:Asset+account\ liabilities\ \ ;\ type:Liability+account\ equity\ \ \ \ \ \ \ ;\ type:Equity+account\ revenues\ \ \ \ \ ;\ type:Revenue+account\ expenses\ \ \ \ \ ;\ type:Expenses+\f[]+.fi+.SS Account types declared with account type codes+.PP+Or, you can write one of those letters separated from the account name+by two or more spaces, but this should probably be considered deprecated+as of hledger 1.13:+.IP+.nf+\f[C] account\ assets\ \ \ \ \ \ \ A account\ liabilities\ \ L account\ equity\ \ \ \ \ \ \ E@@ -1240,46 +1333,29 @@ account\ expenses\ \ \ \ \ X \f[] .fi+.SS Overriding auto\-detected types .PP-Note: if you ever override the types of those auto\-detected english-account names mentioned above, you might need to help the reports a bit:+If you ever override the types of those auto\-detected english account+names mentioned above, you might need to help the reports a bit.+Eg: .IP .nf \f[C]-;\ make\ "liabilities"\ not\ have\ the\ liability\ type,\ who\ knows\ why-account\ liabilities\ \ \ E+;\ make\ "liabilities"\ not\ have\ the\ liability\ type\ \-\ who\ knows\ why+account\ liabilities\ \ \ ;\ type:E -;\ better\ ensure\ some\ other\ account\ has\ the\ liability\ type,\ +;\ we\ need\ to\ ensure\ some\ other\ account\ has\ the\ liability\ type,\ ;\ otherwise\ balancesheet\ would\ still\ show\ "liabilities"\ under\ Liabilities\ -account\ \-\ \ \ \ \ \ \ \ \ \ \ \ \ L-\f[]-.fi-.PP-)-.SS Account comments-.PP-An account directive can also have indented comments on following lines,-eg:-.IP-.nf-\f[C]-account\ assets:bank:checking-\ \ ;\ acctno:12345-\ \ ;\ a\ comment+account\ \-\ \ \ \ \ \ \ \ \ \ \ \ \ ;\ type:L \f[] .fi-.PP-We also allow (and ignore) Ledger\-style subdirectives, with no leading-semicolon, for compatibility.-.PP-Tags in account comments, like \f[C]acctno\f[] above, currently have no-effect. .SS Account display order .PP-Account directives also set the order in which accounts are displayed in-reports, the hledger\-ui accounts screen, the hledger\-web sidebar, etc.-Normally accounts are listed in alphabetical order, but if you have eg-these account directives in the journal:+Account directives also set the order in which accounts are displayed,+eg in reports, the hledger\-ui accounts screen, and the hledger\-web+sidebar.+By default accounts are listed in alphabetical order.+But if you have these account directives in the journal: .IP .nf \f[C]@@ -1291,7 +1367,7 @@ \f[] .fi .PP-you'll see those accounts listed in declaration order, not+you\[aq]ll see those accounts displayed in declaration order, not alphabetically: .IP .nf@@ -1317,13 +1393,14 @@ \f[] .fi .PP-would influence the position of \f[C]zoo\f[] among \f[C]other\f[]'s+would influence the position of \f[C]zoo\f[] among \f[C]other\f[]\[aq]s subaccounts, but not the position of \f[C]other\f[] among the top\-level accounts. This means: \- you will sometimes declare parent accounts (eg-\f[C]account\ other\f[] above) that you don't intend to post to, just to-customize their display order \- sibling accounts stay together (you-couldn't display \f[C]x:y\f[] in between \f[C]a:b\f[] and \f[C]a:c\f[]).+\f[C]account\ other\f[] above) that you don\[aq]t intend to post to,+just to customize their display order \- sibling accounts stay together+(you couldn\[aq]t display \f[C]x:y\f[] in between \f[C]a:b\f[] and+\f[C]a:c\f[]). .SS Rewriting accounts .PP You can define account alias rules which rewrite your account names, or@@ -1362,7 +1439,7 @@ Or, you can use the \f[C]\-\-alias\ \[aq]OLD=NEW\[aq]\f[] option on the command line. This affects all entries.-It's useful for trying out aliases interactively.+It\[aq]s useful for trying out aliases interactively. .PP OLD and NEW are case sensitive full account names. hledger will replace any occurrence of the old account name with the new@@ -1508,23 +1585,22 @@ .PP Partial or relative dates (M/D, D, tomorrow, last week) in the period expression can work (useful or not).-They will be relative to today's date, unless a Y default year directive-is in effect, in which case they will be relative to Y/1/1.+They will be relative to today\[aq]s date, unless a Y default year+directive is in effect, in which case they will be relative to Y/1/1.+.SS Two spaces after the period expression .PP-Period expressions must be terminated by \f[B]two or more spaces\f[] if-followed by additional fields.-For example, the periodic transaction given below includes a transaction-description \[lq]paycheck\[rq], which is separated from the period-expression by a double space.-If not for the second space, hledger would attempt (and fail) to parse-\[lq]paycheck\[rq] as a part of the period expression.+If the period expression is followed by a transaction description, these+must be separated by \f[B]two or more spaces\f[].+This helps hledger know where the period expression ends, so that+descriptions can not accidentally alter their meaning, as in this+example: .IP .nf \f[C]-;\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 2\ or\ more\ spaces-;\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ ||-;\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ vv-~\ every\ 2\ weeks\ from\ 2018/6/4\ to\ 2018/9\ \ paycheck+;\ 2\ or\ more\ spaces\ needed\ here,\ so\ the\ period\ is\ not\ understood\ as\ "every\ 2\ months\ in\ 2020"+;\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ ||+;\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ vv+~\ every\ 2\ months\ \ in\ 2020,\ we\ will\ review \ \ \ \ assets:bank:checking\ \ \ $1500 \ \ \ \ income:acme\ inc \f[]@@ -1553,9 +1629,9 @@ ends on the report end date if specified with \-e/\-p/date:, or 180 days from today. .PP-where \[lq]today\[rq] means the current date at report time.-The \[lq]later of\[rq] rule ensures that forecast transactions do not-overlap normal transactions in time; they will begin only after normal+where "today" means the current date at report time.+The "later of" rule ensures that forecast transactions do not overlap+normal transactions in time; they will begin only after normal transactions end. .PP Forecasting can be useful for estimating balances into the future, and@@ -1583,18 +1659,19 @@ For more details, see: balance: Budget report and Cookbook: Budgeting and Forecasting. .PP-.SS Transaction Modifiers+.SS Transaction modifiers .PP Transaction modifier rules describe changes that should be applied automatically to certain transactions.-Currently, this means adding extra postings (also known as-\[lq]automated postings\[rq]).-Transaction modifiers are enabled by the \f[C]\-\-auto\f[] flag.+They can be enabled by using the \f[C]\-\-auto\f[] flag.+Currently, just one kind of change is possible: adding extra postings.+These rule\-generated postings are known as "automated postings" or+"auto postings". .PP A transaction modifier rule looks quite like a normal transaction, except the first line is an equals sign followed by a query that matches certain postings (mnemonic: \f[C]=\f[] suggests matching).-And each \[lq]posting\[rq] is actually a posting\-generating rule:+And each "posting" is actually a posting\-generating rule: .IP .nf \f[C]@@ -1605,8 +1682,7 @@ \f[] .fi .PP-The posting rules look just like normal postings, except the amount can-be:+These posting rules look like normal postings, except the amount can be: .IP \[bu] 2 a normal amount with a commodity symbol, eg \f[C]$2\f[]. This will be used as\-is.@@ -1616,13 +1692,13 @@ this. .IP \[bu] 2 a numeric multiplier, eg \f[C]*2\f[] (a star followed by a number N).-The matched posting's amount (and total price, if any) will be+The matched posting\[aq]s amount (and total price, if any) will be multiplied by N. .IP \[bu] 2 a multiplier with a commodity symbol, eg \f[C]*$2\f[] (a star, number N, and symbol S).-The matched posting's amount will be multiplied by N, and its commodity-symbol will be replaced with S.+The matched posting\[aq]s amount will be multiplied by N, and its+commodity symbol will be replaced with S. .PP Some examples: .IP@@ -1662,10 +1738,19 @@ \ \ \ \ assets:checking\ \ \ \ \ \ \ \ \ \ \ \ $20 \f[] .fi+.SS Auto postings and transaction balancing / inferred amounts / balance+assertions .PP-Postings added by transaction modifiers participate in transaction-balancing, missing amount inference and balance assertions, like regular-postings.+Currently, transaction modifiers are applied / auto postings are added:+.IP \[bu] 2+after missing amounts are inferred, and transactions are checked for+balancedness,+.IP \[bu] 2+but before balance assertions are checked.+.PP+Note this means that journal entries must be balanced both before and+after auto postings are added.+This changed in hledger 1.12+; see #893 for background. .SH EDITOR SUPPORT .PP Add\-on modes exist for various text editors, to make working with
hledger_journal.info view
@@ -4,7 +4,7 @@ File: hledger_journal.info, Node: Top, Next: FILE FORMAT, Up: (dir) -hledger_journal(5) hledger 1.12+hledger_journal(5) hledger 1.13 ******************************* hledger's usual data source is a plain text file containing journal@@ -82,7 +82,7 @@ * Tags:: * Directives:: * Periodic transactions::-* Transaction Modifiers::+* Transaction modifiers:: File: hledger_journal.info, Node: Transactions, Next: Postings, Up: FILE FORMAT@@ -473,8 +473,10 @@ * Assertions and included files:: * Assertions and multiple -f options:: * Assertions and commodities::+* Assertions and prices:: * Assertions and subaccounts:: * Assertions and virtual postings::+* Assertions and precision:: File: hledger_journal.info, Node: Assertions and ordering, Next: Assertions and included files, Up: Balance Assertions@@ -517,7 +519,7 @@ -f options. Use include or concatenate the files instead. -File: hledger_journal.info, Node: Assertions and commodities, Next: Assertions and subaccounts, Prev: Assertions and multiple -f options, Up: Balance Assertions+File: hledger_journal.info, Node: Assertions and commodities, Next: Assertions and prices, Prev: Assertions and multiple -f options, Up: Balance Assertions 1.9.4 Assertions and commodities --------------------------------@@ -566,9 +568,27 @@ a:euro 0 == 1€ -File: hledger_journal.info, Node: Assertions and subaccounts, Next: Assertions and virtual postings, Prev: Assertions and commodities, Up: Balance Assertions+File: hledger_journal.info, Node: Assertions and prices, Next: Assertions and subaccounts, Prev: Assertions and commodities, Up: Balance Assertions -1.9.5 Assertions and subaccounts+1.9.5 Assertions and prices+---------------------------++Balance assertions ignore transaction prices, and should normally be+written without one:++2019/1/1+ (a) $1 @ €1 = $1++ We do allow prices to be written there, however, and print shows+them, even though they don't affect whether the assertion passes or+fails. This is for backward compatibility (hledger's close command used+to generate balance assertions with prices), and because balance+_assignments_ do use them (see below).+++File: hledger_journal.info, Node: Assertions and subaccounts, Next: Assertions and virtual postings, Prev: Assertions and prices, Up: Balance Assertions++1.9.6 Assertions and subaccounts -------------------------------- Balance assertions do not count the balance from subaccounts; they check@@ -589,9 +609,9 @@ 2 -File: hledger_journal.info, Node: Assertions and virtual postings, Prev: Assertions and subaccounts, Up: Balance Assertions+File: hledger_journal.info, Node: Assertions and virtual postings, Next: Assertions and precision, Prev: Assertions and subaccounts, Up: Balance Assertions -1.9.6 Assertions and virtual postings+1.9.7 Assertions and virtual postings ------------------------------------- Balance assertions are checked against all postings, both real and@@ -599,6 +619,17 @@ query. +File: hledger_journal.info, Node: Assertions and precision, Prev: Assertions and virtual postings, Up: Balance Assertions++1.9.8 Assertions and precision+------------------------------++Balance assertions compare the exactly calculated amounts, which are not+always what is shown by reports. Eg a commodity directive may limit the+display precision, but this will not affect balance assertions. Balance+assertion failure messages show exact amounts.++ File: hledger_journal.info, Node: Balance Assignments, Next: Transaction prices, Prev: Balance Assertions, Up: FILE FORMAT 1.10 Balance Assignments@@ -630,8 +661,27 @@ assignment). Note that using balance assignments makes your journal a little less explicit; to know the exact amount posted, you have to run hledger or do the calculations yourself, instead of just reading it.+* Menu: +* Balance assignments and prices::+ +File: hledger_journal.info, Node: Balance assignments and prices, Up: Balance Assignments++1.10.1 Balance assignments and prices+-------------------------------------++A transaction price in a balance assignment will cause the calculated+amount to have that price attached:++2019/1/1+ (a) = $1 @ €2++$ hledger print --explicit+2019/01/01+ (a) $1 @ €2 = $1 @ €2++ File: hledger_journal.info, Node: Transaction prices, Next: Comments, Prev: Balance Assignments, Up: FILE FORMAT 1.11 Transaction prices@@ -1033,8 +1083,8 @@ 1.14.7 Declaring accounts ------------------------- -'account' directives can be used to pre-declare some or all accounts.-Though not required, they can provide several benefits:+'account' directives can be used to pre-declare accounts. Though not+required, they can provide several benefits: * They can document your intended chart of accounts, providing a reference.@@ -1048,86 +1098,108 @@ * They help with account name completion in the add command, hledger-iadd, hledger-web, ledger-mode etc. - Here is the full syntax:--account ACCTNAME [ACCTTYPE]- [COMMENTS]-- The simplest form just declares a hledger-style account name, eg:+ The simplest form is just the word 'account' followed by a+hledger-style account name, eg: account assets:bank:checking * Menu: -* Account types:: * Account comments::+* Account subdirectives::+* Account types:: * Account display order:: -File: hledger_journal.info, Node: Account types, Next: Account comments, Up: Declaring accounts+File: hledger_journal.info, Node: Account comments, Next: Account subdirectives, Up: Declaring accounts -1.14.7.1 Account types-......................+1.14.7.1 Account comments+......................... -hledger recognises five types of account: asset, liability, equity,-revenue, expense. This is useful for certain accounting-aware reports,-in particular balancesheet, incomestatement and cashflow.+Comments, beginning with a semicolon, optionally including tags, can be+written after the account name, and/or on following lines. Eg: - If you name your top-level accounts with some variation of 'assets',-'liabilities'/'debts', 'equity', 'revenues'/'income', or 'expenses',-their types are detected automatically.+account assets:bank:checking ; a comment+ ; another comment+ ; acctno:12345, a tag - More generally, you can declare an account's type by adding one of-the letters 'ALERX' to its account directive, separated from the account-name by two or more spaces. Eg:+ Tip: comments on the same line require hledger 1.12+. If you need+your journal to be compatible with older hledger versions, write+comments on the next line instead. -account assets A-account liabilities L-account equity E-account revenues R-account expenses X++File: hledger_journal.info, Node: Account subdirectives, Next: Account types, Prev: Account comments, Up: Declaring accounts - Note: if you ever override the types of those auto-detected english-account names mentioned above, you might need to help the reports a bit:+1.14.7.2 Account subdirectives+.............................. -; make "liabilities" not have the liability type, who knows why-account liabilities E+We also allow (and ignore) Ledger-style indented subdirectives, just for+compatibility.: -; better ensure some other account has the liability type, -; otherwise balancesheet would still show "liabilities" under Liabilities -account - L+account assets:bank:checking+ format blah blah ; <- subdirective, ignored - )+ Here is the full syntax of account directives: +account ACCTNAME [ACCTTYPE] [;COMMENT]+ [;COMMENTS]+ [LEDGER-STYLE SUBDIRECTIVES, IGNORED]+ -File: hledger_journal.info, Node: Account comments, Next: Account display order, Prev: Account types, Up: Declaring accounts+File: hledger_journal.info, Node: Account types, Next: Account display order, Prev: Account subdirectives, Up: Declaring accounts -1.14.7.2 Account comments-.........................+1.14.7.3 Account types+...................... -An account directive can also have indented comments on following lines,-eg:+hledger recognises five types (or classes) of account: Asset, Liability,+Equity, Revenue, Expense. This is used by a few accounting-aware+reports such as balancesheet, incomestatement and cashflow.+Auto-detected account types If you name your top-level accounts with+some variation of 'assets', 'liabilities'/'debts', 'equity',+'revenues'/'income', or 'expenses', their types are detected+automatically. Account types declared with tags More generally, you can+declare an account's type with an account directive, by writing a+'type:' tag in a comment, followed by one of the words 'Asset',+'Liability', 'Equity', 'Revenue', 'Expense', or one of the letters+'ALERX' (case insensitive): -account assets:bank:checking- ; acctno:12345- ; a comment+account assets ; type:Asset+account liabilities ; type:Liability+account equity ; type:Equity+account revenues ; type:Revenue+account expenses ; type:Expenses - We also allow (and ignore) Ledger-style subdirectives, with no-leading semicolon, for compatibility.+ Account types declared with account type codes Or, you can write one+of those letters separated from the account name by two or more spaces,+but this should probably be considered deprecated as of hledger 1.13: - Tags in account comments, like 'acctno' above, currently have no-effect.+account assets A+account liabilities L+account equity E+account revenues R+account expenses X + Overriding auto-detected types If you ever override the types of+those auto-detected english account names mentioned above, you might+need to help the reports a bit. Eg:++; make "liabilities" not have the liability type - who knows why+account liabilities ; type:E++; we need to ensure some other account has the liability type, +; otherwise balancesheet would still show "liabilities" under Liabilities +account - ; type:L+ -File: hledger_journal.info, Node: Account display order, Prev: Account comments, Up: Declaring accounts+File: hledger_journal.info, Node: Account display order, Prev: Account types, Up: Declaring accounts -1.14.7.3 Account display order+1.14.7.4 Account display order .............................. -Account directives also set the order in which accounts are displayed in-reports, the hledger-ui accounts screen, the hledger-web sidebar, etc.-Normally accounts are listed in alphabetical order, but if you have eg-these account directives in the journal:+Account directives also set the order in which accounts are displayed,+eg in reports, the hledger-ui accounts screen, and the hledger-web+sidebar. By default accounts are listed in alphabetical order. But if+you have these account directives in the journal: account assets account liabilities@@ -1135,7 +1207,7 @@ account revenues account expenses - you'll see those accounts listed in declaration order, not+ you'll see those accounts displayed in declaration order, not alphabetically: $ hledger accounts -1@@ -1306,7 +1378,7 @@ parent account. -File: hledger_journal.info, Node: Periodic transactions, Next: Transaction Modifiers, Prev: Directives, Up: FILE FORMAT+File: hledger_journal.info, Node: Periodic transactions, Next: Transaction modifiers, Prev: Directives, Up: FILE FORMAT 1.15 Periodic transactions ==========================@@ -1332,32 +1404,36 @@ expression can work (useful or not). They will be relative to today's date, unless a Y default year directive is in effect, in which case they will be relative to Y/1/1.-- Period expressions must be terminated by *two or more spaces* if-followed by additional fields. For example, the periodic transaction-given below includes a transaction description "paycheck", which is-separated from the period expression by a double space. If not for the-second space, hledger would attempt (and fail) to parse "paycheck" as a-part of the period expression.--; 2 or more spaces-; ||-; vv-~ every 2 weeks from 2018/6/4 to 2018/9 paycheck- assets:bank:checking $1500- income:acme inc- * Menu: +* Two spaces after the period expression:: * Forecasting with periodic transactions:: * Budgeting with periodic transactions:: -File: hledger_journal.info, Node: Forecasting with periodic transactions, Next: Budgeting with periodic transactions, Up: Periodic transactions+File: hledger_journal.info, Node: Two spaces after the period expression, Next: Forecasting with periodic transactions, Up: Periodic transactions -1.15.1 Forecasting with periodic transactions+1.15.1 Two spaces after the period expression --------------------------------------------- +If the period expression is followed by a transaction description, these+must be separated by *two or more spaces*. This helps hledger know+where the period expression ends, so that descriptions can not+accidentally alter their meaning, as in this example:++; 2 or more spaces needed here, so the period is not understood as "every 2 months in 2020"+; ||+; vv+~ every 2 months in 2020, we will review+ assets:bank:checking $1500+ income:acme inc+++File: hledger_journal.info, Node: Forecasting with periodic transactions, Next: Budgeting with periodic transactions, Prev: Two spaces after the period expression, Up: Periodic transactions++1.15.2 Forecasting with periodic transactions+---------------------------------------------+ With the '--forecast' flag, each periodic transaction rule generates future transactions recurring at the specified interval. These are not saved in the journal, but appear in all reports. They will look like@@ -1398,7 +1474,7 @@ File: hledger_journal.info, Node: Budgeting with periodic transactions, Prev: Forecasting with periodic transactions, Up: Periodic transactions -1.15.2 Budgeting with periodic transactions+1.15.3 Budgeting with periodic transactions ------------------------------------------- With the '--budget' flag, currently supported by the balance command,@@ -1412,15 +1488,16 @@ and Forecasting. -File: hledger_journal.info, Node: Transaction Modifiers, Prev: Periodic transactions, Up: FILE FORMAT+File: hledger_journal.info, Node: Transaction modifiers, Prev: Periodic transactions, Up: FILE FORMAT -1.16 Transaction Modifiers+1.16 Transaction modifiers ========================== Transaction modifier rules describe changes that should be applied-automatically to certain transactions. Currently, this means adding-extra postings (also known as "automated postings"). Transaction-modifiers are enabled by the '--auto' flag.+automatically to certain transactions. They can be enabled by using the+'--auto' flag. Currently, just one kind of change is possible: adding+extra postings. These rule-generated postings are known as "automated+postings" or "auto postings". A transaction modifier rule looks quite like a normal transaction, except the first line is an equals sign followed by a query that matches@@ -1432,8 +1509,8 @@ ACCT [AMT] ... - The posting rules look just like normal postings, except the amount-can be:+ These posting rules look like normal postings, except the amount can+be: * a normal amount with a commodity symbol, eg '$2'. This will be used as-is.@@ -1477,11 +1554,28 @@ assets:checking:gifts -$20 assets:checking $20 - Postings added by transaction modifiers participate in transaction-balancing, missing amount inference and balance assertions, like regular-postings.+* Menu: +* Auto postings and transaction balancing / inferred amounts / balance assertions::+ +File: hledger_journal.info, Node: Auto postings and transaction balancing / inferred amounts / balance assertions, Up: Transaction modifiers++1.16.1 Auto postings and transaction balancing / inferred amounts /+-------------------------------------------------------------------++balance assertions Currently, transaction modifiers are applied / auto+postings are added:++ * after missing amounts are inferred, and transactions are checked+ for balancedness,+ * but before balance assertions are checked.++ Note this means that journal entries must be balanced both before and+after auto postings are added. This changed in hledger 1.12+; see #893+for background.++ File: hledger_journal.info, Node: EDITOR SUPPORT, Prev: FILE FORMAT, Up: Top 2 EDITOR SUPPORT@@ -1539,69 +1633,81 @@ Ref: #virtual-postings15185 Node: Balance Assertions16405 Ref: #balance-assertions16580-Node: Assertions and ordering17476-Ref: #assertions-and-ordering17662-Node: Assertions and included files18362-Ref: #assertions-and-included-files18603-Node: Assertions and multiple -f options18936-Ref: #assertions-and-multiple--f-options19190-Node: Assertions and commodities19322-Ref: #assertions-and-commodities19557-Node: Assertions and subaccounts20745-Ref: #assertions-and-subaccounts20977-Node: Assertions and virtual postings21498-Ref: #assertions-and-virtual-postings21705-Node: Balance Assignments21847-Ref: #balance-assignments22028-Node: Transaction prices23148-Ref: #transaction-prices23317-Node: Comments25585-Ref: #comments25719-Node: Tags26889-Ref: #tags27007-Node: Directives28409-Ref: #directives28552-Node: Comment blocks34159-Ref: #comment-blocks34304-Node: Including other files34480-Ref: #including-other-files34660-Node: Default year35068-Ref: #default-year35237-Node: Declaring commodities35660-Ref: #declaring-commodities35843-Node: Default commodity37070-Ref: #default-commodity37246-Node: Market prices37882-Ref: #market-prices38047-Node: Declaring accounts38888-Ref: #declaring-accounts39064-Node: Account types40021-Ref: #account-types40170-Node: Account comments41244-Ref: #account-comments41429-Node: Account display order41750-Ref: #account-display-order41923-Node: Rewriting accounts43045-Ref: #rewriting-accounts43230-Node: Basic aliases43964-Ref: #basic-aliases44110-Node: Regex aliases44814-Ref: #regex-aliases44985-Node: Multiple aliases45703-Ref: #multiple-aliases45878-Node: end aliases46376-Ref: #end-aliases46523-Node: Default parent account46624-Ref: #default-parent-account46790-Node: Periodic transactions47674-Ref: #periodic-transactions47856-Node: Forecasting with periodic transactions49559-Ref: #forecasting-with-periodic-transactions49802-Node: Budgeting with periodic transactions51489-Ref: #budgeting-with-periodic-transactions51728-Node: Transaction Modifiers52187-Ref: #transaction-modifiers52350-Node: EDITOR SUPPORT54331-Ref: #editor-support54449+Node: Assertions and ordering17531+Ref: #assertions-and-ordering17717+Node: Assertions and included files18417+Ref: #assertions-and-included-files18658+Node: Assertions and multiple -f options18991+Ref: #assertions-and-multiple--f-options19245+Node: Assertions and commodities19377+Ref: #assertions-and-commodities19607+Node: Assertions and prices20795+Ref: #assertions-and-prices21007+Node: Assertions and subaccounts21447+Ref: #assertions-and-subaccounts21674+Node: Assertions and virtual postings22195+Ref: #assertions-and-virtual-postings22435+Node: Assertions and precision22577+Ref: #assertions-and-precision22768+Node: Balance Assignments23035+Ref: #balance-assignments23216+Node: Balance assignments and prices24380+Ref: #balance-assignments-and-prices24552+Node: Transaction prices24776+Ref: #transaction-prices24945+Node: Comments27213+Ref: #comments27347+Node: Tags28517+Ref: #tags28635+Node: Directives30037+Ref: #directives30180+Node: Comment blocks35787+Ref: #comment-blocks35932+Node: Including other files36108+Ref: #including-other-files36288+Node: Default year36696+Ref: #default-year36865+Node: Declaring commodities37288+Ref: #declaring-commodities37471+Node: Default commodity38698+Ref: #default-commodity38874+Node: Market prices39510+Ref: #market-prices39675+Node: Declaring accounts40516+Ref: #declaring-accounts40692+Node: Account comments41617+Ref: #account-comments41780+Node: Account subdirectives42175+Ref: #account-subdirectives42370+Node: Account types42683+Ref: #account-types42867+Node: Account display order44511+Ref: #account-display-order44681+Node: Rewriting accounts45810+Ref: #rewriting-accounts45995+Node: Basic aliases46729+Ref: #basic-aliases46875+Node: Regex aliases47579+Ref: #regex-aliases47750+Node: Multiple aliases48468+Ref: #multiple-aliases48643+Node: end aliases49141+Ref: #end-aliases49288+Node: Default parent account49389+Ref: #default-parent-account49555+Node: Periodic transactions50439+Ref: #periodic-transactions50621+Node: Two spaces after the period expression51746+Ref: #two-spaces-after-the-period-expression51991+Node: Forecasting with periodic transactions52476+Ref: #forecasting-with-periodic-transactions52766+Node: Budgeting with periodic transactions54453+Ref: #budgeting-with-periodic-transactions54692+Node: Transaction modifiers55151+Ref: #transaction-modifiers55314+Node: Auto postings and transaction balancing / inferred amounts / balance assertions57298+Ref: #auto-postings-and-transaction-balancing-inferred-amounts-balance-assertions57599+Node: EDITOR SUPPORT57977+Ref: #editor-support58095 End Tag Table
hledger_journal.txt view
@@ -446,8 +446,21 @@ a:usd 0 == $1 a:euro 0 == 1 + Assertions and prices+ Balance assertions ignore transaction prices, and should normally be+ written without one:++ 2019/1/1+ (a) $1 @ 1 = $1++ We do allow prices to be written there, however, and print shows them,+ even though they don't affect whether the assertion passes or fails.+ This is for backward compatibility (hledger's close command used to+ generate balance assertions with prices), and because balance assign-+ ments do use them (see below).+ Assertions and subaccounts- Balance assertions do not count the balance from subaccounts; they+ Balance assertions do not count the balance from subaccounts; they check the posted account's exclusive balance. For example: 1/1@@ -455,7 +468,7 @@ checking 1 = 1 ; post to the parent account, its exclusive balance is now 1 equity - The balance report's flat mode shows these exclusive balances more+ The balance report's flat mode shows these exclusive balances more clearly: $ hledger bal checking --flat@@ -468,6 +481,12 @@ Balance assertions are checked against all postings, both real and vir- tual. They are not affected by the --real/-R flag or real: query. + Assertions and precision+ Balance assertions compare the exactly calculated amounts, which are+ not always what is shown by reports. Eg a commodity directive may+ limit the display precision, but this will not affect balance asser-+ tions. Balance assertion failure messages show exact amounts.+ Balance Assignments Ledger-style balance assignments are also supported. These are like balance assertions, but with no posting amount on the left side of the@@ -496,11 +515,22 @@ less explicit; to know the exact amount posted, you have to run hledger or do the calculations yourself, instead of just reading it. + Balance assignments and prices+ A transaction price in a balance assignment will cause the calculated+ amount to have that price attached:++ 2019/1/1+ (a) = $1 @ 2++ $ hledger print --explicit+ 2019/01/01+ (a) $1 @ 2 = $1 @ 2+ Transaction prices Within a transaction, you can note an amount's price in another commod-- ity. This can be used to document the cost (in a purchase) or selling- price (in a sale). For example, transaction prices are useful to- record purchases of a foreign currency. Note transaction prices are+ ity. This can be used to document the cost (in a purchase) or selling+ price (in a sale). For example, transaction prices are useful to+ record purchases of a foreign currency. Note transaction prices are fixed at the time of the transaction, and do not change over time. See also market prices, which represent prevailing exchange rates on a cer- tain date.@@ -529,7 +559,7 @@ (Ledger users: Ledger uses a different syntax for fixed prices, {=UNIT- PRICE}, which hledger currently ignores). - Use the -B/--cost flag to convert amounts to their transaction price's+ Use the -B/--cost flag to convert amounts to their transaction price's commodity, if any. (mnemonic: "B" is from "cost Basis", as in Ledger). Eg here is how -B affects the balance report for the example above: @@ -540,8 +570,8 @@ $-135 assets:dollars $135 assets:euros # <- the euros' cost - Note -B is sensitive to the order of postings when a transaction price- is inferred: the inferred price will be in the commodity of the last+ Note -B is sensitive to the order of postings when a transaction price+ is inferred: the inferred price will be in the commodity of the last amount. So if example 3's postings are reversed, while the transaction is equivalent, -B shows something different: @@ -555,14 +585,14 @@ Comments Lines in the journal beginning with a semicolon (;) or hash (#) or star- (*) are comments, and will be ignored. (Star comments cause org-mode- nodes to be ignored, allowing emacs users to fold and navigate their+ (*) are comments, and will be ignored. (Star comments cause org-mode+ nodes to be ignored, allowing emacs users to fold and navigate their journals with org-mode or orgstruct-mode.) - You can attach comments to a transaction by writing them after the- description and/or indented on the following lines (before the post-- ings). Similarly, you can attach comments to an individual posting by- writing them after the amount and/or indented on the following lines.+ You can attach comments to a transaction by writing them after the+ description and/or indented on the following lines (before the post-+ ings). Similarly, you can attach comments to an individual posting by+ writing them after the amount and/or indented on the following lines. Transaction and posting comments must begin with a semicolon (;). Some examples:@@ -586,24 +616,24 @@ ; another comment line for posting 2 ; a file comment (because not indented) - You can also comment larger regions of a file using comment and+ You can also comment larger regions of a file using comment and end comment directives. Tags- Tags are a way to add extra labels or labelled data to postings and+ Tags are a way to add extra labels or labelled data to postings and transactions, which you can then search or pivot on. - A simple tag is a word (which may contain hyphens) followed by a full+ A simple tag is a word (which may contain hyphens) followed by a full colon, written inside a transaction or posting comment line: 2017/1/16 bought groceries ; sometag: - Tags can have a value, which is the text after the colon, up to the+ Tags can have a value, which is the text after the colon, up to the next comma or end of line, with leading/trailing whitespace removed: expenses:food $10 ; a-posting-tag: the tag value - Note this means hledger's tag values can not contain commas or new-+ Note this means hledger's tag values can not contain commas or new- lines. Ending at commas means you can write multiple short tags on one line, comma separated: @@ -617,78 +647,69 @@ o "tag2" is another tag, whose value is "some value ..." - Tags in a transaction comment affect the transaction and all of its- postings, while tags in a posting comment affect only that posting.- For example, the following transaction has three tags (A, TAG2,+ Tags in a transaction comment affect the transaction and all of its+ postings, while tags in a posting comment affect only that posting.+ For example, the following transaction has three tags (A, TAG2, third-tag) and the posting has four (those plus posting-tag): 1/1 a transaction ; A:, TAG2: ; third-tag: a third transaction tag, <- with a value (a) $1 ; posting-tag: - Tags are like Ledger's metadata feature, except hledger's tag values+ Tags are like Ledger's metadata feature, except hledger's tag values are simple strings. Directives- A directive is a line in the journal beginning with a special keyword,+ A directive is a line in the journal beginning with a special keyword, that influences how the journal is processed. hledger's directives are based on a subset of Ledger's, but there are many differences (and also some differences between hledger versions). Directives' behaviour and interactions can get a little bit complex, so- here is a table summarising the directives and their effects, with+ here is a table summarising the directives and their effects, with links to more detailed docs. - direc- end subdi- purpose can affect (as of++++ direc- end subdi- purpose can affect (as of tive directive rec- 2018/06) tives -------------------------------------------------------------------------------------------------- account any document account names, all entries in all- text declare account types & dis- files, before or+ account any document account names, all entries in all+ text declare account types & dis- files, before or play order after alias end aliases rewrite account names following inline/included entries until end- of current file or+ of current file or end directive- apply account end apply account prepend a common parent to following+ apply account end apply account prepend a common parent to following account names inline/included entries until end- of current file or+ of current file or end directive comment end comment ignore part of journal following inline/included entries until end- of current file or+ of current file or end directive- commodity format declare a commodity and its number notation:+ commodity format declare a commodity and its number notation: number notation & display following entries style in that commodity- in all files; dis-+ in all files; dis- play style: amounts of that commodity in reports------------- D declare a commodity, number commodity: all com-+ D declare a commodity, number commodity: all com- notation & display style for modityless entries- commodityless amounts in all files; num-- ber notation: fol-+ commodityless amounts in all files; num-+ ber notation: fol- lowing commodity-- less entries and+ less entries and entries in that- commodity in all+ commodity in all files; display style: amounts of that commodity in@@ -699,7 +720,7 @@ commodity commodity in reports, when -V is used- Y declare a year for yearless following+ Y declare a year for yearless following dates inline/included entries until end of current file@@ -709,9 +730,9 @@ subdirec- optional indented directive line immediately following a par- tive ent directive- number how to interpret numbers when parsing journal entries (the- notation identity of the decimal separator character). (Currently- each commodity can have its own notation, even in the same+ number how to interpret numbers when parsing journal entries (the+ notation identity of the decimal separator character). (Currently+ each commodity can have its own notation, even in the same file.) display how to display amounts of a commodity in reports (symbol side style and spacing, digit groups, decimal separator, decimal places)@@ -719,37 +740,37 @@ scope are affected by a directive As you can see, directives vary in which journal entries and files they- affect, and whether they are focussed on input (parsing) or output+ affect, and whether they are focussed on input (parsing) or output (reports). Some directives have multiple effects. - If you have a journal made up of multiple files, or pass multiple -f- options on the command line, note that directives which affect input- typically last only until the end of their defining file. This pro-+ If you have a journal made up of multiple files, or pass multiple -f+ options on the command line, note that directives which affect input+ typically last only until the end of their defining file. This pro- vides more simplicity and predictability, eg reports are not changed by- writing file options in a different order. It can be surprising at+ writing file options in a different order. It can be surprising at times though. Comment blocks- A line containing just comment starts a commented region of the file,+ A line containing just comment starts a commented region of the file, and a line containing just end comment (or the end of the current file) ends it. See also comments. Including other files- You can pull in the content of additional files by writing an include+ You can pull in the content of additional files by writing an include directive, like this: include path/to/file.journal - If the path does not begin with a slash, it is relative to the current- file. The include file path may contain common glob patterns (e.g.+ If the path does not begin with a slash, it is relative to the current+ file. The include file path may contain common glob patterns (e.g. *). - The include directive can only be used in journal files. It can+ The include directive can only be used in journal files. It can include journal, timeclock or timedot files, but not CSV files. Default year- You can set a default year to be used for subsequent dates which don't- specify a year. This is a line beginning with Y followed by the year.+ You can set a default year to be used for subsequent dates which don't+ specify a year. This is a line beginning with Y followed by the year. Eg: Y2009 ; set default year to 2009@@ -769,8 +790,8 @@ assets Declaring commodities- The commodity directive declares commodities which may be used in the- journal (though currently we do not enforce this). It may be written+ The commodity directive declares commodities which may be used in the+ journal (though currently we do not enforce this). It may be written on a single line, like this: ; commodity EXAMPLEAMOUNT@@ -780,8 +801,8 @@ ; separating thousands with comma. commodity 1,000.0000 AAAA - or on multiple lines, using the "format" subdirective. In this case- the commodity symbol appears twice and should be the same in both+ or on multiple lines, using the "format" subdirective. In this case+ the commodity symbol appears twice and should be the same in both places: ; commodity SYMBOL@@ -793,19 +814,19 @@ commodity INR format INR 9,99,99,999.00 - Commodity directives have a second purpose: they define the standard+ Commodity directives have a second purpose: they define the standard display format for amounts in the commodity. Normally the display for-- mat is inferred from journal entries, but this can be unpredictable;- declaring it with a commodity directive overrides this and removes- ambiguity. Towards this end, amounts in commodity directives must- always be written with a decimal point (a period or comma, followed by+ mat is inferred from journal entries, but this can be unpredictable;+ declaring it with a commodity directive overrides this and removes+ ambiguity. Towards this end, amounts in commodity directives must+ always be written with a decimal point (a period or comma, followed by 0 or more decimal digits). Default commodity- The D directive sets a default commodity (and display format), to be+ The D directive sets a default commodity (and display format), to be used for amounts without a commodity symbol (ie, plain numbers). (Note- this differs from Ledger's default commodity directive.) The commodity- and display format will be applied to all subsequent commodity-less+ this differs from Ledger's default commodity directive.) The commodity+ and display format will be applied to all subsequent commodity-less amounts, or until the next D directive. # commodity-less amounts should be treated as dollars@@ -820,9 +841,9 @@ a decimal point. Market prices- The P directive declares a market price, which is an exchange rate+ The P directive declares a market price, which is an exchange rate between two commodities on a certain date. (In Ledger, they are called- "historical prices".) These are often obtained from a stock exchange,+ "historical prices".) These are often obtained from a stock exchange, cryptocurrency exchange, or the foreign exchange market. Here is the format:@@ -833,97 +854,117 @@ o COMMODITYA is the symbol of the commodity being priced - o COMMODITYBAMOUNT is an amount (symbol and quantity) in a second com-+ o COMMODITYBAMOUNT is an amount (symbol and quantity) in a second com- modity, giving the price in commodity B of one unit of commodity A. - These two market price directives say that one euro was worth 1.35 US+ These two market price directives say that one euro was worth 1.35 US dollars during 2009, and $1.40 from 2010 onward: P 2009/1/1 $1.35 P 2010/1/1 $1.40 - The -V/--value flag can be used to convert reported amounts to another+ The -V/--value flag can be used to convert reported amounts to another commodity using these prices. Declaring accounts- account directives can be used to pre-declare some or all accounts.- Though not required, they can provide several benefits:+ account directives can be used to pre-declare accounts. Though not+ required, they can provide several benefits: o They can document your intended chart of accounts, providing a refer- ence. - o They can store extra information about accounts (account numbers,+ o They can store extra information about accounts (account numbers, notes, etc.) - o They can help hledger know your accounts' types (asset, liability,- equity, revenue, expense), useful for reports like balancesheet and+ o They can help hledger know your accounts' types (asset, liability,+ equity, revenue, expense), useful for reports like balancesheet and incomestatement. - o They control account display order in reports, allowing non-alpha-+ o They control account display order in reports, allowing non-alpha- betic sorting (eg Revenues to appear above Expenses). - o They help with account name completion in the add command,+ o They help with account name completion in the add command, hledger-iadd, hledger-web, ledger-mode etc. - Here is the full syntax:+ The simplest form is just the word account followed by a hledger-style+ account name, eg: - account ACCTNAME [ACCTTYPE]- [COMMENTS]+ account assets:bank:checking - The simplest form just declares a hledger-style account name, eg:+ Account comments+ Comments, beginning with a semicolon, optionally including tags, can be+ written after the account name, and/or on following lines. Eg: + account assets:bank:checking ; a comment+ ; another comment+ ; acctno:12345, a tag++ Tip: comments on the same line require hledger 1.12+. If you need your+ journal to be compatible with older hledger versions, write comments on+ the next line instead.++ Account subdirectives+ We also allow (and ignore) Ledger-style indented subdirectives, just+ for compatibility.:+ account assets:bank:checking+ format blah blah ; <- subdirective, ignored + Here is the full syntax of account directives:++ account ACCTNAME [ACCTTYPE] [;COMMENT]+ [;COMMENTS]+ [LEDGER-STYLE SUBDIRECTIVES, IGNORED]+ Account types- hledger recognises five types of account: asset, liability, equity,- revenue, expense. This is useful for certain accounting-aware reports,- in particular balancesheet, incomestatement and cashflow.+ hledger recognises five types (or classes) of account: Asset, Liabil-+ ity, Equity, Revenue, Expense. This is used by a few accounting-aware+ reports such as balancesheet, incomestatement and cashflow. + Auto-detected account types If you name your top-level accounts with some variation of assets, lia- bilities/debts, equity, revenues/income, or expenses, their types are detected automatically. - More generally, you can declare an account's type by adding one of the- letters ALERX to its account directive, separated from the account name- by two or more spaces. Eg:+ Account types declared with tags+ More generally, you can declare an account's type with an account+ directive, by writing a type: tag in a comment, followed by one of the+ words Asset, Liability, Equity, Revenue, Expense, or one of the letters+ ALERX (case insensitive): + account assets ; type:Asset+ account liabilities ; type:Liability+ account equity ; type:Equity+ account revenues ; type:Revenue+ account expenses ; type:Expenses++ Account types declared with account type codes+ Or, you can write one of those letters separated from the account name+ by two or more spaces, but this should probably be considered depre-+ cated as of hledger 1.13:+ account assets A account liabilities L account equity E account revenues R account expenses X - Note: if you ever override the types of those auto-detected english- account names mentioned above, you might need to help the reports a- bit:+ Overriding auto-detected types+ If you ever override the types of those auto-detected english account+ names mentioned above, you might need to help the reports a bit. Eg: - ; make "liabilities" not have the liability type, who knows why- account liabilities E+ ; make "liabilities" not have the liability type - who knows why+ account liabilities ; type:E - ; better ensure some other account has the liability type,+ ; we need to ensure some other account has the liability type, ; otherwise balancesheet would still show "liabilities" under Liabilities- account - L-- )-- Account comments- An account directive can also have indented comments on following- lines, eg:-- account assets:bank:checking- ; acctno:12345- ; a comment-- We also allow (and ignore) Ledger-style subdirectives, with no leading- semicolon, for compatibility.-- Tags in account comments, like acctno above, currently have no effect.+ account - ; type:L Account display order- Account directives also set the order in which accounts are displayed- in reports, the hledger-ui accounts screen, the hledger-web sidebar,- etc. Normally accounts are listed in alphabetical order, but if you- have eg these account directives in the journal:+ Account directives also set the order in which accounts are displayed,+ eg in reports, the hledger-ui accounts screen, and the hledger-web+ sidebar. By default accounts are listed in alphabetical order. But if+ you have these account directives in the journal: account assets account liabilities@@ -931,8 +972,8 @@ account revenues account expenses - you'll see those accounts listed in declaration order, not alphabeti-- cally:+ you'll see those accounts displayed in declaration order, not alphabet-+ ically: $ hledger accounts -1 assets@@ -943,16 +984,16 @@ Undeclared accounts, if any, are displayed last, in alphabetical order. - Note that sorting is done at each level of the account tree (within- each group of sibling accounts under the same parent). And currently,+ Note that sorting is done at each level of the account tree (within+ each group of sibling accounts under the same parent). And currently, this directive: account other:zoo - would influence the position of zoo among other's subaccounts, but not- the position of other among the top-level accounts. This means: - you- will sometimes declare parent accounts (eg account other above) that- you don't intend to post to, just to customize their display order -+ would influence the position of zoo among other's subaccounts, but not+ the position of other among the top-level accounts. This means: - you+ will sometimes declare parent accounts (eg account other above) that+ you don't intend to post to, just to customize their display order - sibling accounts stay together (you couldn't display x:y in between a:b and a:c). @@ -971,14 +1012,14 @@ o customising reports Account aliases also rewrite account names in account directives. They- do not affect account names being entered via hledger add or+ do not affect account names being entered via hledger add or hledger-web. See also Cookbook: Rewrite account names. Basic aliases- To set an account alias, use the alias directive in your journal file.- This affects all subsequent journal entries in the current file or its+ To set an account alias, use the alias directive in your journal file.+ This affects all subsequent journal entries in the current file or its included files. The spaces around the = are optional: alias OLD = NEW@@ -986,54 +1027,54 @@ Or, you can use the --alias 'OLD=NEW' option on the command line. This affects all entries. It's useful for trying out aliases interactively. - OLD and NEW are case sensitive full account names. hledger will- replace any occurrence of the old account name with the new one. Sub-+ OLD and NEW are case sensitive full account names. hledger will+ replace any occurrence of the old account name with the new one. Sub- accounts are also affected. Eg: alias checking = assets:bank:wells fargo:checking # rewrites "checking" to "assets:bank:wells fargo:checking", or "checking:a" to "assets:bank:wells fargo:checking:a" Regex aliases- There is also a more powerful variant that uses a regular expression,+ There is also a more powerful variant that uses a regular expression, indicated by the forward slashes: alias /REGEX/ = REPLACEMENT or --alias '/REGEX/=REPLACEMENT'. - REGEX is a case-insensitive regular expression. Anywhere it matches- inside an account name, the matched part will be replaced by REPLACE-- MENT. If REGEX contains parenthesised match groups, these can be ref-+ REGEX is a case-insensitive regular expression. Anywhere it matches+ inside an account name, the matched part will be replaced by REPLACE-+ MENT. If REGEX contains parenthesised match groups, these can be ref- erenced by the usual numeric backreferences in REPLACEMENT. Eg: alias /^(.+):bank:([^:]+)(.*)/ = \1:\2 \3 # rewrites "assets:bank:wells fargo:checking" to "assets:wells fargo checking" - Also note that REPLACEMENT continues to the end of line (or on command- line, to end of option argument), so it can contain trailing white-+ Also note that REPLACEMENT continues to the end of line (or on command+ line, to end of option argument), so it can contain trailing white- space. Multiple aliases- You can define as many aliases as you like using directives or com-- mand-line options. Aliases are recursive - each alias sees the result- of applying previous ones. (This is different from Ledger, where+ You can define as many aliases as you like using directives or com-+ mand-line options. Aliases are recursive - each alias sees the result+ of applying previous ones. (This is different from Ledger, where aliases are non-recursive by default). Aliases are applied in the fol- lowing order: - 1. alias directives, most recently seen first (recent directives take+ 1. alias directives, most recently seen first (recent directives take precedence over earlier ones; directives not yet seen are ignored) 2. alias options, in the order they appear on the command line end aliases- You can clear (forget) all currently defined aliases with the+ You can clear (forget) all currently defined aliases with the end aliases directive: end aliases Default parent account- You can specify a parent account which will be prepended to all- accounts within a section of the journal. Use the apply account and+ You can specify a parent account which will be prepended to all+ accounts within a section of the journal. Use the apply account and end apply account directives like so: apply account home@@ -1050,7 +1091,7 @@ home:food $10 home:cash $-10 - If end apply account is omitted, the effect lasts to the end of the+ If end apply account is omitted, the effect lasts to the end of the file. Included files are also affected, eg: apply account business@@ -1059,18 +1100,18 @@ apply account personal include personal.journal - Prior to hledger 1.0, legacy account and end spellings were also sup-+ Prior to hledger 1.0, legacy account and end spellings were also sup- ported. - A default parent account also affects account directives. It does not- affect account names being entered via hledger add or hledger-web. If- account aliases are present, they are applied after the default parent+ A default parent account also affects account directives. It does not+ affect account names being entered via hledger add or hledger-web. If+ account aliases are present, they are applied after the default parent account. Periodic transactions- Periodic transaction rules describe transactions that recur. They+ Periodic transaction rules describe transactions that recur. They allow you to generate future transactions for forecasting, without hav-- ing to write them out explicitly in the journal (with --forecast).+ ing to write them out explicitly in the journal (with --forecast). Secondly, they also can be used to define budget goals (with --budget). A periodic transaction rule looks like a normal journal entry, with the@@ -1081,85 +1122,85 @@ expenses:rent $2000 assets:bank:checking - There is an additional constraint on the period expression: the start- date must fall on a natural boundary of the interval. Eg+ There is an additional constraint on the period expression: the start+ date must fall on a natural boundary of the interval. Eg monthly from 2018/1/1 is valid, but monthly from 2018/1/15 is not. - Partial or relative dates (M/D, D, tomorrow, last week) in the period- expression can work (useful or not). They will be relative to today's- date, unless a Y default year directive is in effect, in which case+ Partial or relative dates (M/D, D, tomorrow, last week) in the period+ expression can work (useful or not). They will be relative to today's+ date, unless a Y default year directive is in effect, in which case they will be relative to Y/1/1. - Period expressions must be terminated by two or more spaces if followed- by additional fields. For example, the periodic transaction given- below includes a transaction description "paycheck", which is separated- from the period expression by a double space. If not for the second- space, hledger would attempt (and fail) to parse "paycheck" as a part- of the period expression.+ Two spaces after the period expression+ If the period expression is followed by a transaction description,+ these must be separated by two or more spaces. This helps hledger know+ where the period expression ends, so that descriptions can not acciden-+ tally alter their meaning, as in this example: - ; 2 or more spaces- ; ||- ; vv- ~ every 2 weeks from 2018/6/4 to 2018/9 paycheck+ ; 2 or more spaces needed here, so the period is not understood as "every 2 months in 2020"+ ; ||+ ; vv+ ~ every 2 months in 2020, we will review assets:bank:checking $1500 income:acme inc Forecasting with periodic transactions- With the --forecast flag, each periodic transaction rule generates+ With the --forecast flag, each periodic transaction rule generates future transactions recurring at the specified interval. These are not- saved in the journal, but appear in all reports. They will look like- normal transactions, but with an extra tag named recur, whose value is+ saved in the journal, but appear in all reports. They will look like+ normal transactions, but with an extra tag named recur, whose value is the generating period expression. - Forecast transactions start on the first occurrence, and end on the- last occurrence, of their interval within the forecast period. The+ Forecast transactions start on the first occurrence, and end on the+ last occurrence, of their interval within the forecast period. The forecast period: o begins on the later of o the report start date if specified with -b/-p/date: - o the day after the latest normal (non-periodic) transaction in the+ o the day after the latest normal (non-periodic) transaction in the journal, or today if there are no normal transactions. - o ends on the report end date if specified with -e/-p/date:, or 180+ o ends on the report end date if specified with -e/-p/date:, or 180 days from today. - where "today" means the current date at report time. The "later of"- rule ensures that forecast transactions do not overlap normal transac-+ where "today" means the current date at report time. The "later of"+ rule ensures that forecast transactions do not overlap normal transac- tions in time; they will begin only after normal transactions end. - Forecasting can be useful for estimating balances into the future, and- experimenting with different scenarios. Note the start date logic+ Forecasting can be useful for estimating balances into the future, and+ experimenting with different scenarios. Note the start date logic means that forecasted transactions are automatically replaced by normal transactions as you add those. Forecasting can also help with data entry: describe most of your trans-- actions with periodic rules, and every so often copy the output of+ actions with periodic rules, and every so often copy the output of print --forecast to the journal. You can generate one-time transactions too: just write a period expres-- sion specifying a date with no report interval. (You could also write- a normal transaction with a future date, but remember this disables+ sion specifying a date with no report interval. (You could also write+ a normal transaction with a future date, but remember this disables forecast transactions on previous dates.) Budgeting with periodic transactions- With the --budget flag, currently supported by the balance command,- each periodic transaction rule declares recurring budget goals for the- specified accounts. Eg the first example above declares a goal of- spending $2000 on rent (and also, a goal of depositing $2000 into- checking) every month. Goals and actual performance can then be com-+ With the --budget flag, currently supported by the balance command,+ each periodic transaction rule declares recurring budget goals for the+ specified accounts. Eg the first example above declares a goal of+ spending $2000 on rent (and also, a goal of depositing $2000 into+ checking) every month. Goals and actual performance can then be com- pared in budget reports. - For more details, see: balance: Budget report and Cookbook: Budgeting+ For more details, see: balance: Budget report and Cookbook: Budgeting and Forecasting. - Transaction Modifiers- Transaction modifier rules describe changes that should be applied- automatically to certain transactions. Currently, this means adding- extra postings (also known as "automated postings"). Transaction modi-- fiers are enabled by the --auto flag.+ Transaction modifiers+ Transaction modifier rules describe changes that should be applied+ automatically to certain transactions. They can be enabled by using+ the --auto flag. Currently, just one kind of change is possible:+ adding extra postings. These rule-generated postings are known as+ "automated postings" or "auto postings". A transaction modifier rule looks quite like a normal transaction, except the first line is an equals sign followed by a query that@@ -1171,7 +1212,7 @@ ACCT [AMT] ... - The posting rules look just like normal postings, except the amount can+ These posting rules look like normal postings, except the amount can be: o a normal amount with a commodity symbol, eg $2. This will be used@@ -1219,10 +1260,20 @@ assets:checking:gifts -$20 assets:checking $20 - Postings added by transaction modifiers participate in transaction bal-- ancing, missing amount inference and balance assertions, like regular- postings.+ Auto postings and transaction balancing / inferred amounts / balance+ assertions + Currently, transaction modifiers are applied / auto postings are added:++ o after missing amounts are inferred, and transactions are checked for+ balancedness,++ o but before balance assertions are checked.++ Note this means that journal entries must be balanced both before and+ after auto postings are added. This changed in hledger 1.12+; see #893+ for background.+ EDITOR SUPPORT Add-on modes exist for various text editors, to make working with jour- nal files easier. They add colour, navigation aids and helpful com-@@ -1240,6 +1291,7 @@ Sublime Text https://github.com/ledger/ledger/wiki/Edit- ing-Ledger-files-with-Sublime-Text-or-RubyMine Textmate https://github.com/ledger/ledger/wiki/Using-TextMate-2+ Text Wran- https://github.com/ledger/ledger/wiki/Edit- gler ing-Ledger-files-with-TextWrangler Visual Stu- https://marketplace.visualstudio.com/items?item-@@ -1270,4 +1322,4 @@ -hledger 1.12 December 2018 hledger_journal(5)+hledger 1.13 February 2019 hledger_journal(5)
hledger_timeclock.5 view
@@ -1,5 +1,5 @@ -.TH "hledger_timeclock" "5" "December 2018" "hledger 1.12" "hledger User Manuals"+.TH "hledger_timeclock" "5" "February 2019" "hledger 1.13" "hledger User Manuals" @@ -9,7 +9,7 @@ .SH DESCRIPTION .PP hledger can read timeclock files.-As with Ledger, these are (a subset of) timeclock.el's format,+As with Ledger, these are (a subset of) timeclock.el\[aq]s format, containing clock\-in and clock\-out entries as in the example below. The date is a simple date. The time format is HH:MM[:SS][+\-ZZZZ].@@ -67,8 +67,8 @@ .IP \[bu] 2 or use the old \f[C]ti\f[] and \f[C]to\f[] scripts in the ledger 2.x repository.-These rely on a \[lq]timeclock\[rq] executable which I think is just the-ledger 2 executable renamed.+These rely on a "timeclock" executable which I think is just the ledger+2 executable renamed. .SH "REPORTING BUGS"
hledger_timeclock.info view
@@ -4,7 +4,7 @@ File: hledger_timeclock.info, Node: Top, Up: (dir) -hledger_timeclock(5) hledger 1.12+hledger_timeclock(5) hledger 1.13 ********************************* hledger can read timeclock files. As with Ledger, these are (a subset
hledger_timeclock.txt view
@@ -77,4 +77,4 @@ -hledger 1.12 December 2018 hledger_timeclock(5)+hledger 1.13 February 2019 hledger_timeclock(5)
hledger_timedot.5 view
@@ -1,11 +1,11 @@ -.TH "hledger_timedot" "5" "December 2018" "hledger 1.12" "hledger User Manuals"+.TH "hledger_timedot" "5" "February 2019" "hledger 1.13" "hledger User Manuals" .SH NAME .PP-Timedot \- hledger's human\-friendly time logging format+Timedot \- hledger\[aq]s human\-friendly time logging format .SH DESCRIPTION .PP Timedot is a plain text format for logging dated, categorised quantities@@ -16,10 +16,10 @@ It can be formatted like a bar chart, making clear at a glance where time was spent. .PP-Though called \[lq]timedot\[rq], this format is read by hledger as-commodityless quantities, so it could be used to represent dated-quantities other than time.-In the docs below we'll assume it's time.+Though called "timedot", this format is read by hledger as commodityless+quantities, so it could be used to represent dated quantities other than+time.+In the docs below we\[aq]ll assume it\[aq]s time. .SH FILE FORMAT .PP A timedot file contains a series of day entries.@@ -34,7 +34,7 @@ .IP \[bu] 2 a sequence of dots (.) representing quarter hours. Spaces may optionally be used for grouping and readability.-Eg: \&....+Eg: .... \&.. .IP \[bu] 2 an integral or decimal number, representing hours.
hledger_timedot.info view
@@ -4,7 +4,7 @@ File: hledger_timedot.info, Node: Top, Next: FILE FORMAT, Up: (dir) -hledger_timedot(5) hledger 1.12+hledger_timedot(5) hledger 1.13 ******************************* Timedot is a plain text format for logging dated, categorised quantities
hledger_timedot.txt view
@@ -124,4 +124,4 @@ -hledger 1.12 December 2018 hledger_timedot(5)+hledger 1.13 February 2019 hledger_timedot(5)