2012-03-10 23:20:15 +04:00
|
|
|
module Hledger.Data.FormatStrings (
|
2011-06-21 01:33:26 +04:00
|
|
|
parseFormatString
|
2011-06-28 02:59:07 +04:00
|
|
|
, formatStrings
|
2011-06-21 01:33:26 +04:00
|
|
|
, formatValue
|
|
|
|
, FormatString(..)
|
2012-03-24 05:58:34 +04:00
|
|
|
, HledgerFormatField(..)
|
2011-06-21 01:33:26 +04:00
|
|
|
, tests
|
|
|
|
) where
|
|
|
|
|
|
|
|
import Numeric
|
2011-06-28 02:59:07 +04:00
|
|
|
import Data.Char (isPrint)
|
2011-06-21 01:33:26 +04:00
|
|
|
import Data.Maybe
|
|
|
|
import Test.HUnit
|
|
|
|
import Text.ParserCombinators.Parsec
|
|
|
|
import Text.Printf
|
|
|
|
|
2012-03-24 05:58:34 +04:00
|
|
|
import Hledger.Data.Types
|
2011-06-21 01:33:26 +04:00
|
|
|
|
|
|
|
|
|
|
|
formatValue :: Bool -> Maybe Int -> Maybe Int -> String -> String
|
|
|
|
formatValue leftJustified min max value = printf formatS value
|
|
|
|
where
|
|
|
|
l = if leftJustified then "-" else ""
|
|
|
|
min' = maybe "" show min
|
|
|
|
max' = maybe "" (\i -> "." ++ (show i)) max
|
|
|
|
formatS = "%" ++ l ++ min' ++ max' ++ "s"
|
|
|
|
|
|
|
|
parseFormatString :: String -> Either String [FormatString]
|
2011-06-28 02:59:07 +04:00
|
|
|
parseFormatString input = case (runParser formatStrings () "(unknown)") input of
|
2011-06-21 01:33:26 +04:00
|
|
|
Left y -> Left $ show y
|
|
|
|
Right x -> Right x
|
|
|
|
|
|
|
|
{-
|
|
|
|
Parsers
|
|
|
|
-}
|
|
|
|
|
2012-03-24 05:58:34 +04:00
|
|
|
field :: GenParser Char st HledgerFormatField
|
2011-06-21 01:33:26 +04:00
|
|
|
field = do
|
2012-03-24 05:58:34 +04:00
|
|
|
try (string "account" >> return AccountField)
|
|
|
|
<|> try (string "depth_spacer" >> return DepthSpacerField)
|
|
|
|
<|> try (string "date" >> return DescriptionField)
|
|
|
|
<|> try (string "description" >> return DescriptionField)
|
|
|
|
<|> try (string "total" >> return TotalField)
|
2011-06-28 02:59:07 +04:00
|
|
|
<|> try (many1 digit >>= (\s -> return $ FieldNo $ read s))
|
2011-06-21 01:33:26 +04:00
|
|
|
|
2011-06-28 02:59:07 +04:00
|
|
|
formatField :: GenParser Char st FormatString
|
2011-06-21 01:33:26 +04:00
|
|
|
formatField = do
|
|
|
|
char '%'
|
|
|
|
leftJustified <- optionMaybe (char '-')
|
|
|
|
minWidth <- optionMaybe (many1 $ digit)
|
2011-06-28 02:59:07 +04:00
|
|
|
maxWidth <- optionMaybe (do char '.'; many1 $ digit) -- TODO: Can this be (char '1') *> (many1 digit)
|
2011-06-21 01:33:26 +04:00
|
|
|
char '('
|
2011-06-28 02:59:07 +04:00
|
|
|
f <- field
|
2011-06-21 01:33:26 +04:00
|
|
|
char ')'
|
2011-06-28 02:59:07 +04:00
|
|
|
return $ FormatField (isJust leftJustified) (parseDec minWidth) (parseDec maxWidth) f
|
2011-06-21 01:33:26 +04:00
|
|
|
where
|
|
|
|
parseDec s = case s of
|
|
|
|
Just text -> Just m where ((m,_):_) = readDec text
|
|
|
|
_ -> Nothing
|
|
|
|
|
2011-06-28 02:59:07 +04:00
|
|
|
formatLiteral :: GenParser Char st FormatString
|
2011-06-21 01:33:26 +04:00
|
|
|
formatLiteral = do
|
|
|
|
s <- many1 c
|
|
|
|
return $ FormatLiteral s
|
|
|
|
where
|
2011-06-28 02:59:07 +04:00
|
|
|
isPrintableButNotPercentage x = isPrint x && (not $ x == '%')
|
|
|
|
c = (satisfy isPrintableButNotPercentage <?> "printable character")
|
2011-06-21 01:33:26 +04:00
|
|
|
<|> try (string "%%" >> return '%')
|
|
|
|
|
2014-01-10 20:29:25 +04:00
|
|
|
formatStr :: GenParser Char st FormatString
|
|
|
|
formatStr =
|
2011-06-21 01:33:26 +04:00
|
|
|
formatField
|
|
|
|
<|> formatLiteral
|
|
|
|
|
2011-06-28 02:59:07 +04:00
|
|
|
formatStrings :: GenParser Char st [FormatString]
|
2014-01-10 20:29:25 +04:00
|
|
|
formatStrings = many formatStr
|
2011-06-21 01:33:26 +04:00
|
|
|
|
|
|
|
testFormat :: FormatString -> String -> String -> Assertion
|
|
|
|
testFormat fs value expected = assertEqual name expected actual
|
|
|
|
where
|
|
|
|
(name, actual) = case fs of
|
|
|
|
FormatLiteral l -> ("literal", formatValue False Nothing Nothing l)
|
|
|
|
FormatField leftJustify min max _ -> ("field", formatValue leftJustify min max value)
|
|
|
|
|
|
|
|
testParser :: String -> [FormatString] -> Assertion
|
|
|
|
testParser s expected = case (parseFormatString s) of
|
|
|
|
Left error -> assertFailure $ show error
|
|
|
|
Right actual -> assertEqual ("Input: " ++ s) expected actual
|
|
|
|
|
|
|
|
tests = test [ formattingTests ++ parserTests ]
|
|
|
|
|
|
|
|
formattingTests = [
|
|
|
|
testFormat (FormatLiteral " ") "" " "
|
2012-03-24 05:58:34 +04:00
|
|
|
, testFormat (FormatField False Nothing Nothing DescriptionField) "description" "description"
|
|
|
|
, testFormat (FormatField False (Just 20) Nothing DescriptionField) "description" " description"
|
|
|
|
, testFormat (FormatField False Nothing (Just 20) DescriptionField) "description" "description"
|
|
|
|
, testFormat (FormatField True Nothing (Just 20) DescriptionField) "description" "description"
|
|
|
|
, testFormat (FormatField True (Just 20) Nothing DescriptionField) "description" "description "
|
|
|
|
, testFormat (FormatField True (Just 20) (Just 20) DescriptionField) "description" "description "
|
|
|
|
, testFormat (FormatField True Nothing (Just 3) DescriptionField) "description" "des"
|
2011-06-21 01:33:26 +04:00
|
|
|
]
|
|
|
|
|
|
|
|
parserTests = [
|
|
|
|
testParser "" []
|
|
|
|
, testParser "D" [FormatLiteral "D"]
|
2012-03-24 05:58:34 +04:00
|
|
|
, testParser "%(date)" [FormatField False Nothing Nothing DescriptionField]
|
|
|
|
, testParser "%(total)" [FormatField False Nothing Nothing TotalField]
|
|
|
|
, testParser "Hello %(date)!" [FormatLiteral "Hello ", FormatField False Nothing Nothing DescriptionField, FormatLiteral "!"]
|
|
|
|
, testParser "%-(date)" [FormatField True Nothing Nothing DescriptionField]
|
|
|
|
, testParser "%20(date)" [FormatField False (Just 20) Nothing DescriptionField]
|
|
|
|
, testParser "%.10(date)" [FormatField False Nothing (Just 10) DescriptionField]
|
|
|
|
, testParser "%20.10(date)" [FormatField False (Just 20) (Just 10) DescriptionField]
|
|
|
|
, testParser "%20(account) %.10(total)\n" [ FormatField False (Just 20) Nothing AccountField
|
2011-06-21 01:33:26 +04:00
|
|
|
, FormatLiteral " "
|
2012-03-24 05:58:34 +04:00
|
|
|
, FormatField False Nothing (Just 10) TotalField
|
2011-06-21 01:33:26 +04:00
|
|
|
, FormatLiteral "\n"
|
|
|
|
]
|
|
|
|
]
|