module Text.PercentFormat.Spec where
import Data.Char (isDigit)
data Spec = Spec
{ ty :: SpecType
, width :: Int
, leftAlign :: Bool
, padWith :: Char
, base :: Int
, precision :: Maybe Int
, minPrecision :: Int
, positivePrefix :: String
, capitalizeDigits :: Bool
}
deriving (Eq, Show)
data SpecType = NumberSpec
| ReprSpec
| StringSpec
| CharSpec
| Percent
deriving (Eq, Show)
spec :: Spec
spec = Spec
{ ty = error "undefined Spec ty"
, width = 0
, leftAlign = False
, padWith = ' '
, base = 10
, precision = Nothing
, minPrecision = 0
, positivePrefix = ""
, capitalizeDigits = False
}
parseSpec :: String -> (Spec,String)
parseSpec ('%':cs) = (spec {ty = Percent }, cs)
parseSpec ('r':cs) = (spec {ty = ReprSpec }, cs)
parseSpec ('s':cs) = (spec {ty = StringSpec}, cs)
parseSpec ('c':cs) = (spec {ty = CharSpec }, cs)
parseSpec ('i':cs) = (spec {ty = NumberSpec, precision = Just 0}, cs)
parseSpec ('d':cs) = (spec {ty = NumberSpec}, cs)
parseSpec ('x':cs) = (spec {ty = NumberSpec, base = 16}, cs)
parseSpec ('X':cs) = (spec {ty = NumberSpec, base = 16, capitalizeDigits = True}, cs)
parseSpec ('o':cs) = (spec {ty = NumberSpec, base = 8}, cs)
parseSpec ('b':cs) = (spec {ty = NumberSpec, base = 2}, cs)
parseSpec ('f':cs) = (spec {ty = NumberSpec, minPrecision = 1}, cs)
parseSpec ('q':cs) = error $ "`q' format will be implemented in a future version"
parseSpec ('e':cs) = error $ "`e' format will be implemented in a future version"
parseSpec ('E':cs) = error $ "`E' format will be implemented in a future version"
parseSpec ('0':cs) = (s {padWith = '0'}, cs') where (s,cs') = parseSpec cs
parseSpec ( n :cs) | isDigit n = let (w,cs') = span isDigit (n:cs)
(s,cs'') = parseSpec cs'
in (s {width = read w}, cs'')
parseSpec ('.':'*':cs) = let (s,cs') = parseSpec cs
in (s {precision = Nothing}, cs')
parseSpec ('.':cs) = let (w,cs') = span isDigit cs
(s,cs'') = parseSpec cs'
in (s {precision = Just (read ('0':w))}, cs'')
parseSpec ('-':cs) = (s {leftAlign = True}, cs') where (s,cs') = parseSpec cs
parseSpec (' ':cs) = (s {positivePrefix = " "}, cs') where (s,cs') = parseSpec cs
parseSpec ('+':cs) = (s {positivePrefix = "+"}, cs') where (s,cs') = parseSpec cs
parseSpec (c:_) = error $ "unknown format string `" ++ (c:"'")