lib,cli,ui: Introduce showMixed*Unnormalised, eliminate most direct calls of strWidth.

This introduces some new helper functions which are exactly the same
as what we had before, but do not call
normaliseMixedAmountSquashPricesForDisplay, so that we can use the new
functions for displaying Transaction and Posting. It also goes through
and gets rid of most uses of the old showMixed* functions which would
benefit from using the new interface.
This commit is contained in:
Stephen Morgan 2020-09-22 16:31:09 +10:00
parent a838366c9d
commit 9de238757b
10 changed files with 56 additions and 49 deletions

View File

@ -117,7 +117,9 @@ module Hledger.Data.Amount (
showMixedAmountWithZeroCommodity, showMixedAmountWithZeroCommodity,
showMixedAmountWithPrecision, showMixedAmountWithPrecision,
showMixed, showMixed,
showMixedUnnormalised,
showMixedOneLine, showMixedOneLine,
showMixedOneLineUnnormalised,
setMixedAmountPrecision, setMixedAmountPrecision,
canonicaliseMixedAmount, canonicaliseMixedAmount,
-- * misc. -- * misc.
@ -659,12 +661,16 @@ showMixedAmountDebug m | m == missingmixedamt = "(missing)"
-- width (if given) will be elided. The function also returns the actual -- width (if given) will be elided. The function also returns the actual
-- width of the output string. -- width of the output string.
showMixed :: (Amount -> String) -> Maybe Int -> Maybe Int -> Bool -> MixedAmount -> (String, Int) showMixed :: (Amount -> String) -> Maybe Int -> Maybe Int -> Bool -> MixedAmount -> (String, Int)
showMixed showamt mmin mmax c mixed = showMixed showamt mmin mmax c =
showMixedUnnormalised showamt mmin mmax c . normaliseMixedAmountSquashPricesForDisplay
-- | Like showMixed, but does not normalise the MixedAmount before displaying.
showMixedUnnormalised :: (Amount -> String) -> Maybe Int -> Maybe Int -> Bool -> MixedAmount -> (String, Int)
showMixedUnnormalised showamt mmin mmax c (Mixed as) =
(intercalate "\n" $ map finalise elided, width) (intercalate "\n" $ map finalise elided, width)
where where
width = maximum $ fromMaybe 0 mmin : map adLength elided width = maximum $ fromMaybe 0 mmin : map adLength elided
astrs = amtDisplayList sepwidth showamt as astrs = amtDisplayList sepwidth showamt as
Mixed as = normaliseMixedAmountSquashPricesForDisplay mixed
sepwidth = 0 -- "\n" has width 0 sepwidth = 0 -- "\n" has width 0
finalise = adString . pad . if c then colourise else id finalise = adString . pad . if c then colourise else id
@ -683,12 +689,17 @@ showMixed showamt mmin mmax c mixed =
-- as it can in the maximum width (if given), and further Amounts will be -- as it can in the maximum width (if given), and further Amounts will be
-- elided. The function also returns the actual width of the output string. -- elided. The function also returns the actual width of the output string.
showMixedOneLine :: (Amount -> String) -> Maybe Int -> Maybe Int -> Bool -> MixedAmount -> (String, Int) showMixedOneLine :: (Amount -> String) -> Maybe Int -> Maybe Int -> Bool -> MixedAmount -> (String, Int)
showMixedOneLine showamt mmin mmax c mixed = showMixedOneLine showamt mmin mmax c =
showMixedOneLineUnnormalised showamt mmin mmax c . normaliseMixedAmountSquashPricesForDisplay
-- | Like showMixedOneLine, but does not normalise the MixedAmount before
-- displaying.
showMixedOneLineUnnormalised :: (Amount -> String) -> Maybe Int -> Maybe Int -> Bool -> MixedAmount -> (String, Int)
showMixedOneLineUnnormalised showamt mmin mmax c (Mixed as) =
(pad . intercalate ", " $ map finalise elided, max width $ fromMaybe 0 mmin) (pad . intercalate ", " $ map finalise elided, max width $ fromMaybe 0 mmin)
where where
width = maybe 0 adTotal $ lastMay elided width = maybe 0 adTotal $ lastMay elided
astrs = amtDisplayList sepwidth showamt as astrs = amtDisplayList sepwidth showamt as
Mixed as = normaliseMixedAmountSquashPricesForDisplay mixed
sepwidth = 2 -- ", " has width 2 sepwidth = 2 -- ", " has width 2
n = length as n = length as

View File

@ -256,11 +256,11 @@ postingAsLines elideamount onelineamounts pstoalignwith p = concat [
-- currently prices are considered part of the amount string when right-aligning amounts -- currently prices are considered part of the amount string when right-aligning amounts
shownAmounts shownAmounts
| elideamount = [""] | elideamount = [""]
| onelineamounts = [fitString (Just amtwidth) Nothing False False $ showMixedAmountOneLine $ pamount p] | onelineamounts = [fst . showMixedOneLineUnnormalised showAmount (Just amtwidth) Nothing False $ pamount p]
| null (amounts $ pamount p) = [""] | null (amounts $ pamount p) = [""]
| otherwise = map (fitStringMulti (Just amtwidth) Nothing False False . showAmount ) . amounts $ pamount p | otherwise = lines . fst . showMixedUnnormalised showAmount (Just amtwidth) Nothing False $ pamount p
where where
amtwidth = maximum $ 12 : map (strWidth . showMixedAmount . pamount) pstoalignwith -- min. 12 for backwards compatibility amtwidth = maximum $ map (snd . showMixed showAmount (Just 12) Nothing False . pamount) pstoalignwith -- min. 12 for backwards compatibility
(samelinecomment, newlinecomments) = (samelinecomment, newlinecomments) =
case renderCommentLines (pcomment p) of [] -> ("",[]) case renderCommentLines (pcomment p) of [] -> ("",[])

View File

@ -93,8 +93,8 @@ rsInit d reset ui@UIState{aopts=_uopts@UIOpts{cliopts_=CliOpts{reportspec_=rspec
[s] -> s [s] -> s
ss -> intercalate ", " ss ss -> intercalate ", " ss
-- _ -> "<split>" -- should do this if accounts field width < 30 -- _ -> "<split>" -- should do this if accounts field width < 30
,rsItemChangeAmount = showMixedAmountElided 22 False change ,rsItemChangeAmount = showMixed showAmountWithoutPrice Nothing (Just 22) False change
,rsItemBalanceAmount = showMixedAmountElided 22 False bal ,rsItemBalanceAmount = showMixed showAmountWithoutPrice Nothing (Just 22) False bal
,rsItemTransaction = t ,rsItemTransaction = t
} }
-- blank items are added to allow more control of scroll position; we won't allow movement over these -- blank items are added to allow more control of scroll position; we won't allow movement over these
@ -103,8 +103,8 @@ rsInit d reset ui@UIState{aopts=_uopts@UIOpts{cliopts_=CliOpts{reportspec_=rspec
,rsItemStatus = Unmarked ,rsItemStatus = Unmarked
,rsItemDescription = "" ,rsItemDescription = ""
,rsItemOtherAccounts = "" ,rsItemOtherAccounts = ""
,rsItemChangeAmount = "" ,rsItemChangeAmount = ("", 0)
,rsItemBalanceAmount = "" ,rsItemBalanceAmount = ("", 0)
,rsItemTransaction = nulltransaction ,rsItemTransaction = nulltransaction
} }
-- build the List -- build the List
@ -162,8 +162,8 @@ rsDraw UIState{aopts=_uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec}}
whitespacewidth = 10 -- inter-column whitespace, fixed width whitespacewidth = 10 -- inter-column whitespace, fixed width
minnonamtcolswidth = datewidth + 1 + 2 + 2 -- date column plus at least 1 for status and 2 for desc and accts minnonamtcolswidth = datewidth + 1 + 2 + 2 -- date column plus at least 1 for status and 2 for desc and accts
maxamtswidth = max 0 (totalwidth - minnonamtcolswidth - whitespacewidth) maxamtswidth = max 0 (totalwidth - minnonamtcolswidth - whitespacewidth)
maxchangewidthseen = maximum' $ map (strWidth . rsItemChangeAmount) displayitems maxchangewidthseen = maximum' $ map (snd . rsItemChangeAmount) displayitems
maxbalwidthseen = maximum' $ map (strWidth . rsItemBalanceAmount) displayitems maxbalwidthseen = maximum' $ map (snd . rsItemBalanceAmount) displayitems
changewidthproportion = fromIntegral maxchangewidthseen / fromIntegral (maxchangewidthseen + maxbalwidthseen) changewidthproportion = fromIntegral maxchangewidthseen / fromIntegral (maxchangewidthseen + maxbalwidthseen)
maxchangewidth = round $ changewidthproportion * fromIntegral maxamtswidth maxchangewidth = round $ changewidthproportion * fromIntegral maxamtswidth
maxbalwidth = maxamtswidth - maxchangewidth maxbalwidth = maxamtswidth - maxchangewidth
@ -261,13 +261,13 @@ rsDrawItem (datewidth,descwidth,acctswidth,changewidth,balwidth) selected Regist
str " " <+> str " " <+>
str (fitString (Just acctswidth) (Just acctswidth) True True rsItemOtherAccounts) <+> str (fitString (Just acctswidth) (Just acctswidth) True True rsItemOtherAccounts) <+>
str " " <+> str " " <+>
withAttr changeattr (str (fitString (Just changewidth) (Just changewidth) True False rsItemChangeAmount)) <+> withAttr changeattr (str (fitString (Just changewidth) (Just changewidth) True False $ fst rsItemChangeAmount)) <+>
str " " <+> str " " <+>
withAttr balattr (str (fitString (Just balwidth) (Just balwidth) True False rsItemBalanceAmount)) withAttr balattr (str (fitString (Just balwidth) (Just balwidth) True False $ fst rsItemBalanceAmount))
where where
changeattr | '-' `elem` rsItemChangeAmount = sel $ "list" <> "amount" <> "decrease" changeattr | '-' `elem` fst rsItemChangeAmount = sel $ "list" <> "amount" <> "decrease"
| otherwise = sel $ "list" <> "amount" <> "increase" | otherwise = sel $ "list" <> "amount" <> "increase"
balattr | '-' `elem` rsItemBalanceAmount = sel $ "list" <> "balance" <> "negative" balattr | '-' `elem` fst rsItemBalanceAmount = sel $ "list" <> "balance" <> "negative"
| otherwise = sel $ "list" <> "balance" <> "positive" | otherwise = sel $ "list" <> "balance" <> "positive"
sel | selected = (<> "selected") sel | selected = (<> "selected")
| otherwise = id | otherwise = id

View File

@ -146,8 +146,8 @@ data RegisterScreenItem = RegisterScreenItem {
,rsItemStatus :: Status -- ^ transaction status ,rsItemStatus :: Status -- ^ transaction status
,rsItemDescription :: String -- ^ description ,rsItemDescription :: String -- ^ description
,rsItemOtherAccounts :: String -- ^ other accounts ,rsItemOtherAccounts :: String -- ^ other accounts
,rsItemChangeAmount :: String -- ^ the change to the current account from this transaction ,rsItemChangeAmount :: (String, Int) -- ^ the change to the current account from this transaction
,rsItemBalanceAmount :: String -- ^ the balance or running total after this transaction ,rsItemBalanceAmount :: (String, Int) -- ^ the balance or running total after this transaction
,rsItemTransaction :: Transaction -- ^ the full transaction ,rsItemTransaction :: Transaction -- ^ the full transaction
} }
deriving (Show) deriving (Show)

View File

@ -147,11 +147,10 @@ accountTransactionsReportAsText
= unlines $ title : = unlines $ title :
map (accountTransactionsReportItemAsText copts reportq thisacctq amtwidth balwidth) items map (accountTransactionsReportItemAsText copts reportq thisacctq amtwidth balwidth) items
where where
amtwidth = maximumStrict $ 12 : map (strWidth . showamt . itemamt) items amtwidth = maximumStrict $ 12 : map (snd . showamt . itemamt) items
balwidth = maximumStrict $ 12 : map (strWidth . showamt . itembal) items balwidth = maximumStrict $ 12 : map (snd . showamt . itembal) items
showamt showamt = showMixedOneLine showAmountWithoutPrice (Just 12) mmax False -- color_
| no_elide_ = showMixedAmountOneLineWithoutPrice False -- color_ where mmax = if no_elide_ then Nothing else Just 22
| otherwise = showMixedAmountElided 22 False
itemamt (_,_,_,_,a,_) = a itemamt (_,_,_,_,a,_) = a
itembal (_,_,_,_,_,a) = a itembal (_,_,_,_,_,a) = a
-- show a title indicating which account was picked, which can be confusing otherwise -- show a title indicating which account was picked, which can be confusing otherwise
@ -176,7 +175,7 @@ accountTransactionsReportAsText
-- --
accountTransactionsReportItemAsText :: CliOpts -> Query -> Query -> Int -> Int -> AccountTransactionsReportItem -> String accountTransactionsReportItemAsText :: CliOpts -> Query -> Query -> Int -> Int -> AccountTransactionsReportItem -> String
accountTransactionsReportItemAsText accountTransactionsReportItemAsText
copts@CliOpts{reportspec_=ReportSpec{rsOpts=ReportOpts{color_,no_elide_}}} copts@CliOpts{reportspec_=ReportSpec{rsOpts=ReportOpts{color_}}}
reportq thisacctq preferredamtwidth preferredbalwidth reportq thisacctq preferredamtwidth preferredbalwidth
(t@Transaction{tdescription}, _, _issplit, otheracctsstr, change, balance) (t@Transaction{tdescription}, _, _issplit, otheracctsstr, change, balance)
-- Transaction -- the transaction, unmodified -- Transaction -- the transaction, unmodified
@ -193,15 +192,15 @@ accountTransactionsReportItemAsText
," " ," "
,fitString (Just acctwidth) (Just acctwidth) True True accts ,fitString (Just acctwidth) (Just acctwidth) True True accts
," " ," "
,fitString (Just amtwidth) (Just amtwidth) True False amtfirstline ,amtfirstline
," " ," "
,fitString (Just balwidth) (Just balwidth) True False balfirstline ,balfirstline
] ]
: :
[concat [spacer [concat [spacer
,fitString (Just amtwidth) (Just amtwidth) True False a ,a
," " ," "
,fitString (Just balwidth) (Just balwidth) True False b ,b
] ]
| (a,b) <- zip amtrest balrest | (a,b) <- zip amtrest balrest
] ]
@ -229,19 +228,16 @@ accountTransactionsReportItemAsText
desc = T.unpack tdescription desc = T.unpack tdescription
accts = -- T.unpack $ elideAccountName acctwidth $ T.pack accts = -- T.unpack $ elideAccountName acctwidth $ T.pack
otheracctsstr otheracctsstr
showamt amt = fst $ showMixed showAmountWithoutPrice (Just amtwidth) (Just balwidth) color_ change
| no_elide_ = showMixedAmountOneLineWithoutPrice color_ bal = fst $ showMixed showAmountWithoutPrice (Just balwidth) (Just balwidth) color_ balance
| otherwise = showMixedAmountElided 22 color_
amt = showamt change
bal = showamt balance
-- alternate behaviour, show null amounts as 0 instead of blank -- alternate behaviour, show null amounts as 0 instead of blank
-- amt = if null amt' then "0" else amt' -- amt = if null amt' then "0" else amt'
-- bal = if null bal' then "0" else bal' -- bal = if null bal' then "0" else bal'
(amtlines, ballines) = (lines amt, lines bal) (amtlines, ballines) = (lines amt, lines bal)
(amtlen, ballen) = (length amtlines, length ballines) (amtlen, ballen) = (length amtlines, length ballines)
numlines = max 1 (max amtlen ballen) numlines = max 1 (max amtlen ballen)
(amtfirstline:amtrest) = take numlines $ amtlines ++ repeat "" -- posting amount is top-aligned (amtfirstline:amtrest) = take numlines $ amtlines ++ repeat (replicate amtwidth ' ') -- posting amount is top-aligned
(balfirstline:balrest) = take numlines $ replicate (numlines - ballen) "" ++ ballines -- balance amount is bottom-aligned (balfirstline:balrest) = take numlines $ replicate (numlines - ballen) (replicate balwidth ' ') ++ ballines -- balance amount is bottom-aligned
spacer = replicate (totalwidth - (amtwidth + 2 + balwidth)) ' ' spacer = replicate (totalwidth - (amtwidth + 2 + balwidth)) ' '
-- tests -- tests

