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