interpolate 0.2.0 → 0.2.1
raw patch · 6 files changed
+58/−39 lines, 6 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- interpolate.cabal +4/−5
- src/Data/String/Interpolate.hs +30/−13
- src/Data/String/Interpolate/Compat.hs +0/−10
- src/Data/String/Interpolate/Parse.hs +13/−9
- test/Data/String/Interpolate/ParseSpec.hs +8/−2
- test/Data/String/InterpolateSpec.hs +3/−0
interpolate.cabal view
@@ -1,11 +1,11 @@--- This file has been generated from package.yaml by hpack version 0.26.0.+cabal-version: 1.12++-- This file has been generated from package.yaml by hpack version 0.34.2. -- -- see: https://github.com/sol/hpack------ hash: cc8a15b9e3938bac2066e1f8e454e027bd589000a0baf42191f06ceb39e9ce04 name: interpolate-version: 0.2.0+version: 0.2.1 homepage: https://github.com/sol/interpolate#readme bug-reports: https://github.com/sol/interpolate/issues license: MIT@@ -14,7 +14,6 @@ author: Simon Hengel <sol@typeful.net> maintainer: Simon Hengel <sol@typeful.net> build-type: Simple-cabal-version: >= 1.10 category: Data, Text stability: experimental synopsis: String interpolation done right
src/Data/String/Interpolate.hs view
@@ -15,7 +15,7 @@ import Data.String.Interpolate.Internal.Util import Data.String.Interpolate.Parse-import Data.String.Interpolate.Compat (Q, Exp, appE, reportError)+import Language.Haskell.TH -- | -- A `QuasiQuoter` for string interpolation. Expression enclosed within@@ -48,20 +48,37 @@ where err name = error ("Data.String.Interpolate.i: This QuasiQuoter can not be used as a " ++ name ++ "!") - toExp:: [Node] -> Q Exp- toExp nodes = case nodes of- [] -> [|""|]- (x:xs) -> f x `appE` toExp xs+ toExp :: [Node ()] -> Q Exp+ toExp input = do+ nodes <- mapM generateName input+ e <- go nodes+ return $ foldr lambda e [name | Abstraction name <- nodes] where- f (Literal s) = [|showString s|]- f (Expression e) = [|(showString . toString) $(reifyExpression e)|]+ lambda :: Name -> Exp -> Exp+ lambda name e = LamE [VarP name] e - reifyExpression :: String -> Q Exp- reifyExpression s = case parseExp s of- Left _ -> do- reportError "Parse error in expression!"- [|""|]- Right e -> return e+ generateName :: Node () -> Q (Node Name)+ generateName (Abstraction ()) = Abstraction <$> newName "x"+ generateName (Literal s) = return (Literal s)+ generateName (Expression e) = return (Expression e)++ go :: [Node Name] -> Q Exp+ go nodes = case nodes of+ [] -> [|""|]+ (x:xs) -> eval x `appE` go xs+ where+ eval (Literal s) = [|showString s|]+ eval (Expression e) = interpolate (reifyExpression e)+ eval (Abstraction name) = interpolate $ (return $ VarE name)++ interpolate :: Q Exp -> Q Exp+ interpolate e = [|(showString . toString) $(e)|]++ reifyExpression :: String -> Q Exp+ reifyExpression s = case parseExp s of+ Left _ -> do+ fail "Parse error in expression!" :: Q Exp+ Right e -> return e decodeNewlines :: String -> String decodeNewlines = go
src/Data/String/Interpolate/Compat.hs view
@@ -1,13 +1,8 @@ {-# LANGUAGE CPP #-} module Data.String.Interpolate.Compat ( readMaybe-, module Language.Haskell.TH-#if !MIN_VERSION_template_haskell(2,8,0)-, reportError-#endif ) where -import Language.Haskell.TH import Text.Read #if !MIN_VERSION_base(4,6,0)@@ -36,9 +31,4 @@ readMaybe s = case readEither s of Left _ -> Nothing Right a -> Just a-#endif--#if !MIN_VERSION_template_haskell(2,8,0)-reportError :: String -> Q ()-reportError = report True #endif
src/Data/String/Interpolate/Parse.hs view
@@ -2,19 +2,23 @@ import Data.String.Interpolate.Internal.Util -data Node = Literal String | Expression String+data Node a = Literal String | Expression String | Abstraction a -parseNodes :: String -> [Node]+parseNodes :: String -> [Node ()] parseNodes = go "" where- go :: String -> String -> [Node]+ go :: String -> String -> [Node ()] go acc input = case input of- "" -> [(lit . reverse) acc]+ "" -> lit [] '\\':x:xs -> go (x:'\\':acc) xs- '#':'{':xs -> case span (/= '}') xs of- (ys, _:zs) -> (lit . reverse) acc : Expression ys : go "" zs- (_, "") -> [lit (reverse acc ++ input)]+ '#':'{':xs | (e, '}':ys) <- span (/= '}') xs -> lit $ expression e : go "" ys x:xs -> go (x:acc) xs+ where+ expression e+ | null e = Abstraction ()+ | otherwise = Expression e - lit :: String -> Node- lit = Literal . unescape+ lit :: [Node ()] -> [Node ()]+ lit nodes+ | null acc = nodes+ | otherwise = (Literal . unescape $ reverse acc) : nodes
test/Data/String/Interpolate/ParseSpec.hs view
@@ -6,8 +6,8 @@ import Data.String.Interpolate.Parse -deriving instance Eq Node-deriving instance Show Node+deriving instance Eq a => Eq (Node a)+deriving instance Show a => Show (Node a) main :: IO () main = hspec spec@@ -17,6 +17,12 @@ describe "parseNodes" $ do it "parses string literals" $ do parseNodes "foo" `shouldBe` [Literal "foo"]++ it "parses abstractions" $ do+ parseNodes "#{}" `shouldBe` [Abstraction ()]++ it "parses expressions" $ do+ parseNodes "#{foo}" `shouldBe` [Expression "foo"] it "parses embedded expressions" $ do parseNodes "foo #{bar} baz" `shouldBe` [Literal "foo ", Expression "bar", Literal " baz"]
test/Data/String/InterpolateSpec.hs view
@@ -18,6 +18,9 @@ it "interpolates an expression of type String" $ do property $ \xs ys -> [i|foo #{xs ++ ys} bar|] `shouldBe` "foo " ++ xs ++ ys ++ " bar" + it "interpolates abstractions" $ do+ [i|foo #{} bar #{} baz|] (23 :: Int) "test" `shouldBe` "foo 23 bar test baz"+ it "accepts character escapes" $ do [i|foo \955 bar|] `shouldBe` "foo \955 bar"