module Penny.Copper.Payees (
payee
, quotedChar
, quotedPayee
, unquotedFirstChar
, unquotedRestChars
, unquotedPayee
, smartRender
, quoteRender
) where
import Control.Applicative ((<$>), (<*>), (<|>))
import Data.Text (pack, Text, snoc, cons)
import qualified Data.Text as X
import Text.Parsec (char, satisfy, many, between, (<?>))
import Text.Parsec.Text ( Parser )
import Penny.Copper.Util (rangeLettersToSymbols, rangeLetters)
import qualified Penny.Lincoln.Bits as B
import Penny.Lincoln.TextNonEmpty as TNE
quotedChar :: Char -> Bool
quotedChar c = allowed && not banned where
allowed = rangeLettersToSymbols c || c == ' '
banned = c == '>'
payee :: Parser B.Payee
payee = quotedPayee <|> unquotedPayee
quotedPayee :: Parser B.Payee
quotedPayee = between (char '<') (char '>') p <?> "quoted payee" where
p = (\c cs -> B.Payee (TextNonEmpty c (pack cs)))
<$> satisfy quotedChar
<*> many (satisfy quotedChar)
unquotedFirstChar :: Char -> Bool
unquotedFirstChar = rangeLetters
unquotedRestChars :: Char -> Bool
unquotedRestChars = quotedChar
unquotedPayee :: Parser B.Payee
unquotedPayee = let
p c cs = B.Payee (TextNonEmpty c (pack cs))
in p
<$> satisfy unquotedFirstChar
<*> many (satisfy unquotedRestChars)
<?> "unquoted payee"
smartRender :: B.Payee -> Maybe Text
smartRender (B.Payee p) = let
TextNonEmpty f r = p
noQuoteNeeded = unquotedFirstChar f
&& X.all unquotedRestChars r
renderable = TNE.all quotedChar p
quoted = '<' `cons` TNE.toText p `snoc` '>'
makeText
| noQuoteNeeded = Just $ TNE.toText p
| renderable = Just quoted
| otherwise = Nothing
in makeText
quoteRender :: B.Payee -> Maybe Text
quoteRender (B.Payee p) = let
renderable = TNE.all quotedChar p
quoted = '<' `cons` TNE.toText p `snoc` '>'
in if renderable
then Just quoted
else Nothing