From 7b136600fa80ed307c3f6598bf981ce01d9f667d Mon Sep 17 00:00:00 2001 From: Henning Thielemann Date: Sat, 10 Aug 2024 10:13:30 +0200 Subject: [PATCH] cli: Cli.Balance.balanceReportAsFods: use distinguished cell formatting styles --- hledger-lib/Hledger/Write/Ods.hs | 62 ++++++++++++++++++++++--- hledger/Hledger/Cli/Commands/Balance.hs | 40 +++++++++++++++- 2 files changed, 95 insertions(+), 7 deletions(-) diff --git a/hledger-lib/Hledger/Write/Ods.hs b/hledger-lib/Hledger/Write/Ods.hs index 0b93e4d13..31d95ad6c 100644 --- a/hledger-lib/Hledger/Write/Ods.hs +++ b/hledger-lib/Hledger/Write/Ods.hs @@ -21,8 +21,30 @@ import qualified System.IO as IO import Text.Printf (printf) +data Type = TypeString | TypeAmount + deriving (Eq, Ord, Show) + +data Style = Ordinary | Head | Foot + deriving (Eq, Ord, Show) + +data Cell = + Cell { + cellType :: Type, + cellStyle :: Style, + cellContent :: Text + } + +defaultCell :: Cell +defaultCell = + Cell { + cellType = TypeString, + cellStyle = Ordinary, + cellContent = T.empty + } + + printFods :: - IO.TextEncoding -> Map Text ((Maybe Int, Maybe Int), [[Text]]) -> TL.Text + IO.TextEncoding -> Map Text ((Maybe Int, Maybe Int), [[Cell]]) -> TL.Text printFods encoding tables = let fileOpen = map (map (\c -> case c of '\'' -> '"'; _ -> c)) $ @@ -45,6 +67,22 @@ printFods encoding tables = " xmlns:of='urn:oasis:names:tc:opendocument:xmlns:of:1.2'" : " xmlns:field='urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0'" : " xmlns:form='urn:oasis:names:tc:opendocument:xmlns:form:1.0'>" : + "" : + " " : + " " : + " " : + " " : + " " : + " " : + " " : + " " : + " " : + " " : + " " : + " " : + " " : + " " : + "" : [] fileClose = @@ -98,12 +136,24 @@ printFods encoding tables = tableOpen name ++ (table >>= \row -> "" : - (row >>= \cell -> - "" : - printf "%s" cell : - "" : - []) ++ + (row >>= formatCell) ++ "" : []) ++ tableClose) ++ fileClose + +formatCell :: Cell -> [String] +formatCell cell = + let style :: String + style = + case (cellStyle cell, cellType cell) of + (Ordinary, TypeString) -> "" + (Ordinary, TypeAmount) -> " table:style-name='amount'" + (Foot, TypeString) -> " table:style-name='foot'" + (Foot, TypeAmount) -> " table:style-name='total-amount'" + (Head, _) -> " table:style-name='head'" + in + printf "" style : + printf "%s" (cellContent cell) : + "" : + [] diff --git a/hledger/Hledger/Cli/Commands/Balance.hs b/hledger/Hledger/Cli/Commands/Balance.hs index 745be9a91..a78bdbb9c 100644 --- a/hledger/Hledger/Cli/Commands/Balance.hs +++ b/hledger/Hledger/Cli/Commands/Balance.hs @@ -248,6 +248,7 @@ module Hledger.Cli.Commands.Balance ( -- ** balance output rendering ,balanceReportAsText ,balanceReportAsCsv + ,balanceReportAsFods ,balanceReportItemAsText ,multiBalanceRowAsCsvText ,multiBalanceRowAsText @@ -304,6 +305,7 @@ import Hledger.Cli.CliOptions import Hledger.Cli.Utils import Hledger.Write.Csv (CSV, printCSV, printTSV) import Hledger.Write.Ods (printFods) +import qualified Hledger.Write.Ods as Ods -- | Command line options for this command. @@ -402,7 +404,7 @@ balance opts@CliOpts{reportspec_=rspec} j = case balancecalc_ of "tsv" -> \ropts1 -> printTSV . balanceReportAsCsv ropts1 -- "html" -> \ropts -> (<>"\n") . L.renderText . multiBalanceReportAsHtml ropts . balanceReportAsMultiBalanceReport ropts "json" -> const $ (<>"\n") . toJsonText - "fods" -> \ropts1 -> printFods IO.localeEncoding . Map.singleton "Hledger" . (,) (Just 1, Nothing) . balanceReportAsCsv ropts1 + "fods" -> \ropts1 -> printFods IO.localeEncoding . Map.singleton "Hledger" . (,) (Just 1, Nothing) . balanceReportAsFods ropts1 _ -> error' $ unsupportedOutputFormatError fmt -- PARTIAL: writeOutputLazyText opts $ render ropts report where @@ -557,6 +559,42 @@ renderComponent topaligned oneline opts (acctname, dep, total) (FormatField ljus ,displayColour = color_ opts } +-- | Render a single-column balance report as FODS. +balanceReportAsFods :: ReportOpts -> BalanceReport -> [[Ods.Cell]] +balanceReportAsFods opts (items, total) = + headers : + concatMap (\(a, _, _, b) -> rows a b) items ++ + if no_total_ opts then [] + else map (map (\c -> c {Ods.cellStyle = Ods.Foot})) $ + rows totalRowHeadingCsv total + where + cell content = Ods.defaultCell { Ods.cellContent = content } + headers = + map (\content -> (cell content) {Ods.cellStyle = Ods.Head}) $ + "account" : case layout_ opts of + LayoutBare -> ["commodity", "balance"] + _ -> ["balance"] + rows :: AccountName -> MixedAmount -> [[Ods.Cell]] + rows name ma = case layout_ opts of + LayoutBare -> + map (\a -> + [showName name, + cell $ acommodity a, + renderAmount $ mixedAmount a]) + . amounts $ mixedAmountStripCosts ma + _ -> [[showName name, renderAmount ma]] + + showName = cell . accountNameDrop (drop_ opts) + renderAmount amt = + (cell $ wbToText $ showMixedAmountB bopts amt) { + Ods.cellType = Ods.TypeAmount + } + where + bopts = machineFmt{displayCommodity=showcomm, displayCommodityOrder = commorder} + (showcomm, commorder) + | layout_ opts == LayoutBare = (False, Just $ S.toList $ maCommodities amt) + | otherwise = (True, Nothing) + -- Multi-column balance reports -- | Render a multi-column balance report as CSV.