module Penny.Cabin.Balance.Convert.Parser (
Opts(..)
, Target(..)
, SortBy(..)
, RoundTo(..)
, allOptSpecs
) where
import qualified Data.Text as X
import qualified Penny.Cabin.Options as CO
import qualified Penny.Cabin.Parsers as P
import qualified Penny.Lincoln as L
import qualified Penny.Copper.Parsec as Pc
import qualified System.Console.MultiArg.Combinator as C
import qualified Text.Parsec as Parsec
newtype RoundTo = RoundTo { unRoundTo :: L.NonNegative }
deriving (Eq, Show, Ord)
data Target = AutoTarget | ManualTarget L.To
data SortBy = SortByQty | SortByName deriving (Eq, Show, Ord)
data Opts = Opts
{ showZeroBalances :: CO.ShowZeroBalances
, target :: Target
, dateTime :: L.DateTime
, sortOrder :: P.SortOrder
, sortBy :: SortBy
, percentRpt :: Maybe RoundTo
}
allOptSpecs :: [C.OptSpec (Opts -> Opts)]
allOptSpecs =
[ parseZeroBalances
, parseCommodity
, parseAuto
, parseDate
, parseSort
, parseOrder
, parsePct
, parseRound
]
parseZeroBalances :: C.OptSpec (Opts -> Opts)
parseZeroBalances = fmap f P.zeroBalances
where
f x o = o { showZeroBalances = x }
parseCommodity :: C.OptSpec (Opts -> Opts)
parseCommodity = C.OptSpec ["commodity"] "c" (C.OneArg f)
where
f a1 =
case Parsec.parse Pc.lvl1Cmdty "" (X.pack a1) of
Left _ -> Left . C.ErrorMsg $ "invalid commodity"
Right g -> return $ \os -> os { target = ManualTarget . L.To $ g }
parseAuto :: C.OptSpec (Opts -> Opts)
parseAuto = C.OptSpec ["auto-commodity"] "" (C.NoArg f)
where
f os = os { target = AutoTarget }
parseDate :: C.OptSpec (Opts -> Opts)
parseDate = C.OptSpec ["date"] "d" (C.OneArg f)
where
f a1 =
case Parsec.parse Pc.dateTime "" (X.pack a1) of
Left _ -> Left . C.ErrorMsg $ "invalid date"
Right g -> return $ \os -> os { dateTime = g }
parseSort :: C.OptSpec (Opts -> Opts)
parseSort = C.OptSpec ["sort"] "s" (C.ChoiceArg ls)
where
ls = [ ("qty", (\os -> os { sortBy = SortByQty }))
, ("name", (\os -> os { sortBy = SortByName })) ]
parseOrder :: C.OptSpec (Opts -> Opts)
parseOrder = fmap f P.order
where
f x o = o { sortOrder = x }
parsePct :: C.OptSpec (Opts -> Opts)
parsePct = C.OptSpec ["percent"] "%" (C.NoArg f)
where
f o = o { percentRpt = Just (RoundTo . maybe e id . L.nonNegative $ 0) }
e = error $ "Penny.Cabin.Balance.Convert.Parser.parsePct: "
++ "error: zero is not non-negative"
parseRound :: C.OptSpec (Opts -> Opts)
parseRound = C.OptSpec ["round"] "r" (C.OneArg f)
where
f a = do
i <- C.reader a
case L.nonNegative i of
Nothing -> Left . C.ErrorMsg $ "argument is negative"
Just g -> return $ \o -> o { percentRpt = Just (RoundTo g) }