Skip to content

Commit 13cec57

Browse files
committed
cli: support for new layout bare-wide
1 parent 49f1af0 commit 13cec57

File tree

3 files changed

+110
-33
lines changed

3 files changed

+110
-33
lines changed

hledger-lib/Hledger/Reports/ReportOptions.hs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ instance Default AccountListMode where def = ALFlat
119119
data Layout = LayoutWide (Maybe Int)
120120
| LayoutTall
121121
| LayoutBare
122+
| LayoutBareWide
122123
| LayoutTidy
123124
deriving (Eq, Show)
124125

@@ -373,6 +374,7 @@ layoutopt rawopts = fromMaybe (LayoutWide Nothing) $ layout <|> column
373374
, ("tall", LayoutTall)
374375
, ("bare", LayoutBare)
375376
, ("tidy", LayoutTidy)
377+
, ("bare-wide", LayoutBareWide)
376378
]
377379
-- For `--layout=elided,n`, elide to the given width
378380
(s,n) = break (==',') $ map toLower opt
@@ -381,7 +383,7 @@ layoutopt rawopts = fromMaybe (LayoutWide Nothing) $ layout <|> column
381383
c | Just w' <- readMay c -> Just w'
382384
_ -> usageError "width in --layout=wide,WIDTH must be an integer"
383385

384-
err = usageError "--layout's argument should be \"wide[,WIDTH]\", \"tall\", \"bare\", or \"tidy\""
386+
err = usageError "--layout's argument should be \"wide[,WIDTH]\", \"tall\", \"bare\", \"bare-wide\", or \"tidy\""
385387

386388
-- Get the period specified by any -b/--begin, -e/--end and/or -p/--period
387389
-- options appearing in the command line.

hledger/Hledger/Cli/Commands/Balance.hs

Lines changed: 75 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,9 @@ headerDateSpanCell base query spn =
641641
Ods.cellAnchor = composeAnchor base $ replaceDate prd query
642642
}
643643

644+
headerWithoutBorders :: [Ods.Cell () text] -> [Ods.Cell Ods.NumLines text]
645+
headerWithoutBorders = map (\c -> c {Ods.cellBorder = Ods.noBorder})
646+
644647
addHeaderBorders :: [Ods.Cell () text] -> [Ods.Cell Ods.NumLines text]
645648
addHeaderBorders =
646649
map (\c -> c {Ods.cellBorder =
@@ -689,8 +692,11 @@ balanceReportAsSpreadsheet opts (items, total) =
689692
headers =
690693
addHeaderBorders $ map headerCell $
691694
"account" : case layout_ opts of
695+
LayoutBareWide -> allCommodities
692696
LayoutBare -> ["commodity", "balance"]
693697
_ -> ["balance"]
698+
allCommodities =
699+
S.toAscList $ foldMap (\(_,_,_,ma) -> maCommodities ma) items
694700
rows ::
695701
RowClass -> BalanceReportItem ->
696702
[[Ods.Cell Ods.NumLines Text]]
@@ -702,6 +708,15 @@ balanceReportAsSpreadsheet opts (items, total) =
702708
cell $ renderBalanceAcct opts nbsp (name, dispName, dep) in
703709
addRowSpanHeader accountCell $
704710
case layout_ opts of
711+
LayoutBareWide ->
712+
let bopts =
713+
machineFmt {
714+
displayCommodity = False,
715+
displayCommodityOrder = Just allCommodities
716+
} in
717+
[map (\bldAmt ->
718+
fmap wbToText $ cellFromAmount bopts (amountClass rc, bldAmt)) $
719+
showMixedAmountLinesPartsB bopts ma]
705720
LayoutBare ->
706721
map (\a -> [cell $ acommodity a, renderAmount rc $ mixedAmount a])
707722
. amounts $ mixedAmountStripCosts ma
@@ -739,6 +754,15 @@ cellsFromMixedAmount bopts (cls, mixedAmt) =
739754
})
740755
(showMixedAmountLinesPartsB bopts mixedAmt)
741756

