{-| A ledger-compatible @register@ command. -} module Hledger.Cli.Register ( register ,postingsReportAsText -- ,showPostingWithBalanceForVty ,tests_Hledger_Cli_Register ) where import Data.List import Data.Maybe import Test.HUnit import Text.Printf import Hledger import Prelude hiding (putStr) import Hledger.Utils.UTF8IOCompat (putStr) import Hledger.Cli.Options -- | Print a (posting) register report. register :: CliOpts -> Journal -> IO () register opts@CliOpts{reportopts_=ropts} j = do d <- getCurrentDay putStr $ postingsReportAsText opts $ postingsReport ropts (queryFromOpts d ropts) j -- | Render a register report as plain text suitable for console output. postingsReportAsText :: CliOpts -> PostingsReport -> String postingsReportAsText opts = unlines . map (postingsReportItemAsText opts) . snd tests_postingsReportAsText = [ "postingsReportAsText" ~: do -- "unicode in register layout" ~: do j <- readJournal' "2009/01/01 * медвежья шкура\n расходы:покупки 100\n актив:наличные\n" let opts = defreportopts (postingsReportAsText defcliopts $ postingsReport opts (queryFromOpts (parsedate "2008/11/26") opts) j) `is` unlines ["2009/01/01 медвежья шкура расходы:покупки 100 100" ," актив:наличные -100 0"] ] -- | Render one register report line item as plain text. Layout is like so: -- @ -- <----------------------------- width (default: 80) ----------------------------> -- date (10) description (50%) account (50%) amount (12) balance (12) -- DDDDDDDDDD dddddddddddddddddddd aaaaaaaaaaaaaaaaaaa AAAAAAAAAAAA AAAAAAAAAAAA -- -- date and description are shown for the first posting of a transaction only. -- @ postingsReportItemAsText :: CliOpts -> PostingsReportItem -> String postingsReportItemAsText opts (mdate, mdesc, p, b) = concatTopPadded [date, " ", desc, " ", acct, " ", amt, " ", bal] where totalwidth = case widthFromOpts opts of Left _ -> defaultWidth -- shouldn't happen Right (TotalWidth (Width w)) -> w Right (TotalWidth Auto) -> defaultWidth -- XXX Right (FieldWidths _) -> defaultWidth -- XXX datewidth = 10 amtwidth = 12 balwidth = 12 remaining = totalwidth - (datewidth + 1 + 2 + amtwidth + 2 + balwidth) (descwidth, acctwidth) | even r = (r', r') | otherwise = (r', r'+1) where r = remaining - 2 r' = r `div` 2 date = maybe (replicate datewidth ' ') (printf ("%-"++show datewidth++"s") . showDate) mdate desc = maybe (replicate descwidth ' ') (printf ("%-"++show descwidth++"s") . take descwidth . elideRight descwidth) mdesc acct = printf ("%-"++(show acctwidth)++"s") a where a = bracket $ elideAccountName awidth $ paccount p (bracket, awidth) = case ptype p of BalancedVirtualPosting -> (\s -> "["++s++"]", acctwidth-2) VirtualPosting -> (\s -> "("++s++")", acctwidth-2) _ -> (id,acctwidth) amt = padleft amtwidth $ showMixedAmountWithoutPrice $ pamount p bal = padleft balwidth $ showMixedAmountWithoutPrice b -- XXX -- showPostingWithBalanceForVty showtxninfo p b = postingsReportItemAsText defreportopts $ mkpostingsReportItem showtxninfo p b tests_Hledger_Cli_Register :: Test tests_Hledger_Cli_Register = TestList tests_postingsReportAsText