module Penny.Copper.Amount (
amount
, render
) where
import Control.Applicative ((<$>), (<*>), (<|>))
import qualified Data.Text as X
import Text.Parsec ( char, many, (<?>) )
import Text.Parsec.Text ( Parser )
import qualified Penny.Copper.Commodity as C
import qualified Penny.Copper.Qty as Q
import qualified Penny.Lincoln as L
spaces :: Parser L.SpaceBetween
spaces = f <$> many (char ' ') where
f l = if null l then L.NoSpaceBetween else L.SpaceBetween
cmdtyQty :: Parser L.Commodity
-> Q.RadGroup
-> Parser (L.Amount, L.Format)
cmdtyQty p rg = let
f c s q = (a, fmt) where
a = L.Amount q c
fmt = L.Format L.CommodityOnLeft s
e = "amount, commodity on left"
in f <$> p <*> spaces <*> Q.qty rg <?> e
lvl1CmdtyQty :: Q.RadGroup -> Parser (L.Amount, L.Format)
lvl1CmdtyQty = cmdtyQty C.quotedLvl1Cmdty
lvl3CmdtyQty :: Q.RadGroup -> Parser (L.Amount, L.Format)
lvl3CmdtyQty = cmdtyQty C.lvl3Cmdty
cmdtyOnRight :: Q.RadGroup -> Parser (L.Amount, L.Format)
cmdtyOnRight rg = let
f q s c = (a, fmt) where
a = L.Amount q c
fmt = L.Format L.CommodityOnRight s
e = "amount, commodity on right"
in f
<$> Q.qty rg
<*> spaces
<*> (C.quotedLvl1Cmdty <|> C.lvl2Cmdty)
<?> e
amount :: Q.RadGroup -> Parser (L.Amount, L.Format)
amount rg = lvl1CmdtyQty rg
<|> lvl3CmdtyQty rg
<|> cmdtyOnRight rg
<?> "amount"
render ::
(Q.GroupingSpec, Q.GroupingSpec)
-> Q.RadGroup
-> L.Format
-> L.Amount
-> Maybe X.Text
render gs rg f a = let
(q, c) = (L.qty a, L.commodity a)
qty = Q.quote $ Q.renderUnquoted rg gs q
ws = case L.between f of
L.SpaceBetween -> X.singleton ' '
L.NoSpaceBetween -> X.empty
mayLvl3 = C.renderLvl3 c
mayLvl2 = C.renderLvl2 c
in do
quotedLvl1 <- C.renderQuotedLvl1 c
let (l, r) = case L.side f of
L.CommodityOnLeft -> case mayLvl3 of
Nothing -> (quotedLvl1, qty)
Just l3 -> (l3, qty)
L.CommodityOnRight -> case mayLvl2 of
Nothing -> (qty, quotedLvl1)
Just l2 -> (qty, l2)
return $ X.concat [l, ws, r]