{-# LANGUAGE FlexibleContexts, OverloadedStrings, TypeFamilies, PackageImports #-}
module Hledger.Data.StringFormat (
parseStringFormat
, defaultStringFormatStyle
, StringFormat(..)
, StringFormatComponent(..)
, ReportItemField(..)
, tests_StringFormat
) where
import Prelude ()
import "base-compat-batteries" Prelude.Compat
import Numeric
import Data.Char (isPrint)
import Data.Maybe
import Text.Megaparsec
import Text.Megaparsec.Char
import Hledger.Utils.Parse
import Hledger.Utils.String (formatString)
import Hledger.Utils.Test
data StringFormat =
OneLine [StringFormatComponent]
| TopAligned [StringFormatComponent]
| BottomAligned [StringFormatComponent]
deriving (Int -> StringFormat -> ShowS
[StringFormat] -> ShowS
StringFormat -> String
(Int -> StringFormat -> ShowS)
-> (StringFormat -> String)
-> ([StringFormat] -> ShowS)
-> Show StringFormat
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [StringFormat] -> ShowS
$cshowList :: [StringFormat] -> ShowS
show :: StringFormat -> String
$cshow :: StringFormat -> String
showsPrec :: Int -> StringFormat -> ShowS
$cshowsPrec :: Int -> StringFormat -> ShowS
Show, StringFormat -> StringFormat -> Bool
(StringFormat -> StringFormat -> Bool)
-> (StringFormat -> StringFormat -> Bool) -> Eq StringFormat
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: StringFormat -> StringFormat -> Bool
$c/= :: StringFormat -> StringFormat -> Bool
== :: StringFormat -> StringFormat -> Bool
$c== :: StringFormat -> StringFormat -> Bool
Eq)
data StringFormatComponent =
FormatLiteral String
| FormatField Bool
(Maybe Int)
(Maybe Int)
ReportItemField
deriving (Int -> StringFormatComponent -> ShowS
[StringFormatComponent] -> ShowS
StringFormatComponent -> String
(Int -> StringFormatComponent -> ShowS)
-> (StringFormatComponent -> String)
-> ([StringFormatComponent] -> ShowS)
-> Show StringFormatComponent
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [StringFormatComponent] -> ShowS
$cshowList :: [StringFormatComponent] -> ShowS
show :: StringFormatComponent -> String
$cshow :: StringFormatComponent -> String
showsPrec :: Int -> StringFormatComponent -> ShowS
$cshowsPrec :: Int -> StringFormatComponent -> ShowS
Show, StringFormatComponent -> StringFormatComponent -> Bool
(StringFormatComponent -> StringFormatComponent -> Bool)
-> (StringFormatComponent -> StringFormatComponent -> Bool)
-> Eq StringFormatComponent
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: StringFormatComponent -> StringFormatComponent -> Bool
$c/= :: StringFormatComponent -> StringFormatComponent -> Bool
== :: StringFormatComponent -> StringFormatComponent -> Bool
$c== :: StringFormatComponent -> StringFormatComponent -> Bool
Eq)
data ReportItemField =
AccountField
| DefaultDateField
| DescriptionField
| TotalField
| DepthSpacerField
| FieldNo Int
deriving (Int -> ReportItemField -> ShowS
[ReportItemField] -> ShowS
ReportItemField -> String
(Int -> ReportItemField -> ShowS)
-> (ReportItemField -> String)
-> ([ReportItemField] -> ShowS)
-> Show ReportItemField
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ReportItemField] -> ShowS
$cshowList :: [ReportItemField] -> ShowS
show :: ReportItemField -> String
$cshow :: ReportItemField -> String
showsPrec :: Int -> ReportItemField -> ShowS
$cshowsPrec :: Int -> ReportItemField -> ShowS
Show, ReportItemField -> ReportItemField -> Bool
(ReportItemField -> ReportItemField -> Bool)
-> (ReportItemField -> ReportItemField -> Bool)
-> Eq ReportItemField
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ReportItemField -> ReportItemField -> Bool
$c/= :: ReportItemField -> ReportItemField -> Bool
== :: ReportItemField -> ReportItemField -> Bool
$c== :: ReportItemField -> ReportItemField -> Bool
Eq)
parseStringFormat :: String -> Either String StringFormat
parseStringFormat :: String -> Either String StringFormat
parseStringFormat input :: String
input = case (Parsec CustomErr String StringFormat
-> String
-> String
-> Either (ParseErrorBundle String CustomErr) StringFormat
forall e s a.
Parsec e s a -> String -> s -> Either (ParseErrorBundle s e) a
runParser (Parsec CustomErr String StringFormat
stringformatp Parsec CustomErr String StringFormat
-> ParsecT CustomErr String Identity ()
-> Parsec CustomErr String StringFormat
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ParsecT CustomErr String Identity ()
forall e s (m :: * -> *). MonadParsec e s m => m ()
eof) "(unknown)") String
input of
Left y :: ParseErrorBundle String CustomErr
y -> String -> Either String StringFormat
forall a b. a -> Either a b
Left (String -> Either String StringFormat)
-> String -> Either String StringFormat
forall a b. (a -> b) -> a -> b
$ ParseErrorBundle String CustomErr -> String
forall a. Show a => a -> String
show ParseErrorBundle String CustomErr
y
Right x :: StringFormat
x -> StringFormat -> Either String StringFormat
forall a b. b -> Either a b
Right StringFormat
x
defaultStringFormatStyle :: [StringFormatComponent] -> StringFormat
defaultStringFormatStyle = [StringFormatComponent] -> StringFormat
BottomAligned
stringformatp :: SimpleStringParser StringFormat
stringformatp :: Parsec CustomErr String StringFormat
stringformatp = do
Maybe Char
alignspec <- ParsecT CustomErr String Identity Char
-> ParsecT CustomErr String Identity (Maybe Char)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (ParsecT CustomErr String Identity Char
-> ParsecT CustomErr String Identity Char
forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try (ParsecT CustomErr String Identity Char
-> ParsecT CustomErr String Identity Char)
-> ParsecT CustomErr String Identity Char
-> ParsecT CustomErr String Identity Char
forall a b. (a -> b) -> a -> b
$ Token String -> ParsecT CustomErr String Identity (Token String)
forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Token String
'%' ParsecT CustomErr String Identity Char
-> ParsecT CustomErr String Identity Char
-> ParsecT CustomErr String Identity Char
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> [Token String] -> ParsecT CustomErr String Identity (Token String)
forall (f :: * -> *) e s (m :: * -> *).
(Foldable f, MonadParsec e s m) =>
f (Token s) -> m (Token s)
oneOf ("^_,"::String))
let constructor :: [StringFormatComponent] -> StringFormat
constructor =
case Maybe Char
alignspec of
Just '^' -> [StringFormatComponent] -> StringFormat
TopAligned
Just '_' -> [StringFormatComponent] -> StringFormat
BottomAligned
Just ',' -> [StringFormatComponent] -> StringFormat
OneLine
_ -> [StringFormatComponent] -> StringFormat
defaultStringFormatStyle
[StringFormatComponent] -> StringFormat
constructor ([StringFormatComponent] -> StringFormat)
-> ParsecT CustomErr String Identity [StringFormatComponent]
-> Parsec CustomErr String StringFormat
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT CustomErr String Identity StringFormatComponent
-> ParsecT CustomErr String Identity [StringFormatComponent]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many ParsecT CustomErr String Identity StringFormatComponent
componentp
componentp :: SimpleStringParser StringFormatComponent
componentp :: ParsecT CustomErr String Identity StringFormatComponent
componentp = ParsecT CustomErr String Identity StringFormatComponent
formatliteralp ParsecT CustomErr String Identity StringFormatComponent
-> ParsecT CustomErr String Identity StringFormatComponent
-> ParsecT CustomErr String Identity StringFormatComponent
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> ParsecT CustomErr String Identity StringFormatComponent
formatfieldp
formatliteralp :: SimpleStringParser StringFormatComponent
formatliteralp :: ParsecT CustomErr String Identity StringFormatComponent
formatliteralp = do
String
s <- ParsecT CustomErr String Identity Char
-> ParsecT CustomErr String Identity String
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
some ParsecT CustomErr String Identity Char
c
StringFormatComponent
-> ParsecT CustomErr String Identity StringFormatComponent
forall (m :: * -> *) a. Monad m => a -> m a
return (StringFormatComponent
-> ParsecT CustomErr String Identity StringFormatComponent)
-> StringFormatComponent
-> ParsecT CustomErr String Identity StringFormatComponent
forall a b. (a -> b) -> a -> b
$ String -> StringFormatComponent
FormatLiteral String
s
where
isPrintableButNotPercentage :: Char -> Bool
isPrintableButNotPercentage x :: Char
x = Char -> Bool
isPrint Char
x Bool -> Bool -> Bool
&& Char
x Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= '%'
c :: ParsecT CustomErr String Identity Char
c = ((Token String -> Bool)
-> ParsecT CustomErr String Identity (Token String)
forall e s (m :: * -> *).
MonadParsec e s m =>
(Token s -> Bool) -> m (Token s)
satisfy Char -> Bool
Token String -> Bool
isPrintableButNotPercentage ParsecT CustomErr String Identity Char
-> String -> ParsecT CustomErr String Identity Char
forall e s (m :: * -> *) a.
MonadParsec e s m =>
m a -> String -> m a
<?> "printable character")
ParsecT CustomErr String Identity Char
-> ParsecT CustomErr String Identity Char
-> ParsecT CustomErr String Identity Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> ParsecT CustomErr String Identity Char
-> ParsecT CustomErr String Identity Char
forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try (Tokens String -> ParsecT CustomErr String Identity (Tokens String)
forall e s (m :: * -> *).
MonadParsec e s m =>
Tokens s -> m (Tokens s)
string "%%" ParsecT CustomErr String Identity (Tokens String)
-> ParsecT CustomErr String Identity Char
-> ParsecT CustomErr String Identity Char
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Char -> ParsecT CustomErr String Identity Char
forall (m :: * -> *) a. Monad m => a -> m a
return '%')
formatfieldp :: SimpleStringParser StringFormatComponent
formatfieldp :: ParsecT CustomErr String Identity StringFormatComponent
formatfieldp = do
Token String -> ParsecT CustomErr String Identity (Token String)
forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Token String
'%'
Maybe Char
leftJustified <- ParsecT CustomErr String Identity Char
-> ParsecT CustomErr String Identity (Maybe Char)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Token String -> ParsecT CustomErr String Identity (Token String)
forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Token String
'-')
Maybe String
minWidth <- ParsecT CustomErr String Identity String
-> ParsecT CustomErr String Identity (Maybe String)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (ParsecT CustomErr String Identity Char
-> ParsecT CustomErr String Identity String
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
some (ParsecT CustomErr String Identity Char
-> ParsecT CustomErr String Identity String)
-> ParsecT CustomErr String Identity Char
-> ParsecT CustomErr String Identity String
forall a b. (a -> b) -> a -> b
$ ParsecT CustomErr String Identity Char
forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m (Token s)
digitChar)
Maybe String
maxWidth <- ParsecT CustomErr String Identity String
-> ParsecT CustomErr String Identity (Maybe String)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (do Token String -> ParsecT CustomErr String Identity (Token String)
forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Token String
'.'; ParsecT CustomErr String Identity Char
-> ParsecT CustomErr String Identity String
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
some (ParsecT CustomErr String Identity Char
-> ParsecT CustomErr String Identity String)
-> ParsecT CustomErr String Identity Char
-> ParsecT CustomErr String Identity String
forall a b. (a -> b) -> a -> b
$ ParsecT CustomErr String Identity Char
forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m (Token s)
digitChar)
Token String -> ParsecT CustomErr String Identity (Token String)
forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Token String
'('
ReportItemField
f <- SimpleStringParser ReportItemField
fieldp
Token String -> ParsecT CustomErr String Identity (Token String)
forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Token String
')'
StringFormatComponent
-> ParsecT CustomErr String Identity StringFormatComponent
forall (m :: * -> *) a. Monad m => a -> m a
return (StringFormatComponent
-> ParsecT CustomErr String Identity StringFormatComponent)
-> StringFormatComponent
-> ParsecT CustomErr String Identity StringFormatComponent
forall a b. (a -> b) -> a -> b
$ Bool
-> Maybe Int
-> Maybe Int
-> ReportItemField
-> StringFormatComponent
FormatField (Maybe Char -> Bool
forall a. Maybe a -> Bool
isJust Maybe Char
leftJustified) (Maybe String -> Maybe Int
forall a. (Eq a, Num a) => Maybe String -> Maybe a
parseDec Maybe String
minWidth) (Maybe String -> Maybe Int
forall a. (Eq a, Num a) => Maybe String -> Maybe a
parseDec Maybe String
maxWidth) ReportItemField
f
where
parseDec :: Maybe String -> Maybe a
parseDec s :: Maybe String
s = case Maybe String
s of
Just text :: String
text -> a -> Maybe a
forall a. a -> Maybe a
Just a
m where ((m :: a
m,_):_) = ReadS a
forall a. (Eq a, Num a) => ReadS a
readDec String
text
_ -> Maybe a
forall a. Maybe a
Nothing
fieldp :: SimpleStringParser ReportItemField
fieldp :: SimpleStringParser ReportItemField
fieldp = do
SimpleStringParser ReportItemField
-> SimpleStringParser ReportItemField
forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try (Tokens String -> ParsecT CustomErr String Identity (Tokens String)
forall e s (m :: * -> *).
MonadParsec e s m =>
Tokens s -> m (Tokens s)
string "account" ParsecT CustomErr String Identity String
-> SimpleStringParser ReportItemField
-> SimpleStringParser ReportItemField
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ReportItemField -> SimpleStringParser ReportItemField
forall (m :: * -> *) a. Monad m => a -> m a
return ReportItemField
AccountField)
SimpleStringParser ReportItemField
-> SimpleStringParser ReportItemField
-> SimpleStringParser ReportItemField
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> SimpleStringParser ReportItemField
-> SimpleStringParser ReportItemField
forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try (Tokens String -> ParsecT CustomErr String Identity (Tokens String)
forall e s (m :: * -> *).
MonadParsec e s m =>
Tokens s -> m (Tokens s)
string "depth_spacer" ParsecT CustomErr String Identity String
-> SimpleStringParser ReportItemField
-> SimpleStringParser ReportItemField
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ReportItemField -> SimpleStringParser ReportItemField
forall (m :: * -> *) a. Monad m => a -> m a
return ReportItemField
DepthSpacerField)
SimpleStringParser ReportItemField
-> SimpleStringParser ReportItemField
-> SimpleStringParser ReportItemField
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> SimpleStringParser ReportItemField
-> SimpleStringParser ReportItemField
forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try (Tokens String -> ParsecT CustomErr String Identity (Tokens String)
forall e s (m :: * -> *).
MonadParsec e s m =>
Tokens s -> m (Tokens s)
string "date" ParsecT CustomErr String Identity String
-> SimpleStringParser ReportItemField
-> SimpleStringParser ReportItemField
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ReportItemField -> SimpleStringParser ReportItemField
forall (m :: * -> *) a. Monad m => a -> m a
return ReportItemField
DescriptionField)
SimpleStringParser ReportItemField
-> SimpleStringParser ReportItemField
-> SimpleStringParser ReportItemField
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> SimpleStringParser ReportItemField
-> SimpleStringParser ReportItemField
forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try (Tokens String -> ParsecT CustomErr String Identity (Tokens String)
forall e s (m :: * -> *).
MonadParsec e s m =>
Tokens s -> m (Tokens s)
string "description" ParsecT CustomErr String Identity String
-> SimpleStringParser ReportItemField
-> SimpleStringParser ReportItemField
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ReportItemField -> SimpleStringParser ReportItemField
forall (m :: * -> *) a. Monad m => a -> m a
return ReportItemField
DescriptionField)
SimpleStringParser ReportItemField
-> SimpleStringParser ReportItemField
-> SimpleStringParser ReportItemField
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> SimpleStringParser ReportItemField
-> SimpleStringParser ReportItemField
forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try (Tokens String -> ParsecT CustomErr String Identity (Tokens String)
forall e s (m :: * -> *).
MonadParsec e s m =>
Tokens s -> m (Tokens s)
string "total" ParsecT CustomErr String Identity String
-> SimpleStringParser ReportItemField
-> SimpleStringParser ReportItemField
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ReportItemField -> SimpleStringParser ReportItemField
forall (m :: * -> *) a. Monad m => a -> m a
return ReportItemField
TotalField)
SimpleStringParser ReportItemField
-> SimpleStringParser ReportItemField
-> SimpleStringParser ReportItemField
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> SimpleStringParser ReportItemField
-> SimpleStringParser ReportItemField
forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try ((Int -> ReportItemField
FieldNo (Int -> ReportItemField)
-> (String -> Int) -> String -> ReportItemField
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Int
forall a. Read a => String -> a
read) (String -> ReportItemField)
-> ParsecT CustomErr String Identity String
-> SimpleStringParser ReportItemField
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT CustomErr String Identity Char
-> ParsecT CustomErr String Identity String
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
some ParsecT CustomErr String Identity Char
forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m (Token s)
digitChar)
formatStringTester :: StringFormatComponent -> String -> String -> Assertion
formatStringTester fs :: StringFormatComponent
fs value :: String
value expected :: String
expected = String
actual String -> String -> Assertion
forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= String
expected
where
actual :: String
actual = case StringFormatComponent
fs of
FormatLiteral l :: String
l -> Bool -> Maybe Int -> Maybe Int -> ShowS
formatString Bool
False Maybe Int
forall a. Maybe a
Nothing Maybe Int
forall a. Maybe a
Nothing String
l
FormatField leftJustify :: Bool
leftJustify min :: Maybe Int
min max :: Maybe Int
max _ -> Bool -> Maybe Int -> Maybe Int -> ShowS
formatString Bool
leftJustify Maybe Int
min Maybe Int
max String
value
tests_StringFormat :: TestTree
tests_StringFormat = String -> [TestTree] -> TestTree
tests "StringFormat" [
String -> Assertion -> TestTree
test "formatStringHelper" (Assertion -> TestTree) -> Assertion -> TestTree
forall a b. (a -> b) -> a -> b
$ do
StringFormatComponent -> String -> String -> Assertion
formatStringTester (String -> StringFormatComponent
FormatLiteral " ") "" " "
StringFormatComponent -> String -> String -> Assertion
formatStringTester (Bool
-> Maybe Int
-> Maybe Int
-> ReportItemField
-> StringFormatComponent
FormatField Bool
False Maybe Int
forall a. Maybe a
Nothing Maybe Int
forall a. Maybe a
Nothing ReportItemField
DescriptionField) "description" "description"
StringFormatComponent -> String -> String -> Assertion
formatStringTester (Bool
-> Maybe Int
-> Maybe Int
-> ReportItemField
-> StringFormatComponent
FormatField Bool
False (Int -> Maybe Int
forall a. a -> Maybe a
Just 20) Maybe Int
forall a. Maybe a
Nothing ReportItemField
DescriptionField) "description" " description"
StringFormatComponent -> String -> String -> Assertion
formatStringTester (Bool
-> Maybe Int
-> Maybe Int
-> ReportItemField
-> StringFormatComponent
FormatField Bool
False Maybe Int
forall a. Maybe a
Nothing (Int -> Maybe Int
forall a. a -> Maybe a
Just 20) ReportItemField
DescriptionField) "description" "description"
StringFormatComponent -> String -> String -> Assertion
formatStringTester (Bool
-> Maybe Int
-> Maybe Int
-> ReportItemField
-> StringFormatComponent
FormatField Bool
True Maybe Int
forall a. Maybe a
Nothing (Int -> Maybe Int
forall a. a -> Maybe a
Just 20) ReportItemField
DescriptionField) "description" "description"
StringFormatComponent -> String -> String -> Assertion
formatStringTester (Bool
-> Maybe Int
-> Maybe Int
-> ReportItemField
-> StringFormatComponent
FormatField Bool
True (Int -> Maybe Int
forall a. a -> Maybe a
Just 20) Maybe Int
forall a. Maybe a
Nothing ReportItemField
DescriptionField) "description" "description "
StringFormatComponent -> String -> String -> Assertion
formatStringTester (Bool
-> Maybe Int
-> Maybe Int
-> ReportItemField
-> StringFormatComponent
FormatField Bool
True (Int -> Maybe Int
forall a. a -> Maybe a
Just 20) (Int -> Maybe Int
forall a. a -> Maybe a
Just 20) ReportItemField
DescriptionField) "description" "description "
StringFormatComponent -> String -> String -> Assertion
formatStringTester (Bool
-> Maybe Int
-> Maybe Int
-> ReportItemField
-> StringFormatComponent
FormatField Bool
True Maybe Int
forall a. Maybe a
Nothing (Int -> Maybe Int
forall a. a -> Maybe a
Just 3) ReportItemField
DescriptionField) "description" "des"
,let s :: String
s gives :: String -> StringFormat -> TestTree
`gives` expected :: StringFormat
expected = String -> Assertion -> TestTree
test String
s (Assertion -> TestTree) -> Assertion -> TestTree
forall a b. (a -> b) -> a -> b
$ String -> Either String StringFormat
parseStringFormat String
s Either String StringFormat
-> Either String StringFormat -> Assertion
forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= StringFormat -> Either String StringFormat
forall a b. b -> Either a b
Right StringFormat
expected
in String -> [TestTree] -> TestTree
tests "parseStringFormat" [
"" String -> StringFormat -> TestTree
`gives` ([StringFormatComponent] -> StringFormat
defaultStringFormatStyle [])
, "D" String -> StringFormat -> TestTree
`gives` ([StringFormatComponent] -> StringFormat
defaultStringFormatStyle [String -> StringFormatComponent
FormatLiteral "D"])
, "%(date)" String -> StringFormat -> TestTree
`gives` ([StringFormatComponent] -> StringFormat
defaultStringFormatStyle [Bool
-> Maybe Int
-> Maybe Int
-> ReportItemField
-> StringFormatComponent
FormatField Bool
False Maybe Int
forall a. Maybe a
Nothing Maybe Int
forall a. Maybe a
Nothing ReportItemField
DescriptionField])
, "%(total)" String -> StringFormat -> TestTree
`gives` ([StringFormatComponent] -> StringFormat
defaultStringFormatStyle [Bool
-> Maybe Int
-> Maybe Int
-> ReportItemField
-> StringFormatComponent
FormatField Bool
False Maybe Int
forall a. Maybe a
Nothing Maybe Int
forall a. Maybe a
Nothing ReportItemField
TotalField])
, "Hello %(date)!" String -> StringFormat -> TestTree
`gives` ([StringFormatComponent] -> StringFormat
defaultStringFormatStyle [String -> StringFormatComponent
FormatLiteral "Hello ", Bool
-> Maybe Int
-> Maybe Int
-> ReportItemField
-> StringFormatComponent
FormatField Bool
False Maybe Int
forall a. Maybe a
Nothing Maybe Int
forall a. Maybe a
Nothing ReportItemField
DescriptionField, String -> StringFormatComponent
FormatLiteral "!"])
, "%-(date)" String -> StringFormat -> TestTree
`gives` ([StringFormatComponent] -> StringFormat
defaultStringFormatStyle [Bool
-> Maybe Int
-> Maybe Int
-> ReportItemField
-> StringFormatComponent
FormatField Bool
True Maybe Int
forall a. Maybe a
Nothing Maybe Int
forall a. Maybe a
Nothing ReportItemField
DescriptionField])
, "%20(date)" String -> StringFormat -> TestTree
`gives` ([StringFormatComponent] -> StringFormat
defaultStringFormatStyle [Bool
-> Maybe Int
-> Maybe Int
-> ReportItemField
-> StringFormatComponent
FormatField Bool
False (Int -> Maybe Int
forall a. a -> Maybe a
Just 20) Maybe Int
forall a. Maybe a
Nothing ReportItemField
DescriptionField])
, "%.10(date)" String -> StringFormat -> TestTree
`gives` ([StringFormatComponent] -> StringFormat
defaultStringFormatStyle [Bool
-> Maybe Int
-> Maybe Int
-> ReportItemField
-> StringFormatComponent
FormatField Bool
False Maybe Int
forall a. Maybe a
Nothing (Int -> Maybe Int
forall a. a -> Maybe a
Just 10) ReportItemField
DescriptionField])
, "%20.10(date)" String -> StringFormat -> TestTree
`gives` ([StringFormatComponent] -> StringFormat
defaultStringFormatStyle [Bool
-> Maybe Int
-> Maybe Int
-> ReportItemField
-> StringFormatComponent
FormatField Bool
False (Int -> Maybe Int
forall a. a -> Maybe a
Just 20) (Int -> Maybe Int
forall a. a -> Maybe a
Just 10) ReportItemField
DescriptionField])
, "%20(account) %.10(total)" String -> StringFormat -> TestTree
`gives` ([StringFormatComponent] -> StringFormat
defaultStringFormatStyle [Bool
-> Maybe Int
-> Maybe Int
-> ReportItemField
-> StringFormatComponent
FormatField Bool
False (Int -> Maybe Int
forall a. a -> Maybe a
Just 20) Maybe Int
forall a. Maybe a
Nothing ReportItemField
AccountField
,String -> StringFormatComponent
FormatLiteral " "
,Bool
-> Maybe Int
-> Maybe Int
-> ReportItemField
-> StringFormatComponent
FormatField Bool
False Maybe Int
forall a. Maybe a
Nothing (Int -> Maybe Int
forall a. a -> Maybe a
Just 10) ReportItemField
TotalField
])
, String -> Assertion -> TestTree
test "newline not parsed" (Assertion -> TestTree) -> Assertion -> TestTree
forall a b. (a -> b) -> a -> b
$ Either String StringFormat -> Assertion
forall b a. (HasCallStack, Eq b, Show b) => Either a b -> Assertion
assertLeft (Either String StringFormat -> Assertion)
-> Either String StringFormat -> Assertion
forall a b. (a -> b) -> a -> b
$ String -> Either String StringFormat
parseStringFormat "\n"
]
]