ginger 0.3.2.0 → 0.3.5.0
raw patch · 5 files changed
+56/−4 lines, 5 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Text.Ginger.GVal: marshalGVal :: GVal m -> GVal n
+ Text.Ginger.Parse: instance GHC.Exception.Exception Text.Ginger.Parse.ParserError
+ Text.Ginger.Parse: instance GHC.Generics.Generic Text.Ginger.Parse.ParserError
+ Text.Ginger.Run.FuncUtils: extractArgs :: [Text] -> [(Maybe Text, a)] -> (HashMap Text a, [a], HashMap Text a, [Text])
+ Text.Ginger.Run.FuncUtils: extractArgsDefL :: [(Text, a)] -> [(Maybe Text, a)] -> Either ([a], HashMap Text a, [Text]) [a]
+ Text.Ginger.Run.FuncUtils: extractArgsL :: [Text] -> [(Maybe Text, a)] -> Either ([a], HashMap Text a, [Text]) [Maybe a]
+ Text.Ginger.Run.FuncUtils: extractArgsT :: ([Maybe a] -> b) -> [Text] -> [(Maybe Text, a)] -> Either ([a], HashMap Text a, [Text]) b
+ Text.Ginger.Run.FuncUtils: ignoreArgNames :: ([a] -> b) -> ([(c, a)] -> b)
+ Text.Ginger.Run.FuncUtils: injectDefaults :: [a] -> [Maybe a] -> [a]
+ Text.Ginger.Run.FuncUtils: unaryFunc :: forall m h. (Monad m) => (GVal (Run m h) -> GVal (Run m h)) -> Function (Run m h)
+ Text.Ginger.Run.FuncUtils: unaryNumericFunc :: Monad m => Scientific -> (Scientific -> Scientific) -> [(Maybe Text, GVal (Run m h))] -> Run m h (GVal (Run m h))
+ Text.Ginger.Run.FuncUtils: variadicNumericFunc :: Monad m => Scientific -> ([Scientific] -> Scientific) -> [(Maybe Text, GVal (Run m h))] -> Run m h (GVal (Run m h))
+ Text.Ginger.Run.FuncUtils: variadicStringFunc :: Monad m => ([Text] -> Text) -> [(Maybe Text, GVal (Run m h))] -> Run m h (GVal (Run m h))
+ Text.Ginger.Run.VM: appendCapture :: (Monoid h, Monad m) => h -> Run m h ()
+ Text.Ginger.Run.VM: clearCapture :: (Monoid h, Monad m) => Run m h ()
+ Text.Ginger.Run.VM: fetchCapture :: Monad m => Run m h h
+ Text.Ginger.Run.VM: getVar :: Monad m => VarName -> Run m h (GVal (Run m h))
+ Text.Ginger.Run.VM: setVar :: Monad m => VarName -> GVal (Run m h) -> Run m h ()
+ Text.Ginger.Run.VM: withLocalScope :: (Monad m) => Run m h a -> Run m h a
+ Text.Ginger.Run.VM: withLocalState :: (Monad m, MonadState s m) => m a -> m a
Files
- ginger.cabal +3/−3
- src/Text/Ginger/GVal.hs +21/−0
- src/Text/Ginger/Parse.hs +6/−1
- src/Text/Ginger/Run.hs +2/−0
- src/Text/Ginger/Run/Builtins.hs +24/−0
ginger.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/ name: ginger-version: 0.3.2.0+version: 0.3.5.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.@@ -26,10 +26,10 @@ , Text.Ginger.Parse , Text.Ginger.Run , Text.PrintfA+ , Text.Ginger.Run.VM+ , Text.Ginger.Run.FuncUtils other-modules: Text.Ginger.Run.Type- , Text.Ginger.Run.FuncUtils , Text.Ginger.Run.Builtins- , Text.Ginger.Run.VM -- other-extensions: build-depends: base >=4.5 && <5 , aeson
src/Text/Ginger/GVal.hs view
@@ -20,6 +20,7 @@ , (++), (+), (-), (*), (/), div , (=<<), (>>=), return , undefined, otherwise, id, const+ , fmap , Maybe (..) , Bool (..) , Either (..)@@ -105,6 +106,26 @@ , length :: Maybe Int -- ^ Get length of value, if it is a collection (list/dict) , isNull :: Bool -- ^ Check if the value is null , asJSON :: Maybe JSON.Value -- ^ Provide a custom JSON representation of the value+ }++-- | Marshal a GVal between carrier monads.+-- This will lose 'asFunction' information, because functions cannot be+-- transferred to other carrier monads, but it will keep all other data+-- structures intact.+marshalGVal :: GVal m -> GVal n+marshalGVal g =+ GVal+ { asList = fmap marshalGVal <$> asList g+ , asDictItems = fmap (\items -> [(k, marshalGVal v) | (k, v) <- items]) (asDictItems g)+ , asLookup = fmap (fmap marshalGVal .) (asLookup g)+ , asHtml = asHtml g+ , asText = asText g+ , asBoolean = asBoolean g+ , asNumber = asNumber g+ , asFunction = Nothing+ , isNull = isNull g+ , length = length g+ , asJSON = asJSON g } -- | Convenience wrapper around 'asDictItems' to represent a 'GVal' as a
src/Text/Ginger/Parse.hs view
@@ -1,6 +1,7 @@ {-#LANGUAGE TupleSections #-} {-#LANGUAGE OverloadedStrings #-} {-#LANGUAGE ScopedTypeVariables #-}+{-#LANGUAGE DeriveGeneric #-} -- | Ginger parser. module Text.Ginger.Parse ( parseGinger@@ -39,6 +40,8 @@ ) import Control.Monad.Trans.Class ( lift ) import Control.Applicative+import Control.Exception (Exception)+import GHC.Generics import Safe ( readMay ) import Data.Text (Text)@@ -73,7 +76,9 @@ , peSourceLine :: Maybe Int -- ^ Line number, if available , peSourceColumn :: Maybe Int -- ^ Column number, if available }- deriving (Show)+ deriving (Show, Generic)++instance Exception ParserError where -- | Helper function to create a Ginger parser error from a Parsec error. fromParsecError :: ParseError -> ParserError
src/Text/Ginger/Run.hs view
@@ -104,6 +104,7 @@ , ("date", fromFunction gfnDateFormat) , ("dateformat", fromFunction gfnDateFormat) , ("default", fromFunction gfnDefault)+ , ("dictsort", fromFunction gfnDictsort) , ("difference", fromFunction . variadicNumericFunc 0 $ difference) , ("e", fromFunction gfnEscape) , ("equals", fromFunction gfnEquals)@@ -111,6 +112,7 @@ , ("filesizeformat", fromFunction gfnFileSizeFormat) , ("filter", fromFunction gfnFilter) , ("floor", fromFunction . unaryNumericFunc 0 $ Prelude.fromIntegral . Prelude.floor)+ , ("format", fromFunction gfnPrintf) , ("greater", fromFunction gfnGreater) , ("greaterEquals", fromFunction gfnGreaterEquals) , ("int", fromFunction . unaryFunc $ toGVal . fmap (Prelude.truncate :: Scientific -> Int) . asNumber)
src/Text/Ginger/Run/Builtins.hs view
@@ -528,3 +528,27 @@ printfG :: String -> [GVal m] -> String printfG fmt args = printfa fmt (fmap P args) ++gfnDictsort :: Monad m => Function (Run m h)+gfnDictsort args =+ let extracted =+ extractArgsDefL+ [ ("dict", def)+ , ("case_sensitive", def)+ , ("by", "key")+ ]+ args+ in case extracted of+ Right [gDict, gCaseSensitive, gSortBy] -> do+ let caseSensitive = asBoolean gCaseSensitive+ sortByKey <- case asText gSortBy of+ "key" -> return True+ "value" -> return False+ "val" -> return False+ x -> fail $ "Invalid value for 'dictsort()' argument 'by': " ++ show x+ let items = fromMaybe [] $ asDictItems gDict+ let projection =+ (if caseSensitive then id else Text.toUpper) .+ (if sortByKey then fst else (asText . snd))+ return . orderedDict . List.sortOn projection $ items+ _ -> fail "Invalid arguments to 'dictsort'"