marvin-interpolate 0.2.0 → 0.3.0
raw patch · 5 files changed
+92/−41 lines, 5 filesdep ~marvin-interpolatePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: marvin-interpolate
API changes (from Hackage documentation)
- Marvin.Interpolate.Text.Lazy: class ShowLT a where showListLT l = "[" <> intercalate ", " (map showLT l) <> "]"
- Marvin.Interpolate.Text.Lazy: instance GHC.Show.Show a => Marvin.Interpolate.Text.Lazy.ShowLT a
- Marvin.Interpolate.Text.Lazy: instance Marvin.Interpolate.Text.Lazy.ShowLT Data.Text.Internal.Lazy.Text
- Marvin.Interpolate.Text.Lazy: instance Marvin.Interpolate.Text.Lazy.ShowLT Data.Text.Internal.Text
- Marvin.Interpolate.Text.Lazy: instance Marvin.Interpolate.Text.Lazy.ShowLT GHC.Types.Char
- Marvin.Interpolate.Text.Lazy: iqLT :: QuasiQuoter
- Marvin.Interpolate.Text.Lazy: isLT :: String -> Q Exp
- Marvin.Interpolate.Text.Lazy: showLT :: ShowLT a => a -> Text
- Marvin.Interpolate.Text.Lazy: showListLT :: ShowLT a => [a] -> Text
+ Marvin.Interpolate.Text.Lazy: class ShowL a where showListL l = "[" <> intercalate ", " (map showL l) <> "]"
+ Marvin.Interpolate.Text.Lazy: instance GHC.Show.Show a => Marvin.Interpolate.Text.Lazy.ShowL a
+ Marvin.Interpolate.Text.Lazy: instance Marvin.Interpolate.Text.Lazy.ShowL Data.Text.Internal.Lazy.Text
+ Marvin.Interpolate.Text.Lazy: instance Marvin.Interpolate.Text.Lazy.ShowL Data.Text.Internal.Text
+ Marvin.Interpolate.Text.Lazy: instance Marvin.Interpolate.Text.Lazy.ShowL GHC.Types.Char
+ Marvin.Interpolate.Text.Lazy: iqL :: QuasiQuoter
+ Marvin.Interpolate.Text.Lazy: isL :: String -> Q Exp
+ Marvin.Interpolate.Text.Lazy: showL :: ShowL a => a -> Text
+ Marvin.Interpolate.Text.Lazy: showListL :: ShowL a => [a] -> Text
Files
- README.md +11/−9
- marvin-interpolate.cabal +4/−3
- src/Marvin/Interpolate/String.hs +1/−1
- src/Marvin/Interpolate/Text/Lazy.hs +23/−23
- test/Spec.hs +53/−5
README.md view
@@ -3,6 +3,8 @@ [](https://travis-ci.org/JustusAdam/marvin-interpolate) [](http://hackage.haskell.org/package/marvin-interpolate) +You can find the proper documentation for this library as part of the marvin docs on [readthedocs](https://marvin.readthedocs.org/en/latest/interpolation.html), the following readme provides a shortened overview.+ This string interpolation library originates from the [Marvin project](https://github.com/JustusAdam/marvin) where, in an attempt to make it easy for the user to write text with some generated data in it, I developed this string interpolation library. The design is very similar to the string interpolation in Scala and CoffeeScript, in that the hard work happens at compile time (no parsing overhead at runtime) and any valid Haskell expression can be interpolated. @@ -13,7 +15,7 @@ import Marvin.Interpolate -myStr = [i|some string %{show $ map succ [1,2,3]} and data |]+myStr = [iq|some string %{show $ map succ [1,2,3]} and data |] -- "some string [2,3,4] and data" ``` @@ -28,27 +30,27 @@ -- "some string [2,3,4] and data" ``` -It basically transforms the interpolated string `[i|interpolated string|]`, or in splices `$(is "interpolated string")` into a concatenation of all string bits and the expressions in `%{}`.+It basically transforms the interpolated string `[iq|interpolated string|]`, or in splices `$(is "interpolated string")` into a concatenation of all string bits and the expressions in `%{}`. Therefore it is not limited to `String` alone, rather it produces a literal at compile time, which can either be interpreted as `String` or, using the [`OverloadedStrings`](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#overloaded-string-literals) extension, as `Text` or `ByteString` or any other string type. -`i` (for *interpolate*) and `is` (for *interpolate splice*) is the basic interpolator, which inserts the expressions verbatim. Hence when using `i` or `is` all expressions must return the desired string type.+`i` (for *interpolate quoter*) and `is` (for *interpolate splice*) is the basic interpolator, which inserts the expressions verbatim. Hence when using `iq` or `is` all expressions must return the desired string type. There are specialized interpolators, which also perform automatic conversion of non-string types into the desired string type. These specialized interpolators each have an associated typeclass, which converts string types (`String`, `Text` and lazy `Text`) to the target type, but leaves the contents unchanged and calls `show` on all other types before converting. This last instance, which is based on `Show`, can be overlapped by specifying a custom instance for your type, allowing the user to define the conversion. -The naming scheme of the interpolators in general is `i<splice?><pecialization?>`.-I. e. `isS` expands to *interpolate splice to String* and `iLT` to *interpolate to Lazy Text*.+The naming scheme of the interpolators in general is `i<splice|quoter><specialization?>`.+I. e. `isS` expands to *interpolate splice to String* and `iqL` to *interpolate quoter to Lazy Text*. -- `iS` and `isS` in `Marvin.Interpolate.String` converts to `String` via the `ShowS` typeclass-- `iT` and `isT` in `Marvin.Interpolate.Text` converts to `Text` via the `ShowT` typeclass-- `iLT` and `isLT` in `Marvin.Interpolate.Text.Lazy` converts to lazy `Text` via the `ShowLT` typeclass+- `iqS` and `isS` in `Marvin.Interpolate.String` converts to `String` via the `ShowS` typeclass+- `iqT` and `isT` in `Marvin.Interpolate.Text` converts to `Text` via the `ShowT` typeclass+- `iqL` and `isL` in `Marvin.Interpolate.Text.Lazy` converts to lazy `Text` via the `ShowLT` typeclass To import all interpolators, import `Marvin.Interpolate.All`. ## Syntax -Interpolation uses the quasi quoter sytax, which starts with `[interpolator_name|` and ends with `|]`.+Interpolation uses the quasi quoter sytax, which starts with `[interpolator_name|` and ends with `|]` or splice syntax `$(interpolator "interpolated string")`. Anything in between is interpreted by the library. The format string in between uses the syntax `%{expression}`.
marvin-interpolate.cabal view
@@ -1,5 +1,5 @@ name: marvin-interpolate-version: 0.2.0+version: 0.3.0 cabal-version: >=1.10 build-type: Simple license: BSD3@@ -43,8 +43,9 @@ main-is: Spec.hs build-depends: base >=4.9.0.0 && <4.10,- marvin-interpolate >=0.2.0 && <0.3,- hspec >=2.2.4 && <2.3+ marvin-interpolate >=0.3.0 && <0.4,+ hspec >=2.2.4 && <2.3,+ text >=1.2.2.1 && <1.3 default-language: Haskell2010 hs-source-dirs: test ghc-options: -threaded -rtsopts -with-rtsopts=-N
src/Marvin/Interpolate/String.hs view
@@ -58,7 +58,7 @@ -- -- converts all expressions to 'String' by calling 'showStr' on the result. isS :: String -> Q Exp-isS = return . interpolateInto (VarE 'show)+isS = return . interpolateInto (VarE 'showStr) -- | __i__nterpolate __q__uoter to __S__tring
src/Marvin/Interpolate/Text/Lazy.hs view
@@ -14,9 +14,9 @@ {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE UndecidableInstances #-} module Marvin.Interpolate.Text.Lazy- ( isLT, iqLT+ ( isL, iqL -- * Conversion class- , ShowLT(..)+ , ShowL(..) ) where @@ -32,38 +32,38 @@ -- | A type class for converting things to 'L.Text' -- -- Leaves string likes ('String', 'T.Text' and 'L.Text') unchanged, tries 'Show' (overlappable) on all others.-class ShowLT a where- showLT :: a -> L.Text- showListLT :: [a] -> L.Text- showListLT l = "[" <> L.intercalate ", " (map showLT l) <> "]"+class ShowL a where+ showL :: a -> L.Text+ showListL :: [a] -> L.Text+ showListL l = "[" <> L.intercalate ", " (map showL l) <> "]" -instance ShowLT L.Text where- showLT = id+instance ShowL L.Text where+ showL = id -instance ShowLT T.Text where- showLT = L.fromStrict+instance ShowL T.Text where+ showL = L.fromStrict -instance ShowLT Char where- showLT = L.pack . show- showListLT = L.pack+instance ShowL Char where+ showL = L.pack . show+ showListL = L.pack -instance {-# OVERLAPPABLE #-} Show a => ShowLT a where- showLT = L.pack . show+instance {-# OVERLAPPABLE #-} Show a => ShowL a where+ showL = L.pack . show --- | __i__nterpolate __s__plice to __L__azy __T__ext+-- | __i__nterpolate __s__plice to __L__azy Text -- -- Template Haskell splice function, used like @$(isLT "my str %{expr}")@ -- --- converts all expressions to 'L.Text' by calling 'showLT' on the result.-isLT :: String -> Q Exp-isLT = return . interpolateInto (VarE 'showLT)+-- converts all expressions to 'L.Text' by calling 'showL' on the result.+isL :: String -> Q Exp+isL = return . interpolateInto (VarE 'showL) --- | __i__nterpolate __q__uoter to __L__azy __T__ext+-- | __i__nterpolate __q__uoter to __L__azy Text -- -- QuasiQuoter, used like @[iLT|my str %{expr}|]@ ----- converts all expressions to 'L.Text' by calling 'showLT' on the result.-iqLT :: QuasiQuoter-iqLT = mqq { quoteExp = isLT }+-- converts all expressions to 'L.Text' by calling 'showL' on the result.+iqL :: QuasiQuoter+iqL = mqq { quoteExp = isL }
test/Spec.hs view
@@ -1,14 +1,32 @@ {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE OverloadedStrings #-} import Data.List (intercalate) import Marvin.Interpolate.All import Test.Hspec+import qualified Data.Text as T+import qualified Data.Text.Lazy as L -formatSpec :: Spec-formatSpec = do+data G = G++instance Show G where+ show _ = "show"++instance ShowStr G where+ showStr _ = "showStr"++instance ShowT G where+ showT _ = "showT"++instance ShowL G where+ showL _ = "showL"+++main :: IO ()+main = hspec $ do describe "parsing to itself" $ do it "%" $ [iq|%|] `shouldBe` "%"@@ -63,8 +81,38 @@ describe "splice interpolation" $ it "interpolates a splice" $- let x = 5 in $(isS "%{x}") `shouldBe` "5"+ let x = 5 :: Int in $(isS "%{x}") `shouldBe` "5"+ + describe "'is' generic interpolation" $ do+ it "to string" $+ $(is "") `shouldBe` ("" :: String)+ it "to Text" $+ $(is "") `shouldBe` ("" :: T.Text)+ it "to lazy Text" $ + $(is "") `shouldBe` ("" :: L.Text)+ + let x = 5 :: Int + describe "'isS' interpolation to String" $ do+ it "calls show on Int" $+ $(isS "%{x}") `shouldBe` "5"+ it "calls showStr if available" $+ $(isS "%{G}") `shouldBe` "showStr"+ it "does not change Text" $+ $(isS "%{\"str\" :: T.Text}") `shouldBe` "str" -main :: IO ()-main = hspec formatSpec+ describe "'isT' interpolation to Text" $ do+ it "calls show on Int" $+ $(isT "%{x}") `shouldBe` "5"+ it "calls showT if available" $+ $(isT "%{G}") `shouldBe` "showT"+ it "does not change Text" $+ $(isT "%{\"str\" :: T.Text}") `shouldBe` "str"++ describe "'isL' interpolation to lazy Text" $ do+ it "calls show on Int" $+ $(isL "%{x}") `shouldBe` "5"+ it "calls showStr if available" $+ $(isL "%{G}") `shouldBe` "showL"+ it "does not change Text" $+ $(isL "%{\"str\" :: T.Text}") `shouldBe` "str"