757+
cellFromAmount ::
758+
(Ods.Lines border) =>
759+
AmountFormat -> (Ods.Class, (wb, Amount)) -> Ods.Cell border wb
760+
cellFromAmount bopts (cls, (str,amt)) =
761+
(Ods.defaultCell str) {
762+
Ods.cellClass = cls,
763+
Ods.cellType = amountType bopts amt
764+
}
765+
742766
amountType :: AmountFormat -> Amount -> Ods.Type
743767
amountType bopts amt =
744768
Ods.TypeAmount $
@@ -756,29 +780,41 @@ amountType bopts amt =
756780
multiBalanceReportAsCsv :: ReportOpts -> MultiBalanceReport -> CSV
757781
multiBalanceReportAsCsv opts@ReportOpts{..} report =
758782
(if transpose_ then transpose else id) $
759-
rawTableContent $ header : body ++ totals
783+
rawTableContent $ header ++ body ++ totals
760784
where
761785
(header, body, totals) =
762-
multiBalanceReportAsSpreadsheetParts machineFmt opts report
786+
multiBalanceReportAsSpreadsheetParts machineFmt opts
787+
(allCommoditiesFromPeriodicReport $ prRows report) report
763788

764789
-- | Render the Spreadsheet table rows (CSV, ODS, HTML) for a MultiBalanceReport.
765790
-- Returns the heading row, 0 or more body rows, and the totals row if enabled.
766791
multiBalanceReportAsSpreadsheetParts ::
767-
AmountFormat -> ReportOpts -> MultiBalanceReport ->
768-
([Ods.Cell Ods.NumLines Text],
792+
AmountFormat -> ReportOpts ->
793+
[CommoditySymbol] -> MultiBalanceReport ->
794+
([[Ods.Cell Ods.NumLines Text]],
769795
[[Ods.Cell Ods.NumLines Text]],
770796
[[Ods.Cell Ods.NumLines Text]])
771-
multiBalanceReportAsSpreadsheetParts fmt opts@ReportOpts{..} (PeriodicReport colspans items tr) =
772-
(headers, concatMap fullRowAsTexts items, addTotalBorders totalrows)
797+
multiBalanceReportAsSpreadsheetParts fmt opts@ReportOpts{..}
798+
allCommodities (PeriodicReport colspans items tr) =
799+
(allHeaders, concatMap fullRowAsTexts items, addTotalBorders totalrows)
773800
where
774801
accountCell label =
775802
(Ods.defaultCell label) {Ods.cellClass = Ods.Class "account"}
776803
hCell cls label = (headerCell label) {Ods.cellClass = Ods.Class cls}
804+
allHeaders =
805+
case layout_ of
806+
LayoutBareWide ->
807+
[headerWithoutBorders $
808+
Ods.emptyCell :
809+
concatMap (Ods.horizontalSpan allCommodities) dateHeaders,
810+
headers]
811+
_ -> [headers]
777812
headers =
778813
addHeaderBorders $
779814
hCell "account" "account" :
780815
case layout_ of
781816
LayoutTidy -> map headerCell tidyColumnLabels
817+
LayoutBareWide -> dateHeaders >> map headerCell allCommodities
782818
LayoutBare -> headerCell "commodity" : dateHeaders
783819
_ -> dateHeaders
784820
dateHeaders =
@@ -799,7 +835,7 @@ multiBalanceReportAsSpreadsheetParts fmt opts@ReportOpts{..} (PeriodicReport col
799835
rowAsText Total simpleDateSpanCell tr
800836
rowAsText rc dsCell =
801837
map (map (fmap wbToText)) .
802-
multiBalanceRowAsCellBuilders fmt opts colspans rc dsCell
838+
multiBalanceRowAsCellBuilders fmt opts colspans allCommodities rc dsCell
803839

804840
tidyColumnLabels :: [Text]
805841
tidyColumnLabels =
@@ -819,10 +855,12 @@ multiBalanceReportAsSpreadsheet ::
819855
((Maybe Int, Maybe Int), [[Ods.Cell Ods.NumLines Text]])
820856
multiBalanceReportAsSpreadsheet ropts mbr =
821857
let (header,body,total) =
822-
multiBalanceReportAsSpreadsheetParts oneLineNoCostFmt ropts mbr
858+
multiBalanceReportAsSpreadsheetParts oneLineNoCostFmt ropts
859+
(allCommoditiesFromPeriodicReport $ prRows mbr) mbr
823860
in (if transpose_ ropts then swap *** Ods.transpose else id) $
824-
((Just 1, case layout_ ropts of LayoutWide _ -> Just 1; _ -> Nothing),
825-
header : body ++ total)
861+
((Just $ case layout_ ropts of LayoutBareWide -> 2; _ -> 1,
862+
case layout_ ropts of LayoutWide _ -> Just 1; _ -> Nothing),
863+
header ++ body ++ total)
826864

827865

828866
-- | Render a multi-column balance report as plain text suitable for console output.
@@ -893,19 +931,24 @@ multiBalanceReportAsTable opts@ReportOpts{summary_only_, average_, balanceaccum_
893931
(concat rows)
894932
where
895933
colheadings = ["Commodity" | layout_ opts == LayoutBare]
896-
++ (if not summary_only_ then map (reportPeriodName balanceaccum_ spans) spans else [])
934+
++ (if not summary_only_
935+
then case layout_ opts of
936+
LayoutBareWide -> spans >> allCommodities
937+
_ -> map (reportPeriodName balanceaccum_ spans) spans
938+
else [])
897939
++ [" Total" | multiBalanceHasTotalsColumn opts]
898940
++ ["Average" | average_]
941+
allCommodities = allCommoditiesFromPeriodicReport items
899942
(accts, rows) = unzip $ fmap fullRowAsTexts items
900943
where
901944
fullRowAsTexts row = (replicate (length rs) (renderacct row), rs)
902945
where
903-
rs = multiBalanceRowAsText opts row
946+
rs = multiBalanceRowAsText opts allCommodities row
904947
renderacct row' = T.replicate (prrIndent row' * 2) " " <> prrDisplayName row'
905948
addtotalrow
906949
| no_total_ opts = id
907950
| otherwise =
908-
let totalrows = multiBalanceRowAsText opts tr
951+
let totalrows = multiBalanceRowAsText opts allCommodities tr
909952
rowhdrs = Group NoLine $ map Header $ totalRowHeadingText : replicate (length totalrows - 1) ""
910953
colhdrs = Header [] -- unused, concatTables will discard
911954
in (flip (concatTables SingleLine) $ Table rowhdrs colhdrs totalrows)
@@ -914,12 +957,17 @@ multiBalanceReportAsTable opts@ReportOpts{summary_only_, average_, balanceaccum_
914957
multiColumnTableInterRowBorder = NoLine
915958
multiColumnTableInterColumnBorder = if pretty_ opts then SingleLine else NoLine
916959

960+
allCommoditiesFromPeriodicReport ::
961+
[PeriodicReportRow a MixedAmount] -> [CommoditySymbol]
962+
allCommoditiesFromPeriodicReport =
963+
S.toAscList . foldMap (foldMap maCommodities . prrAmounts)
964+
917965
multiBalanceRowAsCellBuilders ::
918-
AmountFormat -> ReportOpts -> [DateSpan] ->
966+
AmountFormat -> ReportOpts -> [DateSpan] -> [CommoditySymbol] ->
919967
RowClass -> (DateSpan -> Ods.Cell Ods.NumLines Text) ->
920968
PeriodicReportRow a MixedAmount ->
921969
[[Ods.Cell Ods.NumLines WideBuilder]]
922-
multiBalanceRowAsCellBuilders bopts ropts@ReportOpts{..} colspans
970+
multiBalanceRowAsCellBuilders bopts ropts@ReportOpts{..} colspans allCommodities
923971
rc renderDateSpanCell (PeriodicReportRow _acct as rowtot rowavg) =
924972
case layout_ of
925973
LayoutWide width -> [fmap (cellFromMixedAmount bopts{displayMaxWidth=width}) clsamts]
@@ -930,6 +978,8 @@ multiBalanceRowAsCellBuilders bopts ropts@ReportOpts{..} colspans
930978
. transpose -- each row becomes a list of Text quantities
931979
. map (cellsFromMixedAmount bopts{displayCommodity=False, displayCommodityOrder=Just cs, displayMinWidth=Nothing})
932980
$ clsamts
981+
LayoutBareWide -> [concatMap (cellsFromMixedAmount bopts{displayCommodity=False, displayCommodityOrder=Just allCommodities, displayMinWidth=Nothing})
982+
$ clsamts]
933983
LayoutTidy -> concat
934984
. zipWith (map . addDateColumns) colspans
935985
. map ( zipWith (\c a -> [wbCell c, a]) cs
@@ -972,16 +1022,20 @@ multiBalanceHasTotalsColumn :: ReportOpts -> Bool
9721022
multiBalanceHasTotalsColumn ropts =
9731023
row_total_ ropts && balanceaccum_ ropts `notElem` [Cumulative, Historical]
9741024

975-
multiBalanceRowAsText :: ReportOpts -> PeriodicReportRow a MixedAmount -> [[WideBuilder]]
976-
multiBalanceRowAsText opts =
1025+
multiBalanceRowAsText ::
1026+
ReportOpts -> [CommoditySymbol] -> PeriodicReportRow a MixedAmount -> [[WideBuilder]]
1027+
multiBalanceRowAsText opts allCommodities =
9771028
rawTableContent .
978-
multiBalanceRowAsCellBuilders oneLineNoCostFmt{displayColour=color_ opts} opts []
1029+
multiBalanceRowAsCellBuilders oneLineNoCostFmt{displayColour=color_ opts}
1030+
opts [] allCommodities
9791031
Value simpleDateSpanCell
9801032

981-
multiBalanceRowAsCsvText :: ReportOpts -> [DateSpan] -> PeriodicReportRow a MixedAmount -> [[T.Text]]
982-
multiBalanceRowAsCsvText opts colspans =
1033+
multiBalanceRowAsCsvText ::
1034+
ReportOpts -> [DateSpan] -> [CommoditySymbol] ->
1035+
PeriodicReportRow a MixedAmount -> [[T.Text]]
1036+
multiBalanceRowAsCsvText opts colspans allCommodities =
9831037
map (map (wbToText . Ods.cellContent)) .
984-
multiBalanceRowAsCellBuilders machineFmt opts colspans
1038+
multiBalanceRowAsCellBuilders machineFmt opts colspans allCommodities
9851039
Value simpleDateSpanCell
9861040

9871041

hledger/Hledger/Cli/CompoundBalanceCommand.hs

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import qualified Data.List.NonEmpty as NonEmpty
2323
import qualified Data.Text as T
2424
import qualified Data.Text.Lazy as TL
2525
import qualified Data.Text.Lazy.Builder as TB
26+
import qualified Data.Set as Set
2627
import Data.Time.Calendar (Day, addDays)
2728
import System.Console.CmdArgs.Explicit as C (Mode, flagNone, flagReq)
2829
import qualified System.IO as IO
@@ -285,12 +286,14 @@ compoundBalanceReportAsText ropts (CompoundPeriodicReport title _colspans subrep
285286
-- [COL1LINE1, COL2LINE1]
286287
-- [COL1LINE2, COL2LINE2]
287288
-- ]
288-
coltotalslines = multiBalanceRowAsText ropts totalsrow
289+
coltotalslines = multiBalanceRowAsText ropts allCommodities totalsrow
289290
totalstable = Table
290291
(Group NoLine $ map Header $ "Net:" : replicate (length coltotalslines - 1) "") -- row headers
291292
(Header []) -- column headers, concatTables will discard these
292293
coltotalslines -- cell values
293294

295+
allCommodities = allCommoditiesFromSubreports subreports
296+
294297
-- | Convert a named multi balance report to a table suitable for
295298
-- concatenating with others to make a compound balance report table.
296299
subreportAsTable ropts1 (title1, r, _) = tablewithtitle
@@ -355,14 +358,21 @@ compoundBalanceReportAsSpreadsheet fmt accountLabel maybeBlank ropts cbr =
355358
_ -> []
356359
dataHeaders =
357360
(guard (layout_ ropts /= LayoutTidy) >>) $
358-
map (Spr.headerCell . reportPeriodName (balanceaccum_ ropts) colspans)
361+
map (dataHeaderCell . reportPeriodName (balanceaccum_ ropts) colspans)
359362
colspans ++
360-
(guard (multiBalanceHasTotalsColumn ropts) >> [Spr.headerCell "Total"]) ++
361-
(guard (average_ ropts) >> [Spr.headerCell "Average"])
363+
(guard (multiBalanceHasTotalsColumn ropts) >> [dataHeaderCell "Total"]) ++
364+
(guard (average_ ropts) >> [dataHeaderCell "Average"])
365+
dataHeaderCell label =
366+
(Spr.headerCell label) {Spr.cellSpan = Spr.SpanHorizontal numSubColumns}
362367
headerrow = leadingHeaders ++ dataHeaders
363368

364369
blankrow =
365370
fmap (Spr.horizontalSpan headerrow . Spr.defaultCell) maybeBlank
371+
numSubColumns =
372+
case layout_ ropts of
373+
LayoutBareWide -> length allCommodities
374+
_ -> 1
375+
allCommodities = allCommoditiesFromSubreports subreports
366376

367377
-- Make rows for a subreport: its title row, not the headings row,
368378
-- the data rows, any totals row, and a blank row for whitespace.
@@ -371,14 +381,18 @@ compoundBalanceReportAsSpreadsheet fmt accountLabel maybeBlank ropts cbr =
371381
subreportrows (subreporttitle, mbr, _increasestotal) =
372382
let
373383
(_, bodyrows, mtotalsrows) =
374-
multiBalanceReportAsSpreadsheetParts fmt ropts mbr
375-
376-
in
377-
Spr.horizontalSpan headerrow
378-
((Spr.defaultCell subreporttitle){
384+
multiBalanceReportAsSpreadsheetParts fmt ropts allCommodities mbr
385+
accountCell =
386+
(Spr.defaultCell subreporttitle) {
379387
Spr.cellStyle = Spr.Body Spr.Total,
380388
Spr.cellClass = Spr.Class "account"
381-
}) :
389+
}
390+
391+
in
392+
(case layout_ ropts of
393+
LayoutBareWide ->
394+
accountCell : map Spr.headerCell (dataHeaders >> allCommodities)
395+
_ -> Spr.horizontalSpan headerrow accountCell) :
382396
bodyrows ++
383397
mtotalsrows ++
384398
maybeToList blankrow ++
@@ -387,7 +401,7 @@ compoundBalanceReportAsSpreadsheet fmt accountLabel maybeBlank ropts cbr =
387401
totalrows =
388402
if no_total_ ropts || length subreports == 1 then []
389403
else
390-
multiBalanceRowAsCellBuilders fmt ropts colspans
404+
multiBalanceRowAsCellBuilders fmt ropts colspans allCommodities
391405
Total simpleDateSpanCell totalrow
392406
-- make a table of rendered lines of the report totals row
393407
& map (map (fmap wbToText))
@@ -399,3 +413,10 @@ compoundBalanceReportAsSpreadsheet fmt accountLabel maybeBlank ropts cbr =
399413
in (title,
400414
((Just 1, Just 1),
401415
headerrow :| concatMap subreportrows subreports ++ totalrows))
416+
417+
allCommoditiesFromSubreports ::
418+
[(text, PeriodicReport a MixedAmount, bool)] -> [CommoditySymbol]
419+
allCommoditiesFromSubreports =
420+
Set.toAscList .
421+
foldMap (\(_,mbr,_) ->
422+
foldMap (foldMap maCommodities . prrAmounts) $ prRows mbr)

0 commit comments

Comments
 (0)