{-# LANGUAGE CPP #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TemplateHaskell #-}
module Hledger.Cli.Commands.Aregister (
aregistermode
,aregister
,tests_Aregister
) where
import Control.Monad (when)
import Data.Aeson (toJSON)
import Data.Aeson.Text (encodeToLazyText)
import Data.List
import Data.Maybe
#if !(MIN_VERSION_base(4,11,0))
import Data.Semigroup ((<>))
#endif
import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
import Data.Time (addDays)
import Safe (headDef)
import System.Console.CmdArgs.Explicit
import Hledger.Read.CsvReader (CSV, CsvRecord, printCSV)
import Hledger
import Hledger.Cli.CliOptions
import Hledger.Cli.Utils
aregistermode :: Mode RawOpts
aregistermode = CommandDoc
-> [Flag RawOpts]
-> [(CommandDoc, [Flag RawOpts])]
-> [Flag RawOpts]
-> ([Arg RawOpts], Maybe (Arg RawOpts))
-> Mode RawOpts
hledgerCommandMode
$(embedFileRelative "Hledger/Cli/Commands/Aregister.txt")
([
[CommandDoc] -> (RawOpts -> RawOpts) -> CommandDoc -> Flag RawOpts
forall a. [CommandDoc] -> (a -> a) -> CommandDoc -> Flag a
flagNone ["txn-dates"] (CommandDoc -> RawOpts -> RawOpts
setboolopt "txn-dates")
"filter strictly by transaction date, not posting date. Warning: this can show a wrong running balance."
,[CommandDoc] -> (RawOpts -> RawOpts) -> CommandDoc -> Flag RawOpts
forall a. [CommandDoc] -> (a -> a) -> CommandDoc -> Flag a
flagNone ["no-elide"] (CommandDoc -> RawOpts -> RawOpts
setboolopt "no-elide") "don't limit amount commodities shown to 2"
,[CommandDoc]
-> Update RawOpts -> CommandDoc -> CommandDoc -> Flag RawOpts
forall a.
[CommandDoc] -> Update a -> CommandDoc -> CommandDoc -> Flag a
flagReq ["width","w"] (\s :: CommandDoc
s opts :: RawOpts
opts -> RawOpts -> Either CommandDoc RawOpts
forall a b. b -> Either a b
Right (RawOpts -> Either CommandDoc RawOpts)
-> RawOpts -> Either CommandDoc RawOpts
forall a b. (a -> b) -> a -> b
$ CommandDoc -> CommandDoc -> RawOpts -> RawOpts
setopt "width" CommandDoc
s RawOpts
opts) "N"
("set output width (default: " CommandDoc -> CommandDoc -> CommandDoc
forall a. [a] -> [a] -> [a]
++
#ifdef mingw32_HOST_OS
show defaultWidth
#else
"terminal width"
#endif
CommandDoc -> CommandDoc -> CommandDoc
forall a. [a] -> [a] -> [a]
++ " or $COLUMNS). -wN,M sets description width as well."
)
,[CommandDoc] -> Flag RawOpts
outputFormatFlag ["txt","csv","json"]
,Flag RawOpts
outputFileFlag
])
[(CommandDoc, [Flag RawOpts])
generalflagsgroup1]
[Flag RawOpts]
hiddenflags
([], Arg RawOpts -> Maybe (Arg RawOpts)
forall a. a -> Maybe a
Just (Arg RawOpts -> Maybe (Arg RawOpts))
-> Arg RawOpts -> Maybe (Arg RawOpts)
forall a b. (a -> b) -> a -> b
$ CommandDoc -> Arg RawOpts
argsFlag "ACCTPAT [QUERY]")
aregister :: CliOpts -> Journal -> IO ()
aregister :: CliOpts -> Journal -> IO ()
aregister opts :: CliOpts
opts@CliOpts{rawopts_ :: CliOpts -> RawOpts
rawopts_=RawOpts
rawopts,reportopts_ :: CliOpts -> ReportOpts
reportopts_=ReportOpts
ropts} j :: Journal
j = do
Day
d <- IO Day
getCurrentDay
let args' :: [CommandDoc]
args' = CommandDoc -> RawOpts -> [CommandDoc]
listofstringopt "args" RawOpts
rawopts
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when ([CommandDoc] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [CommandDoc]
args') (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ CommandDoc -> IO ()
forall a. CommandDoc -> a
error' "aregister needs an account, please provide an account name or pattern"
let
(apat :: CommandDoc
apat:queryargs :: [CommandDoc]
queryargs) = [CommandDoc]
args'
acct :: Text
acct = Text -> [Text] -> Text
forall a. a -> [a] -> a
headDef (CommandDoc -> Text
forall a. CommandDoc -> a
error' (CommandDoc -> Text) -> CommandDoc -> Text
forall a b. (a -> b) -> a -> b
$ CommandDoc -> CommandDoc
forall a. Show a => a -> CommandDoc
show CommandDoc
apatCommandDoc -> CommandDoc -> CommandDoc
forall a. [a] -> [a] -> [a]
++" did not match any account")
([Text] -> Text) -> ([Text] -> [Text]) -> [Text] -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Text] -> [Text]
filterAccts ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$ Journal -> [Text]
journalAccountNames Journal
j
filterAccts :: [Text] -> [Text]
filterAccts = case CommandDoc -> Either CommandDoc Regexp
toRegexCI CommandDoc
apat of
Right re :: Regexp
re -> (Text -> Bool) -> [Text] -> [Text]
forall a. (a -> Bool) -> [a] -> [a]
filter (Regexp -> CommandDoc -> Bool
regexMatch Regexp
re (CommandDoc -> Bool) -> (Text -> CommandDoc) -> Text -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> CommandDoc
T.unpack)
Left _ -> [Text] -> [Text] -> [Text]
forall a b. a -> b -> a
const []
inclusive :: Bool
inclusive = Bool
True
thisacctq :: Query
thisacctq = Regexp -> Query
Acct (Regexp -> Query) -> Regexp -> Query
forall a b. (a -> b) -> a -> b
$ (if Bool
inclusive then Text -> Regexp
accountNameToAccountRegex else Text -> Regexp
accountNameToAccountOnlyRegex) Text
acct
ropts' :: ReportOpts
ropts' = ReportOpts
ropts{
query_ :: CommandDoc
query_=[CommandDoc] -> CommandDoc
unwords ([CommandDoc] -> CommandDoc) -> [CommandDoc] -> CommandDoc
forall a b. (a -> b) -> a -> b
$ (CommandDoc -> CommandDoc) -> [CommandDoc] -> [CommandDoc]
forall a b. (a -> b) -> [a] -> [b]
map CommandDoc -> CommandDoc
quoteIfNeeded ([CommandDoc] -> [CommandDoc]) -> [CommandDoc] -> [CommandDoc]
forall a b. (a -> b) -> a -> b
$ [CommandDoc]
queryargs
,depth_ :: Maybe Int
depth_=Maybe Int
forall a. Maybe a
Nothing
,balancetype_ :: BalanceType
balancetype_= BalanceType
HistoricalBalance
}
reportq :: Query
reportq = [Query] -> Query
And [Day -> ReportOpts -> Query
queryFromOpts Day
d ReportOpts
ropts', Bool -> Query
excludeforecastq (Maybe DateSpan -> Bool
forall a. Maybe a -> Bool
isJust (Maybe DateSpan -> Bool) -> Maybe DateSpan -> Bool
forall a b. (a -> b) -> a -> b
$ ReportOpts -> Maybe DateSpan
forecast_ ReportOpts
ropts)]
where
excludeforecastq :: Bool -> Query
excludeforecastq True = Query
Any
excludeforecastq False =
[Query] -> Query
And [
Query -> Query
Not (DateSpan -> Query
Date (DateSpan -> Query) -> DateSpan -> Query
forall a b. (a -> b) -> a -> b
$ Maybe Day -> Maybe Day -> DateSpan
DateSpan (Day -> Maybe Day
forall a. a -> Maybe a
Just (Day -> Maybe Day) -> Day -> Maybe Day
forall a b. (a -> b) -> a -> b
$ Integer -> Day -> Day
addDays 1 Day
d) Maybe Day
forall a. Maybe a
Nothing)
,Query -> Query
Not Query
generatedTransactionTag
]
(balancelabel :: CommandDoc
balancelabel,items :: [AccountTransactionsReportItem]
items) = ReportOpts
-> Journal
-> Query
-> Query
-> (CommandDoc, [AccountTransactionsReportItem])
accountTransactionsReport ReportOpts
ropts' Journal
j Query
reportq Query
thisacctq
items' :: [AccountTransactionsReportItem]
items' = (if ReportOpts -> Bool
empty_ ReportOpts
ropts then [AccountTransactionsReportItem] -> [AccountTransactionsReportItem]
forall a. a -> a
id else (AccountTransactionsReportItem -> Bool)
-> [AccountTransactionsReportItem]
-> [AccountTransactionsReportItem]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool)
-> (AccountTransactionsReportItem -> Bool)
-> AccountTransactionsReportItem
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MixedAmount -> Bool
mixedAmountLooksZero (MixedAmount -> Bool)
-> (AccountTransactionsReportItem -> MixedAmount)
-> AccountTransactionsReportItem
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AccountTransactionsReportItem -> MixedAmount
forall a b c d e f. (a, b, c, d, e, f) -> e
fifth6)) ([AccountTransactionsReportItem]
-> [AccountTransactionsReportItem])
-> [AccountTransactionsReportItem]
-> [AccountTransactionsReportItem]
forall a b. (a -> b) -> a -> b
$
[AccountTransactionsReportItem] -> [AccountTransactionsReportItem]
forall a. [a] -> [a]
reverse [AccountTransactionsReportItem]
items
render :: (CommandDoc, [AccountTransactionsReportItem]) -> CommandDoc
render | CommandDoc
fmtCommandDoc -> CommandDoc -> Bool
forall a. Eq a => a -> a -> Bool
=="json" = (CommandDoc -> CommandDoc -> CommandDoc
forall a. [a] -> [a] -> [a]
++"\n") (CommandDoc -> CommandDoc)
-> ((CommandDoc, [AccountTransactionsReportItem]) -> CommandDoc)
-> (CommandDoc, [AccountTransactionsReportItem])
-> CommandDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> CommandDoc
T.unpack (Text -> CommandDoc)
-> ((CommandDoc, [AccountTransactionsReportItem]) -> Text)
-> (CommandDoc, [AccountTransactionsReportItem])
-> CommandDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
TL.toStrict (Text -> Text)
-> ((CommandDoc, [AccountTransactionsReportItem]) -> Text)
-> (CommandDoc, [AccountTransactionsReportItem])
-> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value -> Text
forall a. ToJSON a => a -> Text
encodeToLazyText (Value -> Text)
-> ((CommandDoc, [AccountTransactionsReportItem]) -> Value)
-> (CommandDoc, [AccountTransactionsReportItem])
-> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (CommandDoc, [AccountTransactionsReportItem]) -> Value
forall a. ToJSON a => a -> Value
toJSON
| CommandDoc
fmtCommandDoc -> CommandDoc -> Bool
forall a. Eq a => a -> a -> Bool
=="csv" = (CommandDoc -> CommandDoc -> CommandDoc
forall a. [a] -> [a] -> [a]
++"\n") (CommandDoc -> CommandDoc)
-> ((CommandDoc, [AccountTransactionsReportItem]) -> CommandDoc)
-> (CommandDoc, [AccountTransactionsReportItem])
-> CommandDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CSV -> CommandDoc
printCSV (CSV -> CommandDoc)
-> ((CommandDoc, [AccountTransactionsReportItem]) -> CSV)
-> (CommandDoc, [AccountTransactionsReportItem])
-> CommandDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Query
-> Query -> (CommandDoc, [AccountTransactionsReportItem]) -> CSV
accountTransactionsReportAsCsv Query
reportq Query
thisacctq
| CommandDoc
fmtCommandDoc -> CommandDoc -> Bool
forall a. Eq a => a -> a -> Bool
=="txt" = CliOpts
-> Query
-> Query
-> (CommandDoc, [AccountTransactionsReportItem])
-> CommandDoc
accountTransactionsReportAsText CliOpts
opts Query
reportq Query
thisacctq
| Bool
otherwise = CommandDoc
-> (CommandDoc, [AccountTransactionsReportItem]) -> CommandDoc
forall a b. a -> b -> a
const (CommandDoc
-> (CommandDoc, [AccountTransactionsReportItem]) -> CommandDoc)
-> CommandDoc
-> (CommandDoc, [AccountTransactionsReportItem])
-> CommandDoc
forall a b. (a -> b) -> a -> b
$ CommandDoc -> CommandDoc
forall a. CommandDoc -> a
error' (CommandDoc -> CommandDoc) -> CommandDoc -> CommandDoc
forall a b. (a -> b) -> a -> b
$ CommandDoc -> CommandDoc
unsupportedOutputFormatError CommandDoc
fmt
where
fmt :: CommandDoc
fmt = CliOpts -> CommandDoc
outputFormatFromOpts CliOpts
opts
CliOpts -> CommandDoc -> IO ()
writeOutput CliOpts
opts (CommandDoc -> IO ()) -> CommandDoc -> IO ()
forall a b. (a -> b) -> a -> b
$ (CommandDoc, [AccountTransactionsReportItem]) -> CommandDoc
render (CommandDoc
balancelabel,[AccountTransactionsReportItem]
items')
accountTransactionsReportAsCsv :: Query -> Query -> AccountTransactionsReport -> CSV
accountTransactionsReportAsCsv :: Query
-> Query -> (CommandDoc, [AccountTransactionsReportItem]) -> CSV
accountTransactionsReportAsCsv reportq :: Query
reportq thisacctq :: Query
thisacctq (_,is :: [AccountTransactionsReportItem]
is) =
["txnidx","date","code","description","otheraccounts","change","balance"]
[CommandDoc] -> CSV -> CSV
forall a. a -> [a] -> [a]
: (AccountTransactionsReportItem -> [CommandDoc])
-> [AccountTransactionsReportItem] -> CSV
forall a b. (a -> b) -> [a] -> [b]
map (Query -> Query -> AccountTransactionsReportItem -> [CommandDoc]
accountTransactionsReportItemAsCsvRecord Query
reportq Query
thisacctq) [AccountTransactionsReportItem]
is
accountTransactionsReportItemAsCsvRecord :: Query -> Query -> AccountTransactionsReportItem -> CsvRecord
accountTransactionsReportItemAsCsvRecord :: Query -> Query -> AccountTransactionsReportItem -> [CommandDoc]
accountTransactionsReportItemAsCsvRecord
reportq :: Query
reportq thisacctq :: Query
thisacctq
(t :: Transaction
t@Transaction{Integer
tindex :: Transaction -> Integer
tindex :: Integer
tindex,Text
tcode :: Transaction -> Text
tcode :: Text
tcode,Text
tdescription :: Transaction -> Text
tdescription :: Text
tdescription}, _, _issplit :: Bool
_issplit, otheracctsstr :: CommandDoc
otheracctsstr, change :: MixedAmount
change, balance :: MixedAmount
balance)
= [CommandDoc
idx,CommandDoc
date,CommandDoc
code,CommandDoc
desc,CommandDoc
otheracctsstr,CommandDoc
amt,CommandDoc
bal]
where
idx :: CommandDoc
idx = Integer -> CommandDoc
forall a. Show a => a -> CommandDoc
show Integer
tindex
date :: CommandDoc
date = Day -> CommandDoc
showDate (Day -> CommandDoc) -> Day -> CommandDoc
forall a b. (a -> b) -> a -> b
$ Query -> Query -> Transaction -> Day
transactionRegisterDate Query
reportq Query
thisacctq Transaction
t
code :: CommandDoc
code = Text -> CommandDoc
T.unpack Text
tcode
desc :: CommandDoc
desc = Text -> CommandDoc
T.unpack Text
tdescription
amt :: CommandDoc
amt = Bool -> MixedAmount -> CommandDoc
showMixedAmountOneLineWithoutPrice Bool
False MixedAmount
change
bal :: CommandDoc
bal = Bool -> MixedAmount -> CommandDoc
showMixedAmountOneLineWithoutPrice Bool
False MixedAmount
balance
accountTransactionsReportAsText :: CliOpts -> Query -> Query -> AccountTransactionsReport -> String
accountTransactionsReportAsText :: CliOpts
-> Query
-> Query
-> (CommandDoc, [AccountTransactionsReportItem])
-> CommandDoc
accountTransactionsReportAsText
copts :: CliOpts
copts@CliOpts{reportopts_ :: CliOpts -> ReportOpts
reportopts_=ReportOpts{Bool
no_elide_ :: ReportOpts -> Bool
no_elide_ :: Bool
no_elide_}} reportq :: Query
reportq thisacctq :: Query
thisacctq (_balancelabel :: CommandDoc
_balancelabel,items :: [AccountTransactionsReportItem]
items)
= [CommandDoc] -> CommandDoc
unlines ([CommandDoc] -> CommandDoc) -> [CommandDoc] -> CommandDoc
forall a b. (a -> b) -> a -> b
$ CommandDoc
title CommandDoc -> [CommandDoc] -> [CommandDoc]
forall a. a -> [a] -> [a]
:
(AccountTransactionsReportItem -> CommandDoc)
-> [AccountTransactionsReportItem] -> [CommandDoc]
forall a b. (a -> b) -> [a] -> [b]
map (CliOpts
-> Query
-> Query
-> Int
-> Int
-> AccountTransactionsReportItem
-> CommandDoc
accountTransactionsReportItemAsText CliOpts
copts Query
reportq Query
thisacctq Int
amtwidth Int
balwidth) [AccountTransactionsReportItem]
items
where
amtwidth :: Int
amtwidth = [Int] -> Int
forall a. Ord a => [a] -> a
maximumStrict ([Int] -> Int) -> [Int] -> Int
forall a b. (a -> b) -> a -> b
$ 12 Int -> [Int] -> [Int]
forall a. a -> [a] -> [a]
: (AccountTransactionsReportItem -> Int)
-> [AccountTransactionsReportItem] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (CommandDoc -> Int
strWidth (CommandDoc -> Int)
-> (AccountTransactionsReportItem -> CommandDoc)
-> AccountTransactionsReportItem
-> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MixedAmount -> CommandDoc
showamt (MixedAmount -> CommandDoc)
-> (AccountTransactionsReportItem -> MixedAmount)
-> AccountTransactionsReportItem
-> CommandDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AccountTransactionsReportItem -> MixedAmount
forall a b c d e f. (a, b, c, d, e, f) -> e
itemamt) [AccountTransactionsReportItem]
items
balwidth :: Int
balwidth = [Int] -> Int
forall a. Ord a => [a] -> a
maximumStrict ([Int] -> Int) -> [Int] -> Int
forall a b. (a -> b) -> a -> b
$ 12 Int -> [Int] -> [Int]
forall a. a -> [a] -> [a]
: (AccountTransactionsReportItem -> Int)
-> [AccountTransactionsReportItem] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (CommandDoc -> Int
strWidth (CommandDoc -> Int)
-> (AccountTransactionsReportItem -> CommandDoc)
-> AccountTransactionsReportItem
-> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MixedAmount -> CommandDoc
showamt (MixedAmount -> CommandDoc)
-> (AccountTransactionsReportItem -> MixedAmount)
-> AccountTransactionsReportItem
-> CommandDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AccountTransactionsReportItem -> MixedAmount
forall a b c d e f. (a, b, c, d, e, f) -> f
itembal) [AccountTransactionsReportItem]
items
showamt :: MixedAmount -> CommandDoc
showamt
| Bool
no_elide_ = Bool -> MixedAmount -> CommandDoc
showMixedAmountOneLineWithoutPrice Bool
False
| Bool
otherwise = Bool -> MixedAmount -> CommandDoc
showMixedAmountElided Bool
False
itemamt :: (a, b, c, d, e, f) -> e
itemamt (_,_,_,_,a :: e
a,_) = e
a
itembal :: (a, b, c, d, e, f) -> f
itembal (_,_,_,_,_,a :: f
a) = f
a
title :: CommandDoc
title = Text -> CommandDoc
T.unpack (Text -> CommandDoc) -> Text -> CommandDoc
forall a b. (a -> b) -> a -> b
$ Text -> (Text -> Text) -> Maybe Text -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe "" (("Transactions in "Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>)(Text -> Text) -> (Text -> Text) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>" and subaccounts:")) Maybe Text
macct
where
macct :: Maybe Text
macct = case (Query -> Bool) -> Query -> Query
filterQuery Query -> Bool
queryIsAcct Query
thisacctq of
Acct r :: Regexp
r -> Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> Maybe Text)
-> (CommandDoc -> Text) -> CommandDoc -> Maybe Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Text -> Text
T.drop 1 (Text -> Text) -> (CommandDoc -> Text) -> CommandDoc -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Text -> Text
T.dropEnd 5 (Text -> Text) -> (CommandDoc -> Text) -> CommandDoc -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CommandDoc -> Text
T.pack (CommandDoc -> Maybe Text) -> CommandDoc -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Regexp -> CommandDoc
reString Regexp
r
_ -> Maybe Text
forall a. Maybe a
Nothing
accountTransactionsReportItemAsText :: CliOpts -> Query -> Query -> Int -> Int -> AccountTransactionsReportItem -> String
accountTransactionsReportItemAsText :: CliOpts
-> Query
-> Query
-> Int
-> Int
-> AccountTransactionsReportItem
-> CommandDoc
accountTransactionsReportItemAsText
copts :: CliOpts
copts@CliOpts{reportopts_ :: CliOpts -> ReportOpts
reportopts_=ReportOpts{Bool
color_ :: ReportOpts -> Bool
color_ :: Bool
color_,Bool
no_elide_ :: Bool
no_elide_ :: ReportOpts -> Bool
no_elide_}}
reportq :: Query
reportq thisacctq :: Query
thisacctq preferredamtwidth :: Int
preferredamtwidth preferredbalwidth :: Int
preferredbalwidth
(t :: Transaction
t@Transaction{Text
tdescription :: Text
tdescription :: Transaction -> Text
tdescription}, _, _issplit :: Bool
_issplit, otheracctsstr :: CommandDoc
otheracctsstr, change :: MixedAmount
change, balance :: MixedAmount
balance)
= CommandDoc -> [CommandDoc] -> CommandDoc
forall a. [a] -> [[a]] -> [a]
intercalate "\n" ([CommandDoc] -> CommandDoc) -> [CommandDoc] -> CommandDoc
forall a b. (a -> b) -> a -> b
$
[CommandDoc] -> CommandDoc
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [Maybe Int -> Maybe Int -> Bool -> Bool -> CommandDoc -> CommandDoc
fitString (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
datewidth) (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
datewidth) Bool
True Bool
True CommandDoc
date
," "
,Maybe Int -> Maybe Int -> Bool -> Bool -> CommandDoc -> CommandDoc
fitString (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
descwidth) (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
descwidth) Bool
True Bool
True CommandDoc
desc
," "
,Maybe Int -> Maybe Int -> Bool -> Bool -> CommandDoc -> CommandDoc
fitString (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
acctwidth) (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
acctwidth) Bool
True Bool
True CommandDoc
accts
," "
,Maybe Int -> Maybe Int -> Bool -> Bool -> CommandDoc -> CommandDoc
fitString (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
amtwidth) (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
amtwidth) Bool
True Bool
False CommandDoc
amtfirstline
," "
,Maybe Int -> Maybe Int -> Bool -> Bool -> CommandDoc -> CommandDoc
fitString (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
balwidth) (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
balwidth) Bool
True Bool
False CommandDoc
balfirstline
]
CommandDoc -> [CommandDoc] -> [CommandDoc]
forall a. a -> [a] -> [a]
:
[[CommandDoc] -> CommandDoc
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [CommandDoc
spacer
,Maybe Int -> Maybe Int -> Bool -> Bool -> CommandDoc -> CommandDoc
fitString (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
amtwidth) (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
amtwidth) Bool
True Bool
False CommandDoc
a
," "
,Maybe Int -> Maybe Int -> Bool -> Bool -> CommandDoc -> CommandDoc
fitString (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
balwidth) (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
balwidth) Bool
True Bool
False CommandDoc
b
]
| (a :: CommandDoc
a,b :: CommandDoc
b) <- [CommandDoc] -> [CommandDoc] -> [(CommandDoc, CommandDoc)]
forall a b. [a] -> [b] -> [(a, b)]
zip [CommandDoc]
amtrest [CommandDoc]
balrest
]
where
(totalwidth :: Int
totalwidth,mdescwidth :: Maybe Int
mdescwidth) = CliOpts -> (Int, Maybe Int)
registerWidthsFromOpts CliOpts
copts
(datewidth :: Int
datewidth, date :: CommandDoc
date) = (10, Day -> CommandDoc
showDate (Day -> CommandDoc) -> Day -> CommandDoc
forall a b. (a -> b) -> a -> b
$ Query -> Query -> Transaction -> Day
transactionRegisterDate Query
reportq Query
thisacctq Transaction
t)
(amtwidth :: Int
amtwidth, balwidth :: Int
balwidth)
| Int
shortfall Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= 0 = (Int
preferredamtwidth, Int
preferredbalwidth)
| Bool
otherwise = (Int
adjustedamtwidth, Int
adjustedbalwidth)
where
mincolwidth :: Int
mincolwidth = 2
maxamtswidth :: Int
maxamtswidth = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max 0 (Int
totalwidth Int -> Int -> Int
forall a. Num a => a -> a -> a
- (Int
datewidth Int -> Int -> Int
forall a. Num a => a -> a -> a
+ 1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
mincolwidth Int -> Int -> Int
forall a. Num a => a -> a -> a
+ 2 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
mincolwidth Int -> Int -> Int
forall a. Num a => a -> a -> a
+ 2 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ 2))
shortfall :: Int
shortfall = (Int
preferredamtwidth Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
preferredbalwidth) Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
maxamtswidth
amtwidthproportion :: Double
amtwidthproportion = Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
preferredamtwidth Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
preferredamtwidth Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
preferredbalwidth)
adjustedamtwidth :: Int
adjustedamtwidth = Double -> Int
forall a b. (RealFrac a, Integral b) => a -> b
round (Double -> Int) -> Double -> Int
forall a b. (a -> b) -> a -> b
$ Double
amtwidthproportion Double -> Double -> Double
forall a. Num a => a -> a -> a
* Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
maxamtswidth
adjustedbalwidth :: Int
adjustedbalwidth = Int
maxamtswidth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
adjustedamtwidth
remaining :: Int
remaining = Int
totalwidth Int -> Int -> Int
forall a. Num a => a -> a -> a
- (Int
datewidth Int -> Int -> Int
forall a. Num a => a -> a -> a
+ 1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ 2 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
amtwidth Int -> Int -> Int
forall a. Num a => a -> a -> a
+ 2 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
balwidth)
(descwidth :: Int
descwidth, acctwidth :: Int
acctwidth) = (Int
w, Int
remaining Int -> Int -> Int
forall a. Num a => a -> a -> a
- 2 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
w)
where
w :: Int
w = Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe ((Int
remaining Int -> Int -> Int
forall a. Num a => a -> a -> a
- 2) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` 2) Maybe Int
mdescwidth
desc :: CommandDoc
desc = Text -> CommandDoc
T.unpack Text
tdescription
accts :: CommandDoc
accts =
CommandDoc
otheracctsstr
showamt :: MixedAmount -> CommandDoc
showamt
| Bool
no_elide_ = Bool -> MixedAmount -> CommandDoc
showMixedAmountOneLineWithoutPrice Bool
color_
| Bool
otherwise = Bool -> MixedAmount -> CommandDoc
showMixedAmountElided Bool
color_
amt :: CommandDoc
amt = MixedAmount -> CommandDoc
showamt MixedAmount
change
bal :: CommandDoc
bal = MixedAmount -> CommandDoc
showamt MixedAmount
balance
(amtlines :: [CommandDoc]
amtlines, ballines :: [CommandDoc]
ballines) = (CommandDoc -> [CommandDoc]
lines CommandDoc
amt, CommandDoc -> [CommandDoc]
lines CommandDoc
bal)
(amtlen :: Int
amtlen, ballen :: Int
ballen) = ([CommandDoc] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [CommandDoc]
amtlines, [CommandDoc] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [CommandDoc]
ballines)
numlines :: Int
numlines = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max 1 (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
amtlen Int
ballen)
(amtfirstline :: CommandDoc
amtfirstline:amtrest :: [CommandDoc]
amtrest) = Int -> [CommandDoc] -> [CommandDoc]
forall a. Int -> [a] -> [a]
take Int
numlines ([CommandDoc] -> [CommandDoc]) -> [CommandDoc] -> [CommandDoc]
forall a b. (a -> b) -> a -> b
$ [CommandDoc]
amtlines [CommandDoc] -> [CommandDoc] -> [CommandDoc]
forall a. [a] -> [a] -> [a]
++ CommandDoc -> [CommandDoc]
forall a. a -> [a]
repeat ""
(balfirstline :: CommandDoc
balfirstline:balrest :: [CommandDoc]
balrest) = Int -> [CommandDoc] -> [CommandDoc]
forall a. Int -> [a] -> [a]
take Int
numlines ([CommandDoc] -> [CommandDoc]) -> [CommandDoc] -> [CommandDoc]
forall a b. (a -> b) -> a -> b
$ Int -> CommandDoc -> [CommandDoc]
forall a. Int -> a -> [a]
replicate (Int
numlines Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
ballen) "" [CommandDoc] -> [CommandDoc] -> [CommandDoc]
forall a. [a] -> [a] -> [a]
++ [CommandDoc]
ballines
spacer :: CommandDoc
spacer = Int -> Char -> CommandDoc
forall a. Int -> a -> [a]
replicate (Int
totalwidth Int -> Int -> Int
forall a. Num a => a -> a -> a
- (Int
amtwidth Int -> Int -> Int
forall a. Num a => a -> a -> a
+ 2 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
balwidth)) ' '
tests_Aregister :: TestTree
tests_Aregister = CommandDoc -> [TestTree] -> TestTree
tests "Aregister" [
]