diff --git a/hledger/Hledger/Cli/Commands/Aregister.hs b/hledger/Hledger/Cli/Commands/Aregister.hs index 82c7cbc6c..870c73f8f 100644 --- a/hledger/Hledger/Cli/Commands/Aregister.hs +++ b/hledger/Hledger/Cli/Commands/Aregister.hs @@ -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 diff --git a/hledger/Hledger/Cli/Commands/Register.hs b/hledger/Hledger/Cli/Commands/Register.hs index 8c7789fcf..fd26467df 100644 --- a/hledger/Hledger/Cli/Commands/Register.hs +++ b/hledger/Hledger/Cli/Commands/Register.hs @@ -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 diff --git a/hledger/Hledger/Cli/Utils.hs b/hledger/Hledger/Cli/Utils.hs index 988dbee51..76cd2330c 100644 --- a/hledger/Hledger/Cli/Utils.hs +++ b/hledger/Hledger/Cli/Utils.hs @@ -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" [