View File

@ -207,10 +207,10 @@ $ hledger -f- close -p 2016 assets liabilities --show-costs -x
liabilities:employer $5,000.00 @ 0.93 EUR liabilities:employer $5,000.00 @ 0.93 EUR
liabilities:employer $5,000.00 @ 0.95 EUR = $0.00 liabilities:employer $5,000.00 @ 0.95 EUR = $0.00
liabilities:employer -1.00 EUR = 0.00 EUR liabilities:employer -1.00 EUR = 0.00 EUR
equity:opening/closing balances $10,000.00 equity:opening/closing balances $10,000.00
equity:opening/closing balances $-5,000.00 @ 0.93 EUR equity:opening/closing balances $-5,000.00 @ 0.93 EUR
equity:opening/closing balances $-5,000.00 @ 0.95 EUR equity:opening/closing balances $-5,000.00 @ 0.95 EUR
equity:opening/closing balances 5,734.00 EUR equity:opening/closing balances 5,734.00 EUR
2017-01-01 opening balances 2017-01-01 opening balances
assets:bank 5,733.00 EUR = 5,733.00 EUR assets:bank 5,733.00 EUR = 5,733.00 EUR
@ -274,9 +274,9 @@ $ hledger -f- close -p 2019 assets --show-costs -x
assets:aaa AAA -510.00000000 = AAA 0.00000000 assets:aaa AAA -510.00000000 = AAA 0.00000000
assets:usd $-49.50 assets:usd $-49.50
assets:usd $49.390001 @ AAA 10.3528242505 = $0.00 assets:usd $49.390001 @ AAA 10.3528242505 = $0.00
equity:opening/closing balances $49.50 equity:opening/closing balances $49.50
equity:opening/closing balances $-49.390001 @ AAA 10.3528242505 equity:opening/closing balances $-49.390001 @ AAA 10.3528242505
equity:opening/closing balances AAA 510.00000000 equity:opening/closing balances AAA 510.00000000
2020-01-01 opening balances 2020-01-01 opening balances
assets:aaa AAA 510.00000000 = AAA 510.00000000 assets:aaa AAA 510.00000000 = AAA 510.00000000

View File

@ -408,15 +408,15 @@ account1 assets
account2 income account2 income
$ ./csvtest.sh $ ./csvtest.sh
2018-10-15 Assets Update 2018-10-15 Assets Update
assets = EUR 100 assets = EUR 100
income income
2018-10-16 Assets Update 2018-10-16 Assets Update
assets = EUR 200 assets = EUR 200
income income
2018-10-17 Assets Update 2018-10-17 Assets Update
assets = EUR 300 assets = EUR 300
income income
>=0 >=0

View File

@ -21,7 +21,7 @@ hledger -f - print
>>> >>>
2000-01-01 transaction 1 2000-01-01 transaction 1
㐀 㐃㐃1 @ 2 㐂㐂㐂㐂㐂㐂㐂㐂㐂㐂㐂 㐀 㐃㐃1 @ 2 㐂㐂㐂㐂㐂㐂㐂㐂㐂㐂㐂
㐀:㐁 ; 㐃㐃-1 㐀:㐁 ; 㐃㐃-1
2000-01-02 transaction 2 2000-01-02 transaction 2
㐀:㐁:㐂 USD 1 㐀:㐁:㐂 USD 1

View File

@ -64,7 +64,7 @@ hledger -f - print
equity equity
>>> >>>
2017-01-01 2017-01-01
assets = $100 assets = $100
equity equity
>>>2 >>>2

View File

@ -42,7 +42,7 @@ hledger rewrite -f- expenses:gifts --add-posting '(budget:gifts) *-1'
2016-01-01 gift ; modified: 2016-01-01 gift ; modified:
assets:cash $-15 assets:cash $-15
expenses:gifts ; [1/2] expenses:gifts ; [1/2]
(budget:gifts) $-15 ; [2016-01-02], generated-posting: = expenses:gifts (budget:gifts) $-15 ; [2016-01-02], generated-posting: = expenses:gifts
>>>2 >>>2
@ -107,17 +107,17 @@ hledger rewrite -f- -B
2017-04-24 * 09:00-09:25 ; modified: 2017-04-24 * 09:00-09:25 ; modified:
(assets:unbilled:client1) 0.42h (assets:unbilled:client1) 0.42h
assets:to bill:client1 $42.00 ; generated-posting: = ^assets:unbilled:client1 assets:to bill:client1 $42.00 ; generated-posting: = ^assets:unbilled:client1
income:consulting:client1 ; generated-posting: = ^assets:unbilled:client1 income:consulting:client1 ; generated-posting: = ^assets:unbilled:client1
2017-04-25 * 10:00-11:15 ; modified: 2017-04-25 * 10:00-11:15 ; modified:
(assets:unbilled:client1) 1.25h (assets:unbilled:client1) 1.25h
assets:to bill:client1 $125.00 ; generated-posting: = ^assets:unbilled:client1 assets:to bill:client1 $125.00 ; generated-posting: = ^assets:unbilled:client1
income:consulting:client1 ; generated-posting: = ^assets:unbilled:client1 income:consulting:client1 ; generated-posting: = ^assets:unbilled:client1
2017-04-25 * 14:00-15:32 ; modified: 2017-04-25 * 14:00-15:32 ; modified:
(assets:unbilled:client2) 1.54h (assets:unbilled:client2) 1.54h
assets:to bill:client2 $231.00 ; generated-posting: = ^assets:unbilled:client2 assets:to bill:client2 $231.00 ; generated-posting: = ^assets:unbilled:client2
income:consulting:client2 ; generated-posting: = ^assets:unbilled:client2 income:consulting:client2 ; generated-posting: = ^assets:unbilled:client2
>>>2 >>>2
>>>=0 >>>=0