mirror of
https://github.com/simonmichael/hledger.git
synced 2024-09-19 10:17:35 +03:00
dev: reg: areg: Be more clever about register and aregister alignment.
When rendering register or aregister reports, calculate the amount / balance width based on the first 100 items, and start rendering in that way. If you encounter a longer one, update and continue rendering. This will result in adjustment of column width for long reports, but allows us to save a lot more performant/efficient. This can be disabled with the new --align-all flag. We also only render each amount once, rather than twice as before, by storing the rendered amount in a tuple.
This commit is contained in:
parent
cbc985d411
commit
c0cc9e73c1
@ -56,6 +56,7 @@ aregistermode = hledgerCommandMode
|
||||
#endif
|
||||
++ " or $COLUMNS). -wN,M sets description width as well."
|
||||
)
|
||||
,flagNone ["align-all"] (setboolopt "align-all") "truly align to the longest widths"
|
||||
,outputFormatFlag ["txt","csv","json"]
|
||||
,outputFileFlag
|
||||
])
|
||||
@ -127,12 +128,11 @@ accountTransactionsReportItemAsCsvRecord
|
||||
-- | Render a register report as plain text suitable for console output.
|
||||
accountTransactionsReportAsText :: CliOpts -> Query -> Query -> AccountTransactionsReport -> TL.Text
|
||||
accountTransactionsReportAsText copts reportq thisacctq items = TB.toLazyText $
|
||||
title <> TB.singleton '\n' <> lines
|
||||
title <> TB.singleton '\n' <>
|
||||
postingsOrTransactionsReportAsText alignAll copts itemAsText itemamt itembal items
|
||||
where
|
||||
lines = foldMap (accountTransactionsReportItemAsText copts reportq thisacctq amtwidth balwidth) items
|
||||
amtwidth = maximumStrict $ 12 : widths (map itemamt $ take 1000 items)
|
||||
balwidth = maximumStrict $ 12 : widths (map itembal $ take 1000 items)
|
||||
widths = map wbWidth . concatMap (showMixedAmountLinesB oneLine)
|
||||
alignAll = boolopt "align-all" $ rawopts_ copts
|
||||
itemAsText = accountTransactionsReportItemAsText copts reportq thisacctq
|
||||
itemamt (_,_,_,_,a,_) = a
|
||||
itembal (_,_,_,_,_,a) = a
|
||||
|
||||
@ -156,11 +156,13 @@ accountTransactionsReportAsText copts reportq thisacctq items = TB.toLazyText $
|
||||
-- Returns a string which can be multi-line, eg if the running balance
|
||||
-- has multiple commodities.
|
||||
--
|
||||
accountTransactionsReportItemAsText :: CliOpts -> Query -> Query -> Int -> Int -> AccountTransactionsReportItem -> TB.Builder
|
||||
accountTransactionsReportItemAsText :: CliOpts -> Query -> Query -> Int -> Int
|
||||
-> (AccountTransactionsReportItem, [WideBuilder], [WideBuilder])
|
||||
-> TB.Builder
|
||||
accountTransactionsReportItemAsText
|
||||
copts@CliOpts{reportspec_=ReportSpec{_rsReportOpts=ropts@ReportOpts{color_}}}
|
||||
copts@CliOpts{reportspec_=ReportSpec{_rsReportOpts=ropts}}
|
||||
reportq thisacctq preferredamtwidth preferredbalwidth
|
||||
(t@Transaction{tdescription}, _, _issplit, otheracctsstr, change, balance) =
|
||||
((t@Transaction{tdescription}, _, _issplit, otheracctsstr, _, _), amt, bal) =
|
||||
-- Transaction -- the transaction, unmodified
|
||||
-- Transaction -- the transaction, as seen from the current account
|
||||
-- Bool -- is this a split (more than one posting to other accounts) ?
|
||||
@ -206,9 +208,6 @@ accountTransactionsReportItemAsText
|
||||
-- gather content
|
||||
accts = -- T.unpack $ elideAccountName acctwidth $ T.pack
|
||||
otheracctsstr
|
||||
amt = showamt change
|
||||
bal = showamt balance
|
||||
showamt = showMixedAmountLinesB noPrice{displayColour=color_}
|
||||
|
||||
-- tests
|
||||
|
||||
|
@ -50,6 +50,7 @@ registermode = hledgerCommandMode
|
||||
#endif
|
||||
++ " or $COLUMNS). -wN,M sets description width as well."
|
||||
)
|
||||
,flagNone ["align-all"] (setboolopt "align-all") "truly align to the longest widths"
|
||||
,outputFormatFlag ["txt","csv","json"]
|
||||
,outputFileFlag
|
||||
])
|
||||
@ -93,12 +94,10 @@ postingsReportItemAsCsvRecord (_, _, _, p, b) = [idx,date,code,desc,acct,amt,bal
|
||||
|
||||
-- | Render a register report as plain text suitable for console output.
|
||||
postingsReportAsText :: CliOpts -> PostingsReport -> TL.Text
|
||||
postingsReportAsText opts items = TB.toLazyText lines
|
||||
postingsReportAsText opts = TB.toLazyText .
|
||||
postingsOrTransactionsReportAsText alignAll opts (postingsReportItemAsText opts) itemamt itembal
|
||||
where
|
||||
lines = foldMap (postingsReportItemAsText opts amtwidth balwidth) items
|
||||
amtwidth = maximumStrict $ 12 : widths (map itemamt $ take 1000 items)
|
||||
balwidth = maximumStrict $ 12 : widths (map itembal $ take 1000 items)
|
||||
widths = map wbWidth . concatMap (showMixedAmountLinesB oneLine)
|
||||
alignAll = boolopt "align-all" $ rawopts_ opts
|
||||
itemamt (_,_,_,Posting{pamount=a},_) = a
|
||||
itembal (_,_,_,_,a) = a
|
||||
|
||||
@ -126,8 +125,10 @@ postingsReportAsText opts items = TB.toLazyText lines
|
||||
--
|
||||
-- Also returns the natural width (without padding) of the amount and balance
|
||||
-- fields.
|
||||
postingsReportItemAsText :: CliOpts -> Int -> Int -> PostingsReportItem -> TB.Builder
|
||||
postingsReportItemAsText opts preferredamtwidth preferredbalwidth (mdate, mperiod, mdesc, p, b) =
|
||||
postingsReportItemAsText :: CliOpts -> Int -> Int
|
||||
-> (PostingsReportItem, [WideBuilder], [WideBuilder])
|
||||
-> TB.Builder
|
||||
postingsReportItemAsText opts preferredamtwidth preferredbalwidth ((mdate, mperiod, mdesc, p, _), amt, bal) =
|
||||
table <> TB.singleton '\n'
|
||||
where
|
||||
table = renderRowB def{tableBorders=False, borderSpaces=False} . Group NoLine $ map Header
|
||||
@ -177,9 +178,6 @@ postingsReportItemAsText opts preferredamtwidth preferredbalwidth (mdate, mperio
|
||||
BalancedVirtualPosting -> (wrap "[" "]", acctwidth-2)
|
||||
VirtualPosting -> (wrap "(" ")", acctwidth-2)
|
||||
_ -> (id,acctwidth)
|
||||
amt = showamt $ pamount p
|
||||
bal = showamt b
|
||||
showamt = showMixedAmountLinesB oneLine{displayColour=color_ . _rsReportOpts $ reportspec_ opts}
|
||||
|
||||
-- tests
|
||||
|
||||
|
@ -25,6 +25,7 @@ module Hledger.Cli.Utils
|
||||
pivotByOpts,
|
||||
anonymiseByOpts,
|
||||
journalSimilarTransaction,
|
||||
postingsOrTransactionsReportAsText,
|
||||
tests_Cli_Utils,
|
||||
)
|
||||
where
|
||||
@ -35,9 +36,11 @@ import Data.Maybe
|
||||
import qualified Data.Text as T
|
||||
import qualified Data.Text.IO as T
|
||||
import qualified Data.Text.Lazy as TL
|
||||
import qualified Data.Text.Lazy.Builder as TB
|
||||
import qualified Data.Text.Lazy.IO as TL
|
||||
import Data.Time (Day)
|
||||
import Data.Time.Clock.POSIX (POSIXTime, utcTimeToPOSIXSeconds)
|
||||
import Lens.Micro ((^.))
|
||||
import Safe (readMay, headMay)
|
||||
import System.Console.CmdArgs
|
||||
import System.Directory (getModificationTime, getDirectoryContents, copyFile, doesFileExist)
|
||||
@ -256,6 +259,32 @@ journalSimilarTransaction cliopts j desc = mbestmatch
|
||||
journalTransactionsSimilarTo j q desc 10
|
||||
q = queryFromFlags $ _rsReportOpts $ reportspec_ cliopts
|
||||
|
||||
-- | Render a 'PostingsReport' or 'AccountTransactionsReport' as Text,
|
||||
-- determining the appropriate starting widths and increasing as necessary.
|
||||
postingsOrTransactionsReportAsText
|
||||
:: Bool -> CliOpts -> (Int -> Int -> (a, [WideBuilder], [WideBuilder]) -> TB.Builder)
|
||||
-> (a -> MixedAmount) -> (a -> MixedAmount) -> [a] -> TB.Builder
|
||||
postingsOrTransactionsReportAsText alignAll opts itemAsText itemamt itembal report =
|
||||
mconcat . snd $ mapAccumL renderItem (startWidth amt, startWidth bal) itemsWithAmounts
|
||||
where
|
||||
minWidth = 12
|
||||
chunkSize = 100
|
||||
|
||||
renderItem (amtWidth, balWidth) item@(_, amt, bal) = ((amtWidth', balWidth'), itemBuilder)
|
||||
where
|
||||
itemBuilder = itemAsText amtWidth' balWidth' item
|
||||
amtWidth' = if alignAll then amtWidth else maximumStrict $ amtWidth : map wbWidth amt
|
||||
balWidth' = if alignAll then balWidth else maximumStrict $ balWidth : map wbWidth bal
|
||||
|
||||
startWidth f = maximum $ minWidth : map wbWidth (concatMap f startAlign)
|
||||
where
|
||||
startAlign = (if alignAll then id else take chunkSize) itemsWithAmounts
|
||||
|
||||
itemsWithAmounts = map (\x -> (x, showAmt $ itemamt x, showAmt $ itembal x)) report
|
||||
showAmt = showMixedAmountLinesB oneLine{displayColour=opts^.color__}
|
||||
amt = second3
|
||||
bal = third3
|
||||
|
||||
tests_Cli_Utils = testGroup "Utils" [
|
||||
|
||||
-- testGroup "journalApplyValue" [
|
||||
|
Loading…
Reference in New Issue
Block a user