text-format-heavy 0.1.4.0 → 0.1.5.0
raw patch · 10 files changed
+122/−14 lines, 10 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
+ Data.Text.Format.Heavy.Build: convertText :: Maybe Conversion -> Builder -> Builder
+ Data.Text.Format.Heavy.Formats: LowerCase :: Conversion
+ Data.Text.Format.Heavy.Formats: TitleCase :: Conversion
+ Data.Text.Format.Heavy.Formats: UpperCase :: Conversion
+ Data.Text.Format.Heavy.Formats: [gfConvert] :: GenericFormat -> Maybe Conversion
+ Data.Text.Format.Heavy.Formats: data Conversion
+ Data.Text.Format.Heavy.Formats: instance GHC.Classes.Eq Data.Text.Format.Heavy.Formats.Conversion
+ Data.Text.Format.Heavy.Formats: instance GHC.Show.Show Data.Text.Format.Heavy.Formats.Conversion
+ Data.Text.Format.Heavy.Instances: instance (Data.Text.Format.Heavy.Types.Formatable a, Data.Text.Format.Heavy.Types.Formatable b, Data.Text.Format.Heavy.Types.Formatable c, Data.Text.Format.Heavy.Types.Formatable d, Data.Text.Format.Heavy.Types.Formatable e, Data.Text.Format.Heavy.Types.Formatable f, Data.Text.Format.Heavy.Types.Formatable g, Data.Text.Format.Heavy.Types.Formatable h) => Data.Text.Format.Heavy.Types.VarContainer (a, b, c, d, e, f, g, h)
+ Data.Text.Format.Heavy.Instances: instance (Data.Text.Format.Heavy.Types.Formatable a, Data.Text.Format.Heavy.Types.Formatable b, Data.Text.Format.Heavy.Types.Formatable c, Data.Text.Format.Heavy.Types.Formatable d, Data.Text.Format.Heavy.Types.Formatable e, Data.Text.Format.Heavy.Types.Formatable f, Data.Text.Format.Heavy.Types.Formatable g, Data.Text.Format.Heavy.Types.Formatable h, Data.Text.Format.Heavy.Types.Formatable i) => Data.Text.Format.Heavy.Types.VarContainer (a, b, c, d, e, f, g, h, i)
+ Data.Text.Format.Heavy.Instances: instance (Data.Text.Format.Heavy.Types.Formatable a, Data.Text.Format.Heavy.Types.Formatable b, Data.Text.Format.Heavy.Types.Formatable c, Data.Text.Format.Heavy.Types.Formatable d, Data.Text.Format.Heavy.Types.Formatable e, Data.Text.Format.Heavy.Types.Formatable f, Data.Text.Format.Heavy.Types.Formatable g, Data.Text.Format.Heavy.Types.Formatable h, Data.Text.Format.Heavy.Types.Formatable i, Data.Text.Format.Heavy.Types.Formatable j) => Data.Text.Format.Heavy.Types.VarContainer (a, b, c, d, e, f, g, h, i, j)
+ Data.Text.Format.Heavy.Instances: type WithDefault c = ThenCheck c DefaultValue
+ Data.Text.Format.Heavy.Types: instance GHC.Classes.Eq Data.Text.Format.Heavy.Types.Format
+ Data.Text.Format.Heavy.Types: instance GHC.Classes.Eq Data.Text.Format.Heavy.Types.FormatItem
+ Data.Text.Format.Heavy.Types: instance GHC.Show.Show Data.Text.Format.Heavy.Types.Variable
- Data.Text.Format.Heavy.Formats: GenericFormat :: Char -> Maybe Align -> Sign -> Bool -> Maybe Int -> Maybe Int -> Maybe Radix -> GenericFormat
+ Data.Text.Format.Heavy.Formats: GenericFormat :: Char -> Maybe Align -> Sign -> Bool -> Maybe Int -> Maybe Int -> Maybe Radix -> Maybe Conversion -> GenericFormat
- Data.Text.Format.Heavy.Instances: optional :: VarContainer c => c -> ThenCheck c DefaultValue
+ Data.Text.Format.Heavy.Instances: optional :: VarContainer c => c -> WithDefault c
- Data.Text.Format.Heavy.Instances: withDefault :: VarContainer c => c -> Variable -> ThenCheck c DefaultValue
+ Data.Text.Format.Heavy.Instances: withDefault :: VarContainer c => c -> Variable -> WithDefault c
Files
- Data/Text/Format/Heavy.hs +1/−1
- Data/Text/Format/Heavy/Build.hs +16/−3
- Data/Text/Format/Heavy/Formats.hs +9/−0
- Data/Text/Format/Heavy/Instances.hs +52/−3
- Data/Text/Format/Heavy/Parse/Braces.hs +1/−1
- Data/Text/Format/Heavy/Parse/Shell.hs +1/−1
- Data/Text/Format/Heavy/Parse/VarFormat.hs +14/−1
- Data/Text/Format/Heavy/Types.hs +16/−2
- examples/test.hs +11/−1
- text-format-heavy.cabal +1/−1
Data/Text/Format/Heavy.hs view
@@ -38,5 +38,5 @@ import Data.Text.Format.Heavy.Types import Data.Text.Format.Heavy.Formats import Data.Text.Format.Heavy.Build (format)-import Data.Text.Format.Heavy.Instances (Single (..), Shown (..))+import Data.Text.Format.Heavy.Instances hiding (genericIntFormat, genericFloatFormat)
Data/Text/Format/Heavy/Build.hs view
@@ -4,7 +4,7 @@ (format, formatEither, makeBuilder, -- * Formatters building utilities- align, applySign, applySharp,+ align, applySign, applySharp, convertText, formatInt, formatStr, formatFloat, formatBool ) where @@ -77,6 +77,16 @@ applySharp True Decimal text = text applySharp True Hexadecimal text = B.fromLazyText "0x" <> text +-- | Apply text conversion.+convertText :: Maybe Conversion -> B.Builder -> B.Builder+convertText Nothing builder = builder+convertText (Just conv) builder = B.fromLazyText $ converter $ B.toLazyText builder+ where+ converter = case conv of+ UpperCase -> TL.toUpper+ LowerCase -> TL.toLower+ TitleCase -> TL.toTitle+ -- | Format integer number according to GenericFormat formatInt :: Integral a => GenericFormat -> a -> B.Builder formatInt fmt x = align fmt $ applySign (gfSign fmt) x $ applySharp (gfLeading0x fmt) radix $ inRadix@@ -89,11 +99,14 @@ -- | Format floating-point number according to GenericFormat formatFloat :: RealFloat a => GenericFormat -> a -> B.Builder formatFloat fmt x =- align fmt $ applySign (gfSign fmt) x $ formatRealFloat Fixed (gfPrecision fmt) $ abs x+ align fmt+ $ applySign (gfSign fmt) x+ $ formatRealFloat Fixed (gfPrecision fmt)+ $ abs x -- | Format Text according to GenericFormat. formatStr :: GenericFormat -> TL.Text -> B.Builder-formatStr fmt text = align fmt $ B.fromLazyText text+formatStr fmt text = convertText (gfConvert fmt) $ align fmt $ B.fromLazyText text -- | Format boolean value. formatBool :: BoolFormat -> Bool -> B.Builder
Data/Text/Format/Heavy/Formats.hs view
@@ -19,6 +19,13 @@ data Radix = Decimal | Hexadecimal deriving (Eq, Show) +-- | Supported text conversions+data Conversion =+ UpperCase+ | LowerCase+ | TitleCase+ deriving (Eq, Show)+ -- | Generic format description. This is usable for integers, floats and strings. data GenericFormat = GenericFormat { gfFillChar :: Char@@ -28,6 +35,7 @@ , gfWidth :: Maybe Int , gfPrecision :: Maybe Int , gfRadix :: Maybe Radix+ , gfConvert :: Maybe Conversion } deriving (Eq, Show) @@ -40,6 +48,7 @@ , gfWidth = Nothing , gfPrecision = Nothing , gfRadix = Nothing+ , gfConvert = Nothing } data BoolFormat = BoolFormat {
Data/Text/Format/Heavy/Instances.hs view
@@ -4,7 +4,7 @@ (-- * Utility data types Single (..), Several (..), Shown (..), -- * Combinators- DefaultValue (..), ThenCheck (..),+ DefaultValue (..), ThenCheck (..), WithDefault, withDefault, optional, -- * Generic formatters genericIntFormat, genericFloatFormat@@ -261,6 +261,48 @@ lookupVar "6" (_,_,_,_,_,_,g) = Just $ Variable g lookupVar _ _ = Nothing +instance (Formatable a, Formatable b, Formatable c, Formatable d, Formatable e, Formatable f, Formatable g,+ Formatable h)+ => VarContainer (a, b, c, d, e, f, g, h) where+ lookupVar "0" (a,_,_,_,_,_,_,_) = Just $ Variable a+ lookupVar "1" (_,b,_,_,_,_,_,_) = Just $ Variable b+ lookupVar "2" (_,_,c,_,_,_,_,_) = Just $ Variable c+ lookupVar "3" (_,_,_,d,_,_,_,_) = Just $ Variable d+ lookupVar "4" (_,_,_,_,e,_,_,_) = Just $ Variable e+ lookupVar "5" (_,_,_,_,_,f,_,_) = Just $ Variable f+ lookupVar "6" (_,_,_,_,_,_,g,_) = Just $ Variable g+ lookupVar "7" (_,_,_,_,_,_,_,h) = Just $ Variable h+ lookupVar _ _ = Nothing++instance (Formatable a, Formatable b, Formatable c, Formatable d, Formatable e, Formatable f, Formatable g,+ Formatable h, Formatable i)+ => VarContainer (a, b, c, d, e, f, g, h, i) where+ lookupVar "0" (a,_,_,_,_,_,_,_,_) = Just $ Variable a+ lookupVar "1" (_,b,_,_,_,_,_,_,_) = Just $ Variable b+ lookupVar "2" (_,_,c,_,_,_,_,_,_) = Just $ Variable c+ lookupVar "3" (_,_,_,d,_,_,_,_,_) = Just $ Variable d+ lookupVar "4" (_,_,_,_,e,_,_,_,_) = Just $ Variable e+ lookupVar "5" (_,_,_,_,_,f,_,_,_) = Just $ Variable f+ lookupVar "6" (_,_,_,_,_,_,g,_,_) = Just $ Variable g+ lookupVar "7" (_,_,_,_,_,_,_,h,_) = Just $ Variable h+ lookupVar "8" (_,_,_,_,_,_,_,_,i) = Just $ Variable i+ lookupVar _ _ = Nothing++instance (Formatable a, Formatable b, Formatable c, Formatable d, Formatable e, Formatable f, Formatable g,+ Formatable h, Formatable i, Formatable j)+ => VarContainer (a, b, c, d, e, f, g, h, i, j) where+ lookupVar "0" (a,_,_,_,_,_,_,_,_,_) = Just $ Variable a+ lookupVar "1" (_,b,_,_,_,_,_,_,_,_) = Just $ Variable b+ lookupVar "2" (_,_,c,_,_,_,_,_,_,_) = Just $ Variable c+ lookupVar "3" (_,_,_,d,_,_,_,_,_,_) = Just $ Variable d+ lookupVar "4" (_,_,_,_,e,_,_,_,_,_) = Just $ Variable e+ lookupVar "5" (_,_,_,_,_,f,_,_,_,_) = Just $ Variable f+ lookupVar "6" (_,_,_,_,_,_,g,_,_,_) = Just $ Variable g+ lookupVar "7" (_,_,_,_,_,_,_,h,_,_) = Just $ Variable h+ lookupVar "8" (_,_,_,_,_,_,_,_,i,_) = Just $ Variable i+ lookupVar "9" (_,_,_,_,_,_,_,_,_,j) = Just $ Variable j+ lookupVar _ _ = Nothing+ instance Formatable a => VarContainer (Several a) where lookupVar name (Several lst) = if not $ TL.all isDigit name@@ -286,15 +328,22 @@ -- and if variable is not found there it will check in @c2@. data ThenCheck c1 c2 = ThenCheck c1 c2 +-- | Convenience type synonym.+type WithDefault c = ThenCheck c DefaultValue+ instance (VarContainer c1, VarContainer c2) => VarContainer (ThenCheck c1 c2) where lookupVar name (ThenCheck c1 c2) = case lookupVar name c1 of Just result -> Just result Nothing -> lookupVar name c2 -withDefault :: VarContainer c => c -> Variable -> ThenCheck c DefaultValue+-- | Use variables from specified container, or use default value if+-- variable is not found in container.+withDefault :: VarContainer c => c -> Variable -> WithDefault c withDefault c value = c `ThenCheck` DefaultValue value -optional :: VarContainer c => c -> ThenCheck c DefaultValue+-- | Use variables from specified container, or use empty string+-- variable is not found in container.+optional :: VarContainer c => c -> WithDefault c optional c = c `withDefault` (Variable TL.empty)
Data/Text/Format/Heavy/Parse/Braces.hs view
@@ -43,7 +43,7 @@ return $ FVariable (TL.pack name) fmt where variable = do- name <- many alphaNum+ name <- many $ try alphaNum <|> try (char '-') <|> char '.' mbColon <- optionMaybe $ char ':' fmt <- case mbColon of Nothing -> return Nothing
Data/Text/Format/Heavy/Parse/Shell.hs view
@@ -64,7 +64,7 @@ return $ FVariable (TL.pack name) fmt where bracedVariable = between (char '{') (char '}') $ do- name <- many alphaNum+ name <- many $ try alphaNum <|> try (char '-') <|> char '.' mbColon <- optionMaybe $ char ':' fmt <- case mbColon of Nothing -> return Nothing
Data/Text/Format/Heavy/Parse/VarFormat.hs view
@@ -25,6 +25,7 @@ mbWidth <- optionMaybe (pWidth <?> "width specification") mbPrecision <- optionMaybe (pPrecision <?> "precision specification") mbRadix <- optionMaybe (pRadix <?> "radix specification")+ mbConvert <- optionMaybe (pConvert <?> "conversion specification") return $ GenericFormat { gfFillChar = fill , gfAlign = align@@ -33,6 +34,7 @@ , gfWidth = mbWidth , gfPrecision = mbPrecision , gfRadix = mbRadix+ , gfConvert = mbConvert } where pAlign :: Parsec TL.Text st Align@@ -98,12 +100,21 @@ 'h' -> return Hexadecimal 'd' -> return Decimal + pConvert :: Parsec TL.Text st Conversion+ pConvert = do+ char '~'+ conv <- oneOf "ult"+ case conv of+ 'u' -> return UpperCase+ 'l' -> return LowerCase+ 't' -> return TitleCase+ -- | Parse generic variable format. -- -- Syntax is: -- -- @--- [[fill]align][sign][#][width][.precision][radix]+-- [[fill]align][sign][#][width][.precision][radix][~conversion] -- @ -- -- where:@@ -115,6 +126,8 @@ -- * width - minimum length of the field -- * precision - number of decimal places after point, for floatting-point numbers -- * radix - @h@ or @x@ for hexadecimal, @d@ for decimal (default).+-- * conversion - text conversion symbol. Supported are: @u@ - convert to upper case,+-- @l@ - convert to lower case, @t@ - convert to title case (capitalize all words). -- parseGenericFormat :: TL.Text -> Either ParseError GenericFormat parseGenericFormat text = runParser pGenericFormat () "<variable format specification>" text
Data/Text/Format/Heavy/Types.hs view
@@ -21,12 +21,20 @@ vName :: VarName -- ^ Variable name , vFormat :: VarFormat -- ^ Variable format }- deriving (Show)+ deriving (Eq) +instance Show FormatItem where+ show (FString text) = TL.unpack text+ show (FVariable name Nothing) = TL.unpack $ "{" <> name <> "}"+ show (FVariable name (Just fmt)) = TL.unpack $ "{" <> name <> ":" <> fmt <> "}"+ -- | String format data Format = Format [FormatItem]- deriving (Show)+ deriving (Eq) +instance Show Format where+ show (Format lst) = concat $ map show lst+ instance Monoid Format where mempty = Format [] mappend (Format xs) (Format ys) = Format (xs ++ ys)@@ -52,6 +60,12 @@ -- This type may be also used to construct heterogeneous lists: -- @[Variable 1, Variable "x"] :: [Variable]@. data Variable = forall a. Formatable a => Variable a++instance Show Variable where+ show (Variable v) = either error toString $ formatVar Nothing v+ where+ toString :: B.Builder -> String+ toString b = TL.unpack $ B.toLazyText b instance Formatable Variable where formatVar fmt (Variable x) = formatVar fmt x
examples/test.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} import Data.Time+import qualified Data.Text.Lazy as TL import qualified Data.Text.Lazy.IO as TLIO import Data.Text.Format.Heavy import Data.Text.Format.Heavy.Time@@ -13,7 +14,16 @@ xs = (18 :: Int, "hello" :: String, 2.718281828 :: Double, Shown (Just (7 :: Int)), Just (8 :: Int), rt, True) TLIO.putStrLn $ format template xs time <- getZonedTime- TLIO.putStrLn $ format "Hello, {}! It is {:%H:%M:%S} now." $ ("Ilya" :: String, time)+ let vars :: [(TL.Text, Variable)]+ vars = [("name", Variable ("Ilya" :: String)),+ ("time", Variable time),+ ("header.content-type", Variable ("text/json" :: String)),+ ("upper", Variable ("this will be uppercase" :: String)),+ ("lower", Variable ("This will be ALL lower case" :: String)),+ ("title", Variable ("this is the title" :: String)),+ ("noun", Variable ("string" :: String))]+ TLIO.putStrLn $+ format "Hello, {name}! It is {time:%H:%M:%S} now. Test {noun}ification. Content: {header.content-type} x. Upper: <{upper:~u}>, lower <{lower:~l}>, title: <{title:~t}>." vars let mbX = Nothing :: Maybe Float mbY = Just 7.37491 :: Maybe Float mbZ = Nothing :: Maybe Float
text-format-heavy.cabal view
@@ -1,5 +1,5 @@ name: text-format-heavy-version: 0.1.4.0+version: 0.1.5.0 synopsis: Full-weight string formatting library, analog of Python's string.format description: This package contains full-featured string formatting function, similar to Python's string.format. Features include: