packages feed

ginger 0.2.1.0 → 0.2.2.0

raw patch · 4 files changed

+142/−6 lines, 4 filesdep ~basePVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base

API changes (from Hackage documentation)

+ Text.Ginger.GVal: instance Text.Printf.PrintfArg (Text.Ginger.GVal.GVal m)
+ Text.PrintfA: P :: a -> PrintfArgT
+ Text.PrintfA: T :: (forall r. PrintfType r => r) -> PrintfTypeT
+ Text.PrintfA: [unT] :: PrintfTypeT -> forall r. PrintfType r => r
+ Text.PrintfA: data PrintfArgT
+ Text.PrintfA: data PrintfTypeT
+ Text.PrintfA: printfa :: PrintfType t => String -> [PrintfArgT] -> t

Files

ginger.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/  name:                ginger-version:             0.2.1.0+version:             0.2.2.0 synopsis:            An implementation of the Jinja2 template language in Haskell description:         Ginger is Jinja, minus the most blatant pythonisms. Wants                      to be feature complete, but isn't quite there yet.@@ -24,6 +24,7 @@                  , Text.Ginger.Html                  , Text.Ginger.Parse                  , Text.Ginger.Run+                 , Text.PrintfA   -- other-modules:   -- other-extensions:   build-depends: base >=4.5 && <5
src/Text/Ginger/GVal.hs view
@@ -47,6 +47,7 @@ import Data.Scientific ( Scientific                        , floatingOrInteger                        , toBoundedInteger+                       , toRealFloat                         ) import Control.Applicative import qualified Data.Aeson as JSON@@ -56,6 +57,7 @@ import Control.Monad ( forM, mapM ) import Control.Monad.Trans (MonadTrans, lift) import Data.Default (Default, def)+import Text.Printf  import Text.Ginger.Html @@ -122,6 +124,18 @@ instance ToHtml (GVal m) where     toHtml = asHtml +instance PrintfArg (GVal m) where+    formatArg x fmt =+        case fmtChar (vFmt 's' fmt) of+            's' -> formatString+                    (Text.unpack $ asText x)+                    (fmt { fmtChar = 's', fmtPrecision = Nothing })+            'c' -> formatString+                    (Text.unpack $ asText x)+                    fmt+            _ -> formatRealFloat+                    (toRealFloat . fromMaybe 0 . asNumber $ x :: Double)+                    fmt  -- * Representing functions as 'GVal's --
src/Text/Ginger/Run.hs view
@@ -36,20 +36,21 @@  import Prelude ( (.), ($), (==), (/=)                , (>), (<), (>=), (<=)-               , (+), (-), (*), (/), div+               , (+), (-), (*), (/), div, (**), (^)                , (||), (&&)                , (++)                , Show, show                , undefined, otherwise                , Maybe (..)                , Bool (..)-               , Int-               , fromIntegral, floor+               , Int, Integer, String+               , fromIntegral, floor, round                , not                , show                , uncurry                , seq-               , snd+               , fst, snd+               , maybe                ) import qualified Prelude import Data.Maybe (fromMaybe, isJust)@@ -57,6 +58,9 @@ import Text.Ginger.AST import Text.Ginger.Html import Text.Ginger.GVal+import Text.Printf+import Text.PrintfA+import Data.Scientific (formatScientific)  import Data.Text (Text) import Data.String (fromString)@@ -73,8 +77,9 @@ import Data.Scientific (Scientific) import Data.Scientific as Scientific import Data.Default (def)-import Safe (readMay)+import Safe (readMay, lastDef) import Network.HTTP.Types (urlEncode)+import Debug.Trace (trace)  -- | Execution context. Determines how to look up variables from the -- environment, and how to write out template output.@@ -149,7 +154,11 @@             , ("concat", fromFunction . variadicStringFunc $ mconcat)             , ("contains", fromFunction gfnContains)             , ("default", fromFunction gfnDefault)+            , ("d", fromFunction gfnDefault)             , ("difference", fromFunction . variadicNumericFunc 0 $ difference)+            , ("escape", fromFunction gfnEscape)+            , ("e", fromFunction gfnEscape)+            , ("filesizeformat", fromFunction gfnFileSizeFormat)             , ("equals", fromFunction gfnEquals)             , ("nequals", fromFunction gfnNEquals)             , ("greaterEquals", fromFunction gfnGreaterEquals)@@ -164,9 +173,11 @@             , ("modulo", fromFunction . variadicNumericFunc 1 $ fromIntegral . modulo . Prelude.map Prelude.floor)             , ("num", fromFunction . unaryFunc $ toGVal . asNumber)             , ("product", fromFunction . variadicNumericFunc 1 $ Prelude.product)+            , ("printf", fromFunction gfnPrintf)             , ("ratio", fromFunction . variadicNumericFunc 1 $ Scientific.fromFloatDigits . ratio . Prelude.map Scientific.toRealFloat)             , ("round", fromFunction . unaryNumericFunc 0 $ Prelude.fromIntegral . Prelude.round)             , ("show", fromFunction . unaryFunc $ fromString . show)+            , ("slice", fromFunction $ gfnSlice)             , ("str", fromFunction . unaryFunc $ toGVal . asText)             , ("sum", fromFunction . variadicNumericFunc 0 $ Prelude.sum)             , ("truncate", fromFunction . unaryNumericFunc 0 $ Prelude.fromIntegral . Prelude.truncate)@@ -195,6 +206,9 @@             | asBoolean x = return x             | otherwise = gfnDefault xs +        gfnEscape :: Function (Run m h)+        gfnEscape = return . toGVal . html . mconcat . fmap (asText . snd)+         gfnAny :: Function (Run m h)         gfnAny xs = return . toGVal $ Prelude.any (asBoolean . snd) xs @@ -299,6 +313,43 @@         gfnCenter ((_, s):(_, w):(_, pad):_) =             return . toGVal $ center (asText s) (fromMaybe 80 $ Prelude.truncate <$> asNumber w) (asText pad) +        gfnSlice :: Function (Run m h)+        gfnSlice [] = return def+        gfnSlice [(Nothing, slicee)] = return slicee+        gfnSlice [(Nothing, slicee), (Nothing, startPos)] =+            gfnSlice [(Nothing, slicee), (Nothing, startPos), (Nothing, def)]+        gfnSlice [(Nothing, slicee), (Nothing, startPos), (Nothing, length)] = do+            case asDictItems slicee of+                Just items -> do+                    let slicedItems = slice items startInt lengthInt+                    return $ dict slicedItems+                Nothing -> do+                    let items = fromMaybe [] $ asList slicee+                        slicedItems = slice items startInt lengthInt+                    return $ toGVal slicedItems+            where+                startInt :: Int+                startInt = fromMaybe 0 . fmap Prelude.round . asNumber $ startPos++                lengthInt :: Maybe Int+                lengthInt = fmap Prelude.round . asNumber $ length++                slice :: [a] -> Int -> Maybe Int -> [a]+                slice xs start Nothing =+                    Prelude.drop start $ xs+                slice xs start (Just length) =+                    Prelude.take length . Prelude.drop start $ xs+        gfnSlice ((Nothing, slicee):(Nothing, startPos):args) =+            let length = fromMaybe def $ List.lookup (Just "length") args+            in gfnSlice [(Nothing, slicee), (Nothing, startPos), (Nothing, length)]+        gfnSlice ((Nothing, slicee):args) =+            let startPos = fromMaybe def $ List.lookup (Just "start") args+            in gfnSlice ((Nothing, slicee):(Nothing, startPos):args)+        gfnSlice args =+            let slicee = fromMaybe def $ List.lookup (Just "slicee") args+            in gfnSlice ((Nothing, slicee):args)++         gfnSort :: Function (Run m h)         gfnSort [] = return def         gfnSort ((_,sortee):args) = do@@ -351,6 +402,64 @@                 paddingL = Text.take charsL . Text.replicate repsL $ pad                 repsR = Prelude.succ charsR `div` Text.length pad                 paddingR = Text.take charsR . Text.replicate repsR $ pad++        gfnFileSizeFormat :: Function (Run m h)+        gfnFileSizeFormat [(_, sizeG)] =+            gfnFileSizeFormat [(Nothing, sizeG), (Nothing, def)]+        gfnFileSizeFormat [(_, sizeG), (_, binaryG)] = do+            let sizeM = Prelude.round <$> asNumber sizeG+                binary = asBoolean binaryG+            Prelude.maybe+                (return def)+                (return . toGVal . formatFileSize binary)+                sizeM+        gfnFileSizeFormat _ = return def++        formatFileSize :: Bool -> Integer -> String+        formatFileSize binary size =+            let units =+                    if binary+                        then+                            [ (1, "B")+                            , (1024, "kiB")+                            , (1024 ^ 2, "MiB")+                            , (1024 ^ 3, "GiB")+                            , (1024 ^ 4, "TiB")+                            , (1024 ^ 5, "PiB")+                            ]+                        else+                            [ (1, "B")+                            , (1000, "kB")+                            , (1000000, "MB")+                            , (1000000000, "GB")+                            , (1000000000000, "TB")+                            , (1000000000000000, "PB")+                            ]+                (divisor, unitName) =+                    lastDef (1, "B") [ (d, u) | (d, u) <- units, d <= size ]+                dividedSize :: Scientific+                dividedSize = fromIntegral size / fromIntegral divisor+                formattedSize =+                    if isInteger dividedSize+                        then formatScientific Fixed (Just 0) dividedSize+                        else formatScientific Fixed (Just 1) dividedSize+            in formattedSize ++ " " ++ unitName++        gfnPrintf :: Function (Run m h)+        gfnPrintf [] = return def+        gfnPrintf [(_, fmtStrG)] = return fmtStrG+        gfnPrintf ((_, fmtStrG):args) = do+            return . toGVal $ printfG fmtStr (fmap snd args)+            where+                fmtStr = Text.unpack $ asText fmtStrG++printfG :: String -> [GVal m] -> String+printfG fmt args = printfa fmt (fmap (P . asText) args)++apply :: (a -> b -> b) -> b -> [a] -> b+apply f z [] = z+apply f z [x] = f x z+apply f z (x:xs) = f x (apply f z xs)  -- | Create an execution context for runGingerT. -- Takes a lookup function, which returns ginger values into the carrier monad
+ src/Text/PrintfA.hs view
@@ -0,0 +1,12 @@+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE RankNTypes #-}+module Text.PrintfA+where++import Text.Printf++data PrintfArgT = forall a. PrintfArg a => P a+data PrintfTypeT = T { unT :: forall r. PrintfType r => r }++printfa :: PrintfType t => String -> [ PrintfArgT ] -> t+printfa format = unT . foldl (\(T r) (P a) -> T $ r a ) (T $ printf format)