ginger 0.8.0.1 → 0.8.1.0
raw patch · 4 files changed
+88/−2 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- ginger.cabal +1/−1
- src/Text/Ginger/Run.hs +4/−0
- src/Text/Ginger/Run/Builtins.hs +61/−0
- test/Text/Ginger/SimulationTests.hs +22/−1
ginger.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/ name: ginger-version: 0.8.0.1+version: 0.8.1.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.
src/Text/Ginger/Run.hs view
@@ -129,6 +129,7 @@ , ("capitalize", fromFunction . variadicStringFunc $ mconcat . Prelude.map capitalize) , ("ceil", fromFunction . unaryNumericFunc 0 $ Prelude.fromIntegral . Prelude.ceiling) , ("center", fromFunction gfnCenter)+ , ("compose", fromFunction gfnCompose) , ("concat", fromFunction gfnConcat) , ("contains", fromFunction gfnContains) , ("d", fromFunction gfnDefault)@@ -171,6 +172,7 @@ , ("nequals", fromFunction gfnNEquals) , ("num", fromFunction . unaryFunc $ toGVal . asNumber) , ("odd", fromFunction gfnOdd)+ , ("partial", fromFunction gfnPartial) , ("printf", fromFunction gfnPrintf) , ("product", fromFunction . variadicNumericFunc 1 $ Prelude.product) , ("ratio", fromFunction . variadicNumericFunc 1 $ Scientific.fromFloatDigits . ratio . Prelude.map Scientific.toRealFloat)@@ -186,6 +188,8 @@ , ("upper", fromFunction . variadicStringFunc $ mconcat . Prelude.map Text.toUpper) , ("lower", fromFunction . variadicStringFunc $ mconcat . Prelude.map Text.toLower) , ("throw", fromFunction gfnThrow)+ , ("zip", fromFunction gfnZip)+ , ("zipwith", fromFunction gfnZipWith) -- Tests/predicates
src/Text/Ginger/Run/Builtins.hs view
@@ -309,6 +309,67 @@ return . toGVal $ Text.replace search replace str _ -> throwHere $ ArgumentsError (Just "replace") "expected: (str, search, replace)" +gfnCompose :: forall m p h. Monad m => Function (Run p m h)+gfnCompose [] = fail "Invalid arguments to compose()"+gfnCompose [(_, fG)] = return fG+gfnCompose ((_, fG):xs) = do+ gG <- gfnCompose xs+ case (asFunction fG, asFunction gG) of+ (Nothing, _) -> fail $ "Argument to compose() is not a function"+ (_, Nothing) -> fail $ "PANIC: Composition of functions is not a function"+ (Just f, Just g) -> do+ let h args = do+ arg' <- g args+ f [(Nothing, arg')]+ return $ fromFunction h++gfnPartial :: forall m p h. Monad m => Function (Run p m h)+gfnPartial [] = fail "Invalid arguments to partial()"+gfnPartial ((_, fG):args) = do+ case asFunction fG of+ Nothing -> fail "Argument to partial() is not a function"+ Just f -> do+ let h args' = do+ f (args ++ args')+ return $ fromFunction h++gfnZip :: forall m p h. Monad m => Function (Run p m h)+gfnZip args = do+ toGVal <$> go (fmap (fromMaybe [] . asList . snd) args)+ where+ go :: [[GVal (Run p m h)]] -> Run p m h [GVal (Run p m h)]+ go [] = return []+ go args = do+ let heads = fmap headMay args+ tails = fmap (List.drop 1) args+ if List.any isNothing heads then+ return []+ else do+ let currentVal = toGVal (fmap (fromMaybe def) heads)+ tailVals <- go tails+ return $ currentVal : tailVals+++gfnZipWith :: forall m p h. Monad m => Function (Run p m h)+gfnZipWith ((Nothing, gfn):args) = do+ zipFunction <- case asFunction gfn of+ Nothing -> fail $ "Invalid args to zipwith"+ Just fn -> return fn+ toGVal <$> go zipFunction (fmap fst args) (fmap (fromMaybe [] . asList . snd) args)+ where+ go :: Function (Run p m h) -> [Maybe Text] -> [[GVal (Run p m h)]] -> Run p m h [GVal (Run p m h)]+ go f _ [] = return []+ go f argNames args = do+ let heads = fmap headMay args+ tails = fmap (List.drop 1) args+ if List.any isNothing heads then+ return []+ else do+ currentVal <- f (List.zip argNames (fmap (fromMaybe def) heads))+ tailVals <- go f argNames tails+ return $ currentVal : tailVals++ gfnMap :: Monad m => Function m gfnMap args = do let parsedArgs = extractArgsDefL
test/Text/Ginger/SimulationTests.hs view
@@ -497,6 +497,10 @@ "{{ \"foobar\"|center(2) }}" "foobar" ]+ , testCase "\"compose\"" $ do+ mkTestText [] []+ "{{ (compose(json, capitalize))('hello') }}"+ "\"Hello\"" , testCase "\"concat\"" $ do mkTestHtml [] [] "{{ [\"hello\", \"world\"]|concat }}"@@ -747,7 +751,12 @@ -- \"modulo\" -- \"num\" -- TODO- -- \"printf\"+ , testGroup "\"partial\""+ [ testCase "partial" $ do+ mkTestHtml [] []+ "{{ partial(sum, 1)(2) }}"+ "3"+ ] , testGroup "\"printf\"" [ testCase "%i, passed as int" $ do mkTestHtml [] []@@ -901,6 +910,18 @@ mkTestHtml [] [] "{{ replace('foobar', 'o') }}" "fbar"+ ]+ , testGroup "\"zip\""+ [ testCase "lists" $ do+ mkTestHtml [] []+ "{{ zip([1,2,3], [4,5,6])|json(pretty=false) }}"+ "[[1,4],[2,5],[3,6]]"+ ]+ , testGroup "\"zipwith\""+ [ testCase "sum" $ do+ mkTestHtml [] []+ "{{ zipwith(sum, [1,2,3], [4,5,6])|json(pretty=false) }}"+ "[5,7,9]" ] , testGroup "\"json\"" [ testCase "null" $ do