diff --git a/Hledger/Cli/Commands/Register.hs b/Hledger/Cli/Commands/Register.hs index 7641234d6..e3fde1019 100644 --- a/Hledger/Cli/Commands/Register.hs +++ b/Hledger/Cli/Commands/Register.hs @@ -75,12 +75,14 @@ registerReport :: [Opt] -> FilterSpec -> Journal -> RegisterReport registerReport opts fspec j = getitems ps nullposting startbal where ps | interval == NoInterval = displayableps - | otherwise = summarisePostings interval depth empty filterspan displayableps - (precedingps, displayableps, _) = - postingsMatchingDisplayExpr (displayExprFromOpts opts) $ journalPostings $ filterJournalPostings fspec j + | otherwise = summarisePostingsByInterval interval depth empty filterspan displayableps + (precedingps, displayableps, _) = postingsMatchingDisplayExpr (displayExprFromOpts opts) + $ depthClipPostings depth + $ journalPostings + $ filterJournalPostings fspec{depth=Nothing} j startbal = sumPostings precedingps - (interval, depth, empty) = (intervalFromOpts opts, depthFromOpts opts, Empty `elem` opts) filterspan = datespan fspec + (interval, depth, empty) = (intervalFromOpts opts, depthFromOpts opts, Empty `elem` opts) -- | Generate register report line items. getitems :: [Posting] -> Posting -> MixedAmount -> [RegisterReportItem] @@ -100,16 +102,6 @@ mkitem True p b = (ds, p, b) where ds = case ptransaction p of Just (Transaction{tdate=da,tdescription=de}) -> Just (da,de) Nothing -> Just (nulldate,"") --- | Convert a list of postings into summary postings, one per interval. -summarisePostings :: Interval -> Maybe Int -> Bool -> DateSpan -> [Posting] -> [Posting] -summarisePostings interval depth empty filterspan ps = concatMap summarisespan $ splitSpan interval reportspan - where - summarisespan s = summarisePostingsInDateSpan s depth empty (postingsinspan s) - postingsinspan s = filter (isPostingInDateSpan s) ps - dataspan = postingsDateSpan ps - reportspan | empty = filterspan `orDatesFrom` dataspan - | otherwise = dataspan - -- | Date-sort and split a list of postings into three spans - postings matched -- by the given display expression, and the preceding and following postings. postingsMatchingDisplayExpr :: Maybe String -> [Posting] -> ([Posting],[Posting],[Posting]) @@ -148,6 +140,19 @@ datedisplayexpr = do compareop = choice $ map (try . string) ["<=",">=","==","<","=",">"] -- XXX confusing, refactor + +-- | Convert a list of postings into summary postings. Summary postings +-- are one per account per interval and aggregated to the specified depth +-- if any. +summarisePostingsByInterval :: Interval -> Maybe Int -> Bool -> DateSpan -> [Posting] -> [Posting] +summarisePostingsByInterval interval depth empty filterspan ps = concatMap summarisespan $ splitSpan interval reportspan + where + summarisespan s = summarisePostingsInDateSpan s depth empty (postingsinspan s) + postingsinspan s = filter (isPostingInDateSpan s) ps + dataspan = postingsDateSpan ps + reportspan | empty = filterspan `orDatesFrom` dataspan + | otherwise = dataspan + -- | Given a date span (representing a reporting interval) and a list of -- postings within it: aggregate the postings so there is only one per -- account, and adjust their date/description so that they will render @@ -159,8 +164,8 @@ datedisplayexpr = do -- When a depth argument is present, postings to accounts of greater -- depth are aggregated where possible. -- --- The showempty flag forces the display of a zero-posting span --- and also zero-posting accounts within the span. +-- The showempty flag includes spans with no postings and also postings +-- with 0 amount. summarisePostingsInDateSpan :: DateSpan -> Maybe Int -> Bool -> [Posting] -> [Posting] summarisePostingsInDateSpan (DateSpan b e) depth showempty ps | null ps && (isNothing b || isNothing e) = [] @@ -183,10 +188,20 @@ summarisePostingsInDateSpan (DateSpan b e) depth showempty ps balancetoshowfor a = (if isclipped a then inclbalof else exclbalof) (if null a then "top" else a) +-- | Clip the account names to the specified depth in a list of postings. +depthClipPostings :: Maybe Int -> [Posting] -> [Posting] +depthClipPostings depth = map (depthClipPosting depth) + +-- | Clip a posting's account name to the specified depth. +depthClipPosting :: Maybe Int -> Posting -> Posting +depthClipPosting Nothing p = p +depthClipPosting (Just d) p@Posting{paccount=a} = p{paccount=clipAccountName d a} + + tests_Register :: Test tests_Register = TestList [ - "summarisePostings" ~: do - summarisePostings Quarterly Nothing False (DateSpan Nothing Nothing) [] ~?= [] + "summarisePostingsByInterval" ~: do + summarisePostingsByInterval Quarterly Nothing False (DateSpan Nothing Nothing) [] ~?= [] ] diff --git a/Hledger/Cli/Tests.hs b/Hledger/Cli/Tests.hs index 24f62b2bb..9310b7534 100644 --- a/Hledger/Cli/Tests.hs +++ b/Hledger/Cli/Tests.hs @@ -572,12 +572,17 @@ tests = TestList [ l <- samplejournal let opts = [Depth "2"] (registerReportAsText opts $ registerReport opts (optsToFilterSpec opts [] t1) l) `is` unlines - ["2008/01/01 income income:salary $-1 $-1" - ,"2008/06/01 gift income:gifts $-1 $-2" - ,"2008/06/03 eat & shop expenses:food $1 $-1" - ," expenses:supplies $1 0" - ," assets:cash $-2 $-2" - ,"2008/12/31 pay off liabilities:debts $1 $-1" + ["2008/01/01 income assets:bank $1 $1" + ," income:salary $-1 0" + ,"2008/06/01 gift assets:bank $1 $1" + ," income:gifts $-1 0" + ,"2008/06/02 save assets:bank $1 $1" + ," assets:bank $-1 0" + ,"2008/06/03 eat & shop expenses:food $1 $1" + ," expenses:supplies $1 $2" + ," assets:cash $-2 0" + ,"2008/12/31 pay off liabilities:debts $1 $1" + ," assets:bank $-1 0" ] ,"show dollars" ~: show (dollars 1) ~?= "$1.00" diff --git a/MANUAL.markdown b/MANUAL.markdown index 8abf4110e..6114cd768 100644 --- a/MANUAL.markdown +++ b/MANUAL.markdown @@ -240,7 +240,7 @@ Here is the command-line help: -C --cleared report only on cleared transactions -U --uncleared report only on uncleared transactions -B --cost, --basis report cost of commodities - --depth=N hide accounts/transactions deeper than this + --depth=N hide sub-accounts deeper than this -d EXPR --display=EXPR show only transactions matching EXPR (where EXPR is 'dOP[DATE]' and OP is <, <=, =, >=, >) --effective use transactions' effective dates, if any @@ -284,17 +284,24 @@ Examples: ##### register -The register command displays postings, one per line, and their running -total. With a [reporting interval](#reporting-interval) it will aggregate -similar postings within each interval. - -Examples: +The register command displays postings, one per line, and their running total. +With no [filter patterns](#filter-patterns), this is not all that different from [print](#print): $ hledger register - $ hledger register --monthly -E rent -Note `--depth` doesn't work too well with `register` currently; -it hides deeper postings rather than aggregating them. +More typically, use it to see a specific account's activity: + + $ hledger register assets:bank:checking + +The `--depth` option limits the amount of sub-account detail displayed: + + $ hledger register assets:bank:checking --depth 2 + +With a [reporting interval](#reporting-interval) it shows aggregated +summary postings within each interval: + + $ hledger register --monthly rent + $ hledger register --monthly -E food --depth 4 ##### balance @@ -651,8 +658,8 @@ subsequent dates may be written as month/day. Eg: #### Period expressions hledger supports flexible "period expressions" with the `-p/--period` -option to select transactions within a period of time (like 2009) and/or -with a reporting interval (like weekly). hledger period expressions are +option to select transactions within a period of time (eg in 2009) and/or +with a reporting interval (eg weekly). hledger period expressions are similar but not identical to c++ ledger's. Here is a basic period expression specifying the first quarter of 2009 @@ -729,20 +736,8 @@ accurate running total. Eg, to show the balance since the first of the month: #### Depth limiting With the `--depth N` option, reports will show only the uppermost accounts -in the account tree, down to level N. This is most useful with -[balance](#balance) and [chart](#chart). For example: - - $ hledger balance --depth 2 - -shows a more concise balance report displaying only the top two levels of -accounts. - -It's currently not so useful with [register](#register), eg this: - - $ hledger register --depth 1 - -shows only the postings in top-level accounts, which usually means -none. +in the account tree, down to level N. See the [balance](#balance), +[register](#register) and [chart](#chart) examples. #### Prices diff --git a/tests/register-depth.test b/tests/register-depth.test index 2749e4253..c44ef7bb0 100644 --- a/tests/register-depth.test +++ b/tests/register-depth.test @@ -1,18 +1,49 @@ -# -bin/hledger -f - register --depth 1 +# this matches the second-level account but displays only the first-level name +bin/hledger -f - register aa --depth 1 +<<< +2010/1/1 x + a:aa:aaa 1 + b + +>>> +2010/01/01 x a 1 1 +>>>2 +# this matches the second-level account, displays the second-level name, does not aggregate transactions +bin/hledger -f - register aa --depth 2 <<< 2010/1/1 x a:aa 1 b:bb:bbb +2010/1/1 y + a:aa 1 + b:bb:bbb + +2010/1/2 z + a:aa 1 + b:bb:bbb + >>> +2010/01/01 x a:aa 1 1 +2010/01/01 y a:aa 1 2 +2010/01/02 z a:aa 1 3 >>>2 -# -bin/hledger -f - register --depth 1 --empty --monthly +# this matches the second-level account, displays the first-level name, aggregates by reporting interval +bin/hledger -f - register aa --depth 1 --daily <<< 2010/1/1 x a:aa 1 b:bb:bbb +2010/1/1 y + a:aa 1 + b:bb:bbb + +2010/1/2 z + a:aa 1 + b:bb:bbb + >>> +2010/01/01 - 2010/01/01 a 2 2 +2010/01/02 - 2010/01/02 a 1 3 >>>2