packages feed

qm-interpolated-string 0.2.1.0 → 0.3.0.0

raw patch · 19 files changed

+1706/−445 lines, 19 files

Files

CHANGELOG.md view
@@ -1,3 +1,33 @@+## <a name="v0.3.0.0"></a>0.3.0.0++* Testing on GHC 8.2.2+* More tests to cover more usage scenarios+* Ability to use `}` inside an interpolation block by escaping it++### **WARNING!** Breaking changes++* `\r` characters are no longer pre-removed.++  Up to [v0.2.1.0](#v0.2.1.0) all `\r` characters were pre-removed. When you+  compile your code with GHC you can use either *LF* or *CRLF* for line-breaks+  but not *CR* alone. When I changed handling of interpolation blocks (see+  below) I needed to get contents of interpolations blocks without **any**+  modifications, so I replaced pre-removing all *CR*s with explicit handling of+  *CRLF* in patterns. If your code ever was depending on `\r` symbols appearing+  alone inside quoters (that I can't even imagine) it could break your code.+  But it will probably never happen, I'm just noticing it here.++* Fix for interpolation blocks parsing.++  Once I noticed that `[qm|{"\n"}|]` compiles to `"n"`, I considered this as a+  bug, I also realized that interpolation blocks aren't interpreted as a bare+  haskell code as I was expecting. My bad, I've missed that, haven't written+  enought tests to cover such scenarios, it migrated from original+  *interpolatedstring-perl6* package. So I had to fix this mistake,+  notwithstanding it can break your code when you update the library. Now+  everything inside interpolation blocks is taken as bare haskell code as+  possible.+ ## <a name="v0.2.1.0"></a>0.2.1.0  * Support GHC 7.4.1
README.md view
@@ -126,6 +126,27 @@ | s                    | Replaces line breaks with spaces | qms, qns     | ``` +## About interpolation blocks++Along with all specifics of any of the quoters (which supports interpolation+blocks, which has `m` in their names) interpolation blocks work different. When+curly bracket (`{`) opens everything inside until it closes (by `}`) is parsed+as bare as possible to be given to+[haskell-src-meta](http://hackage.haskell.org/package/haskell-src-meta)+without any modifications, to be parsed as bare haskell code.++But you might need use curly brackets inside an interpolation block. I don't+think it would be a good idea, because complicated logic there may cause code+readability issues, but if you're sure you need it then you get it. You just+need to escape closing bracket to prevent interpolation block from closing, like+this: `\}`. I know it could parsed and opening curly brackets inside could be+used to prevent closing by next `}` symbol, but I chose do it this way to+prevent any unobvious tricky behavior (e.g. consider `}` appear inside a string,+`[qm|foo {'x':'}':"y"} bar|]`, how that should be handled?). So I've decided to+not make parser to be very smart, just to follow simple logic. You just need to+explicitly escape every `}` symbol inside that isn't closer of an interpolation+block (you could find an example below).+ ## About escaping  ### Symbols that can be escaped@@ -149,6 +170,10 @@             this list it is interpreted just as backslash symbol, keep in mind             that `\\\` (without any of symbols from this list after)             and `\\\\` are producing same result - `\\`)+  7. `\}` - closing bracket inside an interpolation block+            (it works **only** inside opened interpolation block)+            to prevent interpolation block from closing+            (useful to escape records modification)  ### Escaping examples @@ -221,10 +246,26 @@ [qnb| foo {1+2} |] -- Result: "foo {1+2}" ``` +That's how you update some record inside interpolation block+(you need to escape closing bracket):++```haskell+{-# LANGUAGE QuasiQuotes #-}+import Text.InterpolatedString.QM (qm)+data Foo = Foo {bar :: Int, baz :: Int} deriving Show+main = let foo = Foo 10 20 in putStrLn [qm| Foo is: {foo {baz = 30\}} |]+-- Foo is: Foo {bar = 10, baz = 30}+```++## Wanna make a contribution or maintain your own fork?++You can find some info for developers on+[wiki pages](https://github.com/unclechu/haskell-qm-interpolated-string/wiki).+ ## Author  [Viacheslav Lotsmanov](https://github.com/unclechu)  ## License -[The Unlicense](./LICENSE)+[The Unlicense](LICENSE)
qm-interpolated-string.cabal view
@@ -1,5 +1,5 @@ name:               qm-interpolated-string-version:            0.2.1.0+version:            0.3.0.0 synopsis:           Implementation of interpolated multiline strings description:        Implementation of interpolated multiline strings                     that ignores indentation and trailing whitespaces@@ -19,6 +19,7 @@                   , GHC == 7.10.1                   , GHC == 7.10.2                   , GHC == 8.0.2+                  , GHC == 8.2.2  source-repository head   type:     git
src/Text/InterpolatedString/QM.hs view
@@ -68,6 +68,18 @@ --       baz |] -- "foo\\nbar\\nbaz" -- @ --+-- Keep in mind that this example:+--+-- @+-- ['qmb'|+--   foo+--   bar+-- |]+-- @+--+-- Won't produce @"foo\\nbar\\n"@ nor @"\\nfor\\nbar\\n"@ but @"foo\\nbar"@, it+-- means it separates "between" the lines not by edges.+-- qmb :: QuasiQuoter qmb = QuasiQuoter Parsers.qmb   (error "Cannot use 'qmb' as a pattern")@@ -83,6 +95,19 @@ --       {'b':'a':'r':""} --       baz |] -- "foo\\n{'b':'a':'r':\\"\\"}\\nbaz" -- @+--+-- Keep in mind that this example:+--+-- @+-- ['qnb'|+--   foo+--   bar+-- |]+-- @+--+-- Won't produce @"foo\\nbar\\n"@ nor @"\\nfor\\nbar\\n"@ but @"foo\\nbar"@, it+-- means it separates "between" the lines not by edges.+-- qnb :: QuasiQuoter qnb = QuasiQuoter Parsers.qnb   (error "Cannot use 'qnb' as a pattern")@@ -97,6 +122,19 @@ --       {'b':'a':'r':""} --       baz |] -- "foo bar baz" -- @+--+-- Keep in mind that this example:+--+-- @+-- ['qms'|+--   foo+--   bar+-- |]+-- @+--+-- Won't produce @"foo bar "@ nor @" for bar "@ but @"foo bar"@, it+-- means it separates "between" the lines not by edges.+-- qms :: QuasiQuoter qms = QuasiQuoter Parsers.qms   (error "Cannot use 'qms' as a pattern")@@ -113,6 +151,19 @@ --       {'b':'a':'r':""} --       baz |] -- "foo {'b':'a':'r':\\"\\"} baz" -- @+--+-- Keep in mind that this example:+--+-- @+-- ['qns'|+--   foo+--   bar+-- |]+-- @+--+-- Won't produce @"foo bar "@ nor @" for bar "@ but @"foo bar"@, it+-- means it separates "between" the lines not by edges.+-- qns :: QuasiQuoter qns = QuasiQuoter Parsers.qns   (error "Cannot use 'qns' as a pattern")
src/Text/InterpolatedString/QM/Internal/Parsers.hs view
@@ -23,12 +23,12 @@                                                          )  import Text.InterpolatedString.QM.Internal.Parsers.Helpers-  ( unQX+  ( unQX                   -- For code generated by template   , clearIndentAtStart-  , clearIndentAtSOF-  , clearIndentTillEOF+  , clearIndentAtSOF       -- For code generated by template+  , clearIndentTillEOF     -- For code generated by template   , clearFirstQXXLineBreak-  , clearLastQXXLineBreak+  , clearLastQXXLineBreak  -- For code generated by template   , makeExpr   ) @@ -43,12 +43,12 @@  -- With interpolation blocks (line breaks and indentation are ignored) qm :: String -> TH.ExpQ-qm = makeExpr . parseQM "" . clearIndentAtStart . filter (/= '\r')+qm = makeExpr . parseQM "" . clearIndentAtStart   -- No interpolation block (line breaks and indentation are ignored) qn :: String -> TH.ExpQ-qn = makeExpr . parseQN "" . clearIndentAtStart . filter (/= '\r')+qn = makeExpr . parseQN "" . clearIndentAtStart   -- With interpolation blocks (line breaks are kept, indentation is ignored)@@ -57,7 +57,6 @@     . parseQMB ""     . clearFirstQXXLineBreak     . clearIndentAtStart-    . filter (/= '\r')   -- No interpolation block (line breaks are kept, indentation is ignored)@@ -66,7 +65,6 @@     . parseQNB ""     . clearFirstQXXLineBreak     . clearIndentAtStart-    . filter (/= '\r')   -- With interpolation blocks@@ -76,7 +74,6 @@     . parseQMS ""     . clearFirstQXXLineBreak     . clearIndentAtStart-    . filter (/= '\r')   -- No interpolation block@@ -86,4 +83,3 @@     . parseQNS ""     . clearFirstQXXLineBreak     . clearIndentAtStart-    . filter (/= '\r')
src/Text/InterpolatedString/QM/Internal/Parsers/Helpers.hs view
@@ -38,71 +38,72 @@                                                          )  -class QQ a string where-  toQQ :: a -> string--instance IsString s => QQ s s where-  toQQ = id--instance (ShowQ a, IsString s) => QQ a s where-  toQQ = fromString . showQ+class    QQ a string                     where toQQ :: a -> string+instance IsString s => QQ s s            where toQQ = id+instance (ShowQ a, IsString s) => QQ a s where toQQ = fromString . showQ   -- Parser for interpolation block unQX :: Parser -> Parser-unQX _ a ""          = [Literal (reverse a)]-unQX f a ('\\':x:xs) = unQX f (x:a) xs-unQX f a ("\\")      = unQX f ('\\':a) ""-unQX f a ('}':xs)    = AntiQuote (reverse a) : f "" xs-unQX f a (x:xs)      = unQX f (x:a) xs+unQX _ a ""            = [Literal (reverse a)] -- Error, block isn't closed+unQX f a ('\\':'}':xs) = unQX f ('}':a) xs+unQX f a ('}':xs)      = AntiQuote (reverse a) : f "" xs+unQX f a (x:xs)        = unQX f (x:a) xs   clearIndentAtSOF :: String -> Maybe String-clearIndentAtSOF ""                                 = Nothing+clearIndentAtSOF "" = Nothing+clearIndentAtSOF ('\r':'\n':xs) = clearIndentAtSOF $ '\n' : xs clearIndentAtSOF s@(x:xs) | x == '\n' && hasChanges = Just processed                           | otherwise               = Nothing    where processed  = '\n' : cutOff xs         hasChanges = processed /= s -        cutOff ""                        = ""+        cutOff "" = ""         cutOff z@(y:ys) | y `elem` "\t " = cutOff ys                         | otherwise      = z   clearIndentTillEOF :: String -> Maybe String-clearIndentTillEOF ""                       = Nothing+clearIndentTillEOF "" = Nothing clearIndentTillEOF s@(x:_) | x `elem` "\t " = cutOff s                            | otherwise      = Nothing -  where cutOff ""                      = Just ""-        cutOff z@('\n':_)              = Just z+  where cutOff "" = Just ""+        cutOff ('\r':'\n':xs) = cutOff $ '\n' : xs+        cutOff z@('\n':_) = Just z         cutOff (y:ys) | y `elem` "\t " = cutOff ys                       | otherwise      = Nothing   clearLastQXXLineBreak :: String -> Bool -- Cannot really be empty (matched in `parseQMB`)-clearLastQXXLineBreak ""                        = False-clearLastQXXLineBreak (x:xs) | x `elem` "\t\n " = f xs+clearLastQXXLineBreak "" = False+clearLastQXXLineBreak ('\r':'\n':xs) = clearLastQXXLineBreak $ '\n' : xs+clearLastQXXLineBreak (x:xs) | x `elem` "\t \n" = f xs                              | otherwise        = False -  where f ""                        = True-        f (y:ys) | y `elem` "\t\n " = f ys+  where f "" = True+        f ('\r':'\n':ys) = f $ '\n' : ys+        f (y:ys) | y `elem` "\t \n" = f ys                  | otherwise        = False   clearFirstQXXLineBreak :: String -> String-clearFirstQXXLineBreak ""                          = ""-clearFirstQXXLineBreak s@(x:xs) | x `elem` "\t\n " = cutOff xs+clearFirstQXXLineBreak "" = ""+clearFirstQXXLineBreak ('\r':'\n':xs) = clearFirstQXXLineBreak $ '\n' : xs+clearFirstQXXLineBreak s@(x:xs) | x `elem` "\t \n" = cutOff xs                                 | otherwise        = s-  where cutOff ""                          = ""-        cutOff c@(y:ys) | y `elem` "\t\n " = cutOff ys++  where cutOff "" = ""+        cutOff ('\r':'\n':ys) = cutOff $ '\n' : ys+        cutOff c@(y:ys) | y `elem` "\t \n" = cutOff ys                         | otherwise        = c   clearIndentAtStart :: String -> String-clearIndentAtStart ""                        = ""+clearIndentAtStart "" = "" clearIndentAtStart s@(x:xs) | x `elem` "\t " = clearIndentAtStart xs                             | otherwise      = s @@ -116,8 +117,8 @@   where reify :: String -> TH.Q TH.Exp         reify s = case parseExp s of #if MIN_VERSION_template_haskell(2,8,0)-                       Left  e -> TH.reportError e >> [| mempty |]+                       Left  err  -> TH.reportError err >> [| mempty |] #else-                       Left  e -> TH.report True e >> [| mempty |]+                       Left  err  -> TH.report True err >> [| mempty |] #endif-                       Right e -> return e+                       Right expr -> return expr
src/Text/InterpolatedString/QM/Internal/Parsers/TH.hs view
@@ -1,7 +1,6 @@ -- Fork of: https://github.com/audreyt/interpolatedstring-perl6/blob/63d91a83eb5e48740c87570a8c7fd4668afE6832/src/Text/InterpolatedString/Perl6.hs -- Author of the 'interpolatedstring-perl6' package: Audrey Tang -{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE PackageImports #-} {-# LANGUAGE ViewPatterns #-} @@ -62,17 +61,51 @@      decls = -      map    (uncurry f) $-      map    (\x -> case x of C (_, y, z) -> (y, z) ; D y -> y   ) $-      filter (\x -> case x of C (y, _, _) -> y      ; D _ -> True)+      let+        -- Filtering truthy conditional patterns,+        -- collecting declarative+        -- and applying `f`.+        reducer x acc = case x of+                             C (True, pat, body) -> f pat body : acc+                             D (      pat, body) -> f pat body : acc+                             _                   -> acc -- Skipping -      [ D ( ListP []+      in++      -- All patterns here are prefixed with "a" (`aE`) accumulator.+      --+      -- Means:+      --   ```+      --   D ( consP [varP "x", varP "xs"]+      --     , apps [fE, consE [varE "x", aE], varE "xs"]+      --     )+      --   ```+      -- will be for example:+      --   ```+      --   parseQM a (x:xs) = parseQM (x:a) xs+      --   ```+      foldr reducer [] [++        D ( ListP []           , ListE [apps [conE "Literal", apps [varE "reverse", aE]]]           )        , C ( lineBreaks `elem` [KeepLineBreaks, ReplaceLineBreaksWithSpaces]           , ViewP (varE "clearLastQXXLineBreak") $ conP "True" []           , apps [fE, aE, strE ""]+          )++        -- Cutting '\r' symbols off.+        -- Doing it here (also in '.Helpers' module) to prevent touching+        -- anything inside interpolation block, to make it be just pure+        -- untouched haskell code, with minimal specific details (such as+        -- ability to escape close bracket `\}` to prevent interpolation block+        -- from closing.+      , D ( consP [varP "x", chrP '\r', chrP '\n', varP "xs"]+          , apps [fE, aE, consE [varE "x", chrE '\n', varE "xs"]]+          )+      , D ( consP [chrP '\r', chrP '\n', varP "xs"]+          , apps [fE, aE, consE [chrE '\n', varE "xs"]]           )        , D ( consP [chrP '\\', chrP '\\', varP "xs"]
test/LineBreaks/CRLF/QM/Spec.hs view
@@ -1,4 +1,7 @@ -- This file automatically generated by generate-cr-and-crlf-tests.sh (do not modify!)
+-- WARNING! Do not remove trailing whitespace or tabs, it's part of the test!
+{-# OPTIONS_GHC -fno-warn-tabs #-}
+
 {-# LANGUAGE PackageImports #-}
 {-# LANGUAGE QuasiQuotes #-}
 
@@ -9,7 +12,16 @@ -- local imports
 import "qm-interpolated-string" Text.InterpolatedString.QM (qm)
 
+newtype TestFoo = TestFoo {testBar :: Int} deriving (Show)
+newtype TestFoo2 = TestFoo2 {test1 :: TestFoo} deriving (Show)
 
+testFoo :: TestFoo
+testFoo = TestFoo 42
+
+testFoo2 :: TestFoo2
+testFoo2 = TestFoo2 testFoo
+
+
 spec :: Spec
 spec = do
 
@@ -36,30 +48,94 @@     it "Fourth (escaping interpolation blocks to show them as text)" $
       [qm| {1+2} \{3+4} |] `shouldBe` "3 {3+4}"
 
+  it "Empty string" $ [qm|  |] `shouldBe` ""
+
   it "Type annotation in interpolation block" $
     [qm|{10 :: Float}|] `shouldBe` "10.0"
 
-  it "Escaping interpolation symbols inside interpolation block" $ do
-    [qm|foo {"b{a{r"} baz|]   `shouldBe` "foo b{a{r baz"
-    [qm|foo {"b\}a\}r"} baz|] `shouldBe` "foo b}a}r baz"
+  describe "Escaping" $ do
 
-  it "Example from generated docs" $ [qm| foo {'b':'a':'r':""}
-                                        \ baz |] `shouldBe` "foo bar baz"
+    it "Escaping interpolation symbols inside interpolation block" $ do
+      [qm|foo {"b{a{r"} baz|]   `shouldBe` "foo b{a{r baz"
+      [qm|foo {"b\}a\}r"} baz|] `shouldBe` "foo b}a}r baz"
 
-  it "Escaping backslashes" $ do [qm| foo\bar |]    `shouldBe` "foo\\bar"
-                                 [qm| foo\\bar |]   `shouldBe` "foo\\bar"
-                                 [qm| foo\\\bar |]  `shouldBe` "foo\\\\bar"
-                                 [qm| foo\\\\bar |] `shouldBe` "foo\\\\bar"
+    it "Escaping backslashes" $ do [qm| foo\bar |]    `shouldBe` "foo\\bar"
+                                   [qm| foo\\bar |]   `shouldBe` "foo\\bar"
+                                   [qm| foo\\\bar |]  `shouldBe` "foo\\\\bar"
+                                   [qm| foo\\\\bar |] `shouldBe` "foo\\\\bar"
 
-  it "Empty string" $ [qm|  |] `shouldBe` ""
+    it "Escaping space by slash at EOL after space" $
+      [qm| foo \
+           bar |] `shouldBe` "foo bar"
 
-  it "Escaping space by slash at EOL after space" $
-    [qm| foo \
-         bar |] `shouldBe` "foo bar"
+    it "Escaped spaces at the edges" $ do [qm| foo\ |] `shouldBe` "foo "
+                                          [qm|\ foo |] `shouldBe` " foo"
 
-  it "Escaped spaces at the edges" $ do [qm| foo\ |] `shouldBe` "foo "
-                                        [qm|\ foo |] `shouldBe` " foo"
+    it "Escaping backslash itself when it makes sense" $ do
+      [qm| foo\nbar   |] `shouldBe` "foo\nbar"
+      [qm| foo\\nbar  |] `shouldBe` "foo\\nbar"
+      [qm| foo\tbar   |] `shouldBe` "foo\tbar"
+      [qm| foo\\tbar  |] `shouldBe` "foo\\tbar"
+      [qm| foo\	bar   |] `shouldBe` "foo\tbar"
+      [qm| foo\\	bar |] `shouldBe` "foo\\\tbar"
+      [qm| foo\ bar   |] `shouldBe` "foo bar"
+      [qm| foo\\ bar  |] `shouldBe` "foo\\ bar"
 
+      [qm| foo\
+           bar  |] `shouldBe` "foobar"
+      [qm| foo\\
+           bar  |] `shouldBe` "foo\\bar"
+
+    describe "Escaping inside interpolation blocks" $ do
+
+      it "Line-breaks must be interpreted as just haskell code" $ do
+        [qm| {'\n'}          |] `shouldBe` "\n"
+        [qm| {"foo\nbar"}    |] `shouldBe` "foo\nbar"
+        [qm| {"foo\\nbar"}   |] `shouldBe` "foo\\nbar"
+        [qm| {"foo\\\nbar"}  |] `shouldBe` "foo\\\nbar"
+        [qm| {"foo\\\\nbar"} |] `shouldBe` "foo\\\\nbar"
+
+      it "Escaping for multiline strings" $ do
+        [qm| {"foo\
+              \bar\
+              \baz"} |] `shouldBe` "foobarbaz"
+        [qm| {"foo \
+              \bar\
+              \ baz"} |] `shouldBe` "foo bar baz"
+        [qm| x  \
+             {"foo \
+             \bar\
+             \ baz"}  \
+             y |] `shouldBe` "x  foo bar baz  y"
+
+      it "Escaping of close-bracket '}'" $ do
+        [qm| { testFoo {testBar = 9000\} } |]
+          `shouldBe` show testFoo {testBar = 9000}
+        [qm| foo{ testFoo {testBar = 9000\} }bar |]
+          `shouldBe` "foo" ++ show testFoo {testBar = 9000} ++ "bar"
+        [qm|foo{testFoo2 {test1 = (test1 testFoo2) {testBar = 9000\}\}}bar|]
+          `shouldBe` "foo" ++ show testFoo2 {test1 = TestFoo 9000} ++ "bar"
+        [qm| foo { testFoo2 {
+               test1 = (test1 testFoo2)
+                       { testBar = 9000 \}
+                           \}
+                 } bar |]
+          `shouldBe` "foo " ++ show testFoo2 {test1 = TestFoo 9000} ++ " bar"
+        [qm| {"\}"}   |] `shouldBe` "}"
+        [qm| {"\\\}"} |] `shouldBe` "\\}"
+        [qm| {123}}   |] `shouldBe` "123}"
+
+      it "When interpolation block is escaped\
+         \ everything must be interpreted as usual" $ do
+        [qm| \{ foo\nbar\\baz\} } |] `shouldBe` "{ foo\nbar\\baz\\} }"
+        [qm| \{ foo\
+                bar } |] `shouldBe` "{ foobar }"
+
+      it "Tabs characters in string inside interpolation block" $ do
+        [qm| {"foo\t\tbar" } |] `shouldBe` "foo\t\tbar"
+        [qm| {"foo		bar" } |] `shouldBe` "foo\t\tbar"
+        [qm| {"foo\\t\tbar"} |] `shouldBe` "foo\\t\tbar"
+
   describe "Tabs as indentation" $ do
 
     it "Tabs is only indentation at left side" $ do
@@ -100,6 +176,12 @@ 
   describe "New README examples" $ do
 
+    it "First example" $
+      [qm| Hello,
+           world!
+           Pi is {floor pi}.{floor $ (pi - 3) * 100}… |]
+        `shouldBe` "Hello,world!Pi is 3.14…"
+
     it "Simple usage example" $ do
       let title = "Testing"
           text = "Some testing text"
@@ -118,7 +200,7 @@         `shouldBe`
           "you can escape spaces when you need them"
 
-    it "Indentation and line breaks are ignored" $ 
+    it "Indentation and line breaks are ignored" $
       [qm|
               indentation and li
         ne bre
@@ -141,21 +223,11 @@ 
     it "Interpolation" $ [qm| foo {1+2} |] `shouldBe` "foo 3"
 
-  it "Haddock example" $
+  it "Haddock example" $ do
     [qm| foo {'b':'a':'r':""}
        \ baz |] `shouldBe` "foo bar baz"
-
-  it "Escaping backslash itself when it makes sense" $ do
-    [qm| foo\nbar   |] `shouldBe` "foo\nbar"
-    [qm| foo\\nbar  |] `shouldBe` "foo\\nbar"
-    [qm| foo\tbar   |] `shouldBe` "foo\tbar"
-    [qm| foo\\tbar  |] `shouldBe` "foo\\tbar"
-    [qm| foo\	bar   |] `shouldBe` "foo\tbar"
-    [qm| foo\\	bar |] `shouldBe` "foo\\\tbar"
-    [qm| foo\ bar   |] `shouldBe` "foo bar"
-    [qm| foo\\ bar  |] `shouldBe` "foo\\ bar"
-
-    [qm| foo\
-         bar  |] `shouldBe` "foobar"
-    [qm| foo\\
-         bar  |] `shouldBe` "foo\\bar"
+    [qm| foo
+       \ {'b':'a':'r':""}
+       \ baz |] `shouldBe` "foo bar baz"
+    [qm| foo {'b':'a':'r':""}
+         baz |] `shouldBe` "foo barbaz"
test/LineBreaks/CRLF/QMB/Spec.hs view
@@ -1,4 +1,7 @@ -- This file automatically generated by generate-cr-and-crlf-tests.sh (do not modify!)
+-- WARNING! Do not remove trailing whitespace or tabs, it's part of the test!
+{-# OPTIONS_GHC -fno-warn-tabs #-}
+
 {-# LANGUAGE PackageImports #-}
 {-# LANGUAGE QuasiQuotes #-}
 
@@ -9,7 +12,16 @@ -- local imports
 import "qm-interpolated-string" Text.InterpolatedString.QM (qmb)
 
+newtype TestFoo = TestFoo {testBar :: Int} deriving (Show)
+newtype TestFoo2 = TestFoo2 {test1 :: TestFoo} deriving (Show)
 
+testFoo :: TestFoo
+testFoo = TestFoo 42
+
+testFoo2 :: TestFoo2
+testFoo2 = TestFoo2 testFoo
+
+
 spec :: Spec
 spec = do
 
@@ -57,30 +69,95 @@     it "Fourth (escaping interpolation blocks to show them as text)" $
       [qmb| {1+2} \{3+4} |] `shouldBe` "3 {3+4}"
 
+  it "Empty string" $ [qmb|  |] `shouldBe` ""
+
   it "Type annotation in interpolation block" $
     [qmb|{10 :: Float}|] `shouldBe` "10.0"
 
-  it "Escaping interpolation symbols inside interpolation block" $ do
-    [qmb|foo {"b{a{r"} baz|]   `shouldBe` "foo b{a{r baz"
-    [qmb|foo {"b\}a\}r"} baz|] `shouldBe` "foo b}a}r baz"
+  describe "Escaping" $ do
 
-  it "Example from generated docs" $ [qmb| foo {'b':'a':'r':""}
-                                         \ baz |] `shouldBe` "foo bar\n baz"
+    it "Escaping interpolation symbols inside interpolation block" $ do
+      [qmb|foo {"b{a{r"} baz|]   `shouldBe` "foo b{a{r baz"
+      [qmb|foo {"b\}a\}r"} baz|] `shouldBe` "foo b}a}r baz"
 
-  it "Escaping backslashes" $ do [qmb| foo\bar |]    `shouldBe` "foo\\bar"
-                                 [qmb| foo\\bar |]   `shouldBe` "foo\\bar"
-                                 [qmb| foo\\\bar |]  `shouldBe` "foo\\\\bar"
-                                 [qmb| foo\\\\bar |] `shouldBe` "foo\\\\bar"
+    it "Escaping backslashes" $ do [qmb| foo\bar |]    `shouldBe` "foo\\bar"
+                                   [qmb| foo\\bar |]   `shouldBe` "foo\\bar"
+                                   [qmb| foo\\\bar |]  `shouldBe` "foo\\\\bar"
+                                   [qmb| foo\\\\bar |] `shouldBe` "foo\\\\bar"
 
-  it "Empty string" $ [qmb|  |] `shouldBe` ""
+    it "Escaping space by backslash at EOL after space\
+       \ (line break is cutted off)" $
+      [qmb| foo \
+            bar |] `shouldBe` "foo bar"
 
-  it "Escaping space by backslash at EOL after space (line break is cutted off)" $
-    [qmb| foo \
-          bar |] `shouldBe` "foo bar"
+    it "Escaped spaces at the edges" $ do [qmb| foo\ |] `shouldBe` "foo "
+                                          [qmb|\ foo |] `shouldBe` " foo"
 
-  it "Escaped spaces at the edges" $ do [qmb| foo\ |] `shouldBe` "foo "
-                                        [qmb|\ foo |] `shouldBe` " foo"
+    it "Escaping backslash itself when it makes sense" $ do
+      [qmb| foo\nbar  |] `shouldBe` "foo\nbar"
+      [qmb| foo\\nbar |] `shouldBe` "foo\\nbar"
+      [qmb| foo\tbar  |] `shouldBe` "foo\tbar"
+      [qmb| foo\\tbar |] `shouldBe` "foo\\tbar"
+      [qmb| foo\	bar |] `shouldBe` "foo\tbar"
+      [qmb| foo\\	bar |] `shouldBe` "foo\\\tbar"
+      [qmb| foo\ bar  |] `shouldBe` "foo bar"
+      [qmb| foo\\ bar |] `shouldBe` "foo\\ bar"
 
+      [qmb| foo\
+            bar  |] `shouldBe` "foobar"
+      [qmb| foo\\
+            bar  |] `shouldBe` "foo\\\nbar"
+
+    describe "Escaping inside interpolation blocks" $ do
+
+      it "Line-breaks must be interpreted as just haskell code" $ do
+        [qmb| {'\n'}          |] `shouldBe` "\n"
+        [qmb| {"foo\nbar"}    |] `shouldBe` "foo\nbar"
+        [qmb| {"foo\\nbar"}   |] `shouldBe` "foo\\nbar"
+        [qmb| {"foo\\\nbar"}  |] `shouldBe` "foo\\\nbar"
+        [qmb| {"foo\\\\nbar"} |] `shouldBe` "foo\\\\nbar"
+
+      it "Escaping for multiline strings" $ do
+        [qmb| {"foo\
+               \bar\
+               \baz"} |] `shouldBe` "foobarbaz"
+        [qmb| {"foo \
+               \bar\
+               \ baz"} |] `shouldBe` "foo bar baz"
+        [qmb| x  \
+              {"foo \
+              \bar\
+              \ baz"}  \
+              y |] `shouldBe` "x  foo bar baz  y"
+
+      it "Escaping of close-bracket '}'" $ do
+        [qmb| { testFoo {testBar = 9000\} } |]
+          `shouldBe` show testFoo {testBar = 9000}
+        [qmb| foo{ testFoo {testBar = 9000\} }bar |]
+          `shouldBe` "foo" ++ show testFoo {testBar = 9000} ++ "bar"
+        [qmb|foo{testFoo2 {test1 = (test1 testFoo2) {testBar = 9000\}\}}bar|]
+          `shouldBe` "foo" ++ show testFoo2 {test1 = TestFoo 9000} ++ "bar"
+        [qmb| foo { testFoo2 {
+                test1 = (test1 testFoo2)
+                        { testBar = 9000 \}
+                            \}
+                  } bar |]
+          `shouldBe` "foo " ++ show testFoo2 {test1 = TestFoo 9000} ++ " bar"
+        [qmb| {"\}"}   |] `shouldBe` "}"
+        [qmb| {"\\\}"} |] `shouldBe` "\\}"
+        [qmb| {123}}   |] `shouldBe` "123}"
+
+      it "When interpolation block is escaped\
+         \ everything must be interpreted as usual" $ do
+        [qmb| \{ foo\nbar\\baz\} } |] `shouldBe` "{ foo\nbar\\baz\\} }"
+        [qmb| \{ foo\
+                 bar } |] `shouldBe` "{ foobar }"
+
+      it "Tabs characters in string inside interpolation block" $ do
+        [qmb| {"foo\t\tbar" } |] `shouldBe` "foo\t\tbar"
+        [qmb| {"foo		bar"  } |] `shouldBe` "foo\t\tbar"
+        [qmb| {"foo\\t\tbar"} |] `shouldBe` "foo\\t\tbar"
+
   describe "Tabs as indentation" $ do
 
     it "Tabs is only indentation at left side" $ do
@@ -121,6 +198,12 @@ 
   describe "New README examples" $ do
 
+    it "First example" $
+      [qmb| Hello,
+            world!
+            Pi is {floor pi}.{floor $ (pi - 3) * 100}… |]
+        `shouldBe` "Hello,\nworld!\nPi is 3.14…"
+
     it "Simple usage example" $ do
       let title = "Testing"
           text = "Some testing text"
@@ -133,24 +216,43 @@         `shouldBe`
           "<article>\n<h1>Testing</h1>\n<p>Some testing text</p>\n</article>"
 
+    it "Can escape spaces" $
+      [qmb|   you can escape spaces
+            \ when you need them    |]
+        `shouldBe`
+          "you can escape spaces\n when you need them"
+
+    -- By 'not really' it means that it just copied from `QM` and shows what
+    -- happens with the same input if you use it with this quoter.
+    it "Indentation and line breaks are ignored (not really)" $
+      [qmb|
+              indentation and li
+        ne bre
+         aks are i
+             gno
+           red
+             (not really)
+      |]
+      `shouldBe` "indentation and li\nne bre\naks are i\ngno\nred\n(not really)"
+
+    it "Escaping indentation or line breaks" $
+      [qmb|  \  You can escape indentation or\n
+                line breaks when you need them! \  |]
+        `shouldBe`
+          "  You can escape indentation or\n\nline breaks when you need them!  "
+
+    it "Interpolation blocks can be escaped too" $
+      [qmb| Interpolation blocks can be escaped too: {1+2} \{3+4} |]
+        `shouldBe`
+          "Interpolation blocks can be escaped too: 3 {3+4}"
+
     it "Interpolation" $ [qmb| foo {1+2} |] `shouldBe` "foo 3"
 
-  it "Haddock example" $
+  it "Haddock example" $ do
+    [qmb| foo {'b':'a':'r':""}
+          baz |] `shouldBe` "foo bar\nbaz"
     [qmb| foo
           {'b':'a':'r':""}
           baz |] `shouldBe` "foo\nbar\nbaz"
-
-  it "Escaping backslash itself when it makes sense" $ do
-    [qmb| foo\nbar  |] `shouldBe` "foo\nbar"
-    [qmb| foo\\nbar |] `shouldBe` "foo\\nbar"
-    [qmb| foo\tbar  |] `shouldBe` "foo\tbar"
-    [qmb| foo\\tbar |] `shouldBe` "foo\\tbar"
-    [qmb| foo\	bar |] `shouldBe` "foo\tbar"
-    [qmb| foo\\	bar |] `shouldBe` "foo\\\tbar"
-    [qmb| foo\ bar  |] `shouldBe` "foo bar"
-    [qmb| foo\\ bar |] `shouldBe` "foo\\ bar"
-
-    [qmb| foo\
-          bar  |] `shouldBe` "foobar"
-    [qmb| foo\\
-          bar  |] `shouldBe` "foo\\\nbar"
+    [qmb| foo {'b':'a':'r':""}
+        \ baz |] `shouldBe` "foo bar\n baz"
test/LineBreaks/CRLF/QMS/Spec.hs view
@@ -1,4 +1,7 @@ -- This file automatically generated by generate-cr-and-crlf-tests.sh (do not modify!)
+-- WARNING! Do not remove trailing whitespace or tabs, it's part of the test!
+{-# OPTIONS_GHC -fno-warn-tabs #-}
+
 {-# LANGUAGE PackageImports #-}
 {-# LANGUAGE QuasiQuotes #-}
 
@@ -9,7 +12,16 @@ -- local imports
 import "qm-interpolated-string" Text.InterpolatedString.QM (qms)
 
+newtype TestFoo = TestFoo {testBar :: Int} deriving (Show)
+newtype TestFoo2 = TestFoo2 {test1 :: TestFoo} deriving (Show)
 
+testFoo :: TestFoo
+testFoo = TestFoo 42
+
+testFoo2 :: TestFoo2
+testFoo2 = TestFoo2 testFoo
+
+
 spec :: Spec
 spec = do
 
@@ -57,30 +69,95 @@     it "Fourth (escaping interpolation blocks to show them as text)" $
       [qms| {1+2} \{3+4} |] `shouldBe` "3 {3+4}"
 
+  it "Empty string" $ [qms|  |] `shouldBe` ""
+
   it "Type annotation in interpolation block" $
     [qms|{10 :: Float}|] `shouldBe` "10.0"
 
-  it "Escaping interpolation symbols inside interpolation block" $ do
-    [qms|foo {"b{a{r"} baz|]   `shouldBe` "foo b{a{r baz"
-    [qms|foo {"b\}a\}r"} baz|] `shouldBe` "foo b}a}r baz"
+  describe "Escaping" $ do
 
-  it "Example from generated docs" $ [qms| foo {'b':'a':'r':""}
-                                         \ baz |] `shouldBe` "foo bar  baz"
+    it "Escaping interpolation symbols inside interpolation block" $ do
+      [qms|foo {"b{a{r"} baz|]   `shouldBe` "foo b{a{r baz"
+      [qms|foo {"b\}a\}r"} baz|] `shouldBe` "foo b}a}r baz"
 
-  it "Escaping backslashes" $ do [qms| foo\bar |]    `shouldBe` "foo\\bar"
-                                 [qms| foo\\bar |]   `shouldBe` "foo\\bar"
-                                 [qms| foo\\\bar |]  `shouldBe` "foo\\\\bar"
-                                 [qms| foo\\\\bar |] `shouldBe` "foo\\\\bar"
+    it "Escaping backslashes" $ do [qms| foo\bar |]    `shouldBe` "foo\\bar"
+                                   [qms| foo\\bar |]   `shouldBe` "foo\\bar"
+                                   [qms| foo\\\bar |]  `shouldBe` "foo\\\\bar"
+                                   [qms| foo\\\\bar |] `shouldBe` "foo\\\\bar"
 
-  it "Empty string" $ [qms|  |] `shouldBe` ""
+    it "Escaping space by backslash at EOL after space\
+       \ (line break is cutted off)" $
+      [qms| foo \
+            bar |] `shouldBe` "foo bar"
 
-  it "Escaping space by backslash at EOL after space (line break is cutted off)" $
-    [qms| foo \
-          bar |] `shouldBe` "foo bar"
+    it "Escaped spaces at the edges" $ do [qms| foo\ |] `shouldBe` "foo "
+                                          [qms|\ foo |] `shouldBe` " foo"
 
-  it "Escaped spaces at the edges" $ do [qms| foo\ |] `shouldBe` "foo "
-                                        [qms|\ foo |] `shouldBe` " foo"
+    it "Escaping backslash itself when it makes sense" $ do
+      [qms| foo\nbar  |] `shouldBe` "foo\nbar"
+      [qms| foo\\nbar |] `shouldBe` "foo\\nbar"
+      [qms| foo\tbar  |] `shouldBe` "foo\tbar"
+      [qms| foo\\tbar |] `shouldBe` "foo\\tbar"
+      [qms| foo\	bar |] `shouldBe` "foo\tbar"
+      [qms| foo\\	bar |] `shouldBe` "foo\\\tbar"
+      [qms| foo\ bar  |] `shouldBe` "foo bar"
+      [qms| foo\\ bar |] `shouldBe` "foo\\ bar"
 
+      [qms| foo\
+            bar  |] `shouldBe` "foobar"
+      [qms| foo\\
+            bar  |] `shouldBe` "foo\\ bar"
+
+    describe "Escaping inside interpolation blocks" $ do
+
+      it "Line-breaks must be interpreted as just haskell code" $ do
+        [qms| {'\n'}          |] `shouldBe` "\n"
+        [qms| {"foo\nbar"}    |] `shouldBe` "foo\nbar"
+        [qms| {"foo\\nbar"}   |] `shouldBe` "foo\\nbar"
+        [qms| {"foo\\\nbar"}  |] `shouldBe` "foo\\\nbar"
+        [qms| {"foo\\\\nbar"} |] `shouldBe` "foo\\\\nbar"
+
+      it "Escaping for multiline strings" $ do
+        [qms| {"foo\
+               \bar\
+               \baz"} |] `shouldBe` "foobarbaz"
+        [qms| {"foo \
+               \bar\
+               \ baz"} |] `shouldBe` "foo bar baz"
+        [qms| x  \
+              {"foo \
+              \bar\
+              \ baz"}  \
+              y |] `shouldBe` "x  foo bar baz  y"
+
+      it "Escaping of close-bracket '}'" $ do
+        [qms| { testFoo {testBar = 9000\} } |]
+          `shouldBe` show testFoo {testBar = 9000}
+        [qms| foo{ testFoo {testBar = 9000\} }bar |]
+          `shouldBe` "foo" ++ show testFoo {testBar = 9000} ++ "bar"
+        [qms|foo{testFoo2 {test1 = (test1 testFoo2) {testBar = 9000\}\}}bar|]
+          `shouldBe` "foo" ++ show testFoo2 {test1 = TestFoo 9000} ++ "bar"
+        [qms| foo { testFoo2 {
+                test1 = (test1 testFoo2)
+                        { testBar = 9000 \}
+                            \}
+                  } bar |]
+          `shouldBe` "foo " ++ show testFoo2 {test1 = TestFoo 9000} ++ " bar"
+        [qms| {"\}"}   |] `shouldBe` "}"
+        [qms| {"\\\}"} |] `shouldBe` "\\}"
+        [qms| {123}}   |] `shouldBe` "123}"
+
+      it "When interpolation block is escaped\
+         \ everything must be interpreted as usual" $ do
+        [qms| \{ foo\nbar\\baz\} } |] `shouldBe` "{ foo\nbar\\baz\\} }"
+        [qms| \{ foo\
+                 bar } |] `shouldBe` "{ foobar }"
+
+      it "Tabs characters in string inside interpolation block" $ do
+        [qms| {"foo\t\tbar" } |] `shouldBe` "foo\t\tbar"
+        [qms| {"foo		bar"  } |] `shouldBe` "foo\t\tbar"
+        [qms| {"foo\\t\tbar"} |] `shouldBe` "foo\\t\tbar"
+
   describe "Tabs as indentation" $ do
 
     it "Tabs is only indentation at left side" $ do
@@ -139,24 +216,44 @@         `shouldBe`
           "<article> <h1>Testing</h1> <p>Some testing text</p> </article>"
 
+    it "Can escape spaces" $
+      [qms|   you can escape spaces
+            \ when you need them    |]
+        `shouldBe`
+          "you can escape spaces  when you need them"
+
+    -- By 'not really' it means that it just copied from `QM` and shows what
+    -- happens with the same input if you use it with this quoter.
+    it "Indentation and line breaks are ignored (not really)" $
+      [qms|
+              indentation and li
+        ne bre
+         aks are i
+             gno
+           red
+             (not really)
+      |]
+      `shouldBe` "indentation and li ne bre aks are i gno red (not really)"
+
+    it "Escaping indentation or line breaks" $
+      [qms|  \  You can escape indentation or\n
+                line breaks when you need them! \  |]
+        `shouldBe`
+          "  You can escape indentation or\n line breaks when you need them!  "
+
+    it "Interpolation blocks can be escaped too" $
+      [qms| Interpolation blocks can be escaped too: {1+2} \{3+4} |]
+        `shouldBe`
+          "Interpolation blocks can be escaped too: 3 {3+4}"
+
     it "Interpolation" $ [qms| foo {1+2} |] `shouldBe` "foo 3"
 
-  it "Haddock example" $
+  it "Haddock example" $ do
+    [qms| foo {'b':'a':'r':""}
+          baz |] `shouldBe` "foo bar baz"
     [qms| foo
           {'b':'a':'r':""}
           baz |] `shouldBe` "foo bar baz"
-
-  it "Escaping backslash itself when it makes sense" $ do
-    [qms| foo\nbar  |] `shouldBe` "foo\nbar"
-    [qms| foo\\nbar |] `shouldBe` "foo\\nbar"
-    [qms| foo\tbar  |] `shouldBe` "foo\tbar"
-    [qms| foo\\tbar |] `shouldBe` "foo\\tbar"
-    [qms| foo\	bar |] `shouldBe` "foo\tbar"
-    [qms| foo\\	bar |] `shouldBe` "foo\\\tbar"
-    [qms| foo\ bar  |] `shouldBe` "foo bar"
-    [qms| foo\\ bar |] `shouldBe` "foo\\ bar"
-
-    [qms| foo\
-          bar  |] `shouldBe` "foobar"
-    [qms| foo\\
-          bar  |] `shouldBe` "foo\\ bar"
+    -- Double-space with escaping
+    [qms| foo {'b':'a':'r':""}
+        \ baz |] `shouldBe` "foo bar  baz"
test/LineBreaks/CRLF/QN/Spec.hs view
@@ -1,4 +1,7 @@ -- This file automatically generated by generate-cr-and-crlf-tests.sh (do not modify!)
+-- WARNING! Do not remove trailing whitespace or tabs, it's part of the test!
+{-# OPTIONS_GHC -fno-warn-tabs #-}
+
 {-# LANGUAGE PackageImports #-}
 {-# LANGUAGE QuasiQuotes #-}
 
@@ -36,34 +39,100 @@     it "Fourth (escaping interpolation blocks to show them as text)" $
       [qn| {1+2} \{3+4} |] `shouldBe` "{1+2} \\{3+4}"
 
-    it "Example of `qn` QuasiQuoter" $
-      [qn| foo {1+2} |] `shouldBe` "foo {1+2}"
+  it "Empty string" $ [qn|  |] `shouldBe` ""
 
   it "Type annotation in interpolation block" $
     [qn|{10 :: Float}|] `shouldBe` "{10 :: Float}"
 
-  it "Escaping interpolation symbols inside interpolation block" $ do
-    [qn|foo {"b{a{r"} baz|] `shouldBe` "foo {\"b{a{r\"} baz"
-    [qn|foo {"b\}a\}r"} baz|] `shouldBe` "foo {\"b\\}a\\}r\"} baz"
+  describe "Escaping" $ do
 
-  it "Example from generated docs" $
-    [qn| foo {'b':'a':'r':""}
-       \ baz |] `shouldBe` "foo {'b':'a':'r':\"\"} baz"
+    it "Escaping interpolation symbols inside interpolation block" $ do
+      [qn|foo {"b{a{r"} baz|] `shouldBe` "foo {\"b{a{r\"} baz"
+      [qn|foo {"b\}a\}r"} baz|] `shouldBe` "foo {\"b\\}a\\}r\"} baz"
 
-  it "Escaping backslashes" $ do [qn| foo\bar |]    `shouldBe` "foo\\bar"
-                                 [qn| foo\\bar |]   `shouldBe` "foo\\bar"
-                                 [qn| foo\\\bar |]  `shouldBe` "foo\\\\bar"
-                                 [qn| foo\\\\bar |] `shouldBe` "foo\\\\bar"
+    it "Escaping backslashes" $ do [qn| foo\bar |]    `shouldBe` "foo\\bar"
+                                   [qn| foo\\bar |]   `shouldBe` "foo\\bar"
+                                   [qn| foo\\\bar |]  `shouldBe` "foo\\\\bar"
+                                   [qn| foo\\\\bar |] `shouldBe` "foo\\\\bar"
 
-  it "Empty string" $ [qn|  |] `shouldBe` ""
+    it "Escaping space by slash at EOL after space" $
+      [qn| foo \
+           bar |] `shouldBe` "foo bar"
 
-  it "Escaping space by slash at EOL after space" $
-    [qn| foo \
-         bar |] `shouldBe` "foo bar"
+    it "Escaped spaces at the edges" $ do [qn| foo\ |] `shouldBe` "foo "
+                                          [qn|\ foo |] `shouldBe` " foo"
 
-  it "Escaped spaces at the edges" $ do [qn| foo\ |] `shouldBe` "foo "
-                                        [qn|\ foo |] `shouldBe` " foo"
+    it "Escaping backslash itself when it makes sense" $ do
+      [qn| foo\nbar   |] `shouldBe` "foo\nbar"
+      [qn| foo\\nbar  |] `shouldBe` "foo\\nbar"
+      [qn| foo\tbar   |] `shouldBe` "foo\tbar"
+      [qn| foo\\tbar  |] `shouldBe` "foo\\tbar"
+      [qn| foo\	bar   |] `shouldBe` "foo\tbar"
+      [qn| foo\\	bar |] `shouldBe` "foo\\\tbar"
+      [qn| foo\ bar   |] `shouldBe` "foo bar"
+      [qn| foo\\ bar  |] `shouldBe` "foo\\ bar"
 
+      [qn| foo\
+           bar  |] `shouldBe` "foobar"
+      [qn| foo\\
+           bar  |] `shouldBe` "foo\\bar"
+
+    -- By 'not really' it means we just shows here what happens with examples
+    -- for QM when we use them with QN quoter.
+    describe "Escaping inside interpolation blocks (not really!)" $ do
+
+      it "Line-breaks must be interpreted as just haskell code\
+         \ (not really!)" $ do
+        [qn| {'\n'}          |] `shouldBe` "{'\n'}"
+        [qn| {"foo\nbar"}    |] `shouldBe` "{\"foo\nbar\"}"
+        [qn| {"foo\\nbar"}   |] `shouldBe` "{\"foo\\nbar\"}"
+        [qn| {"foo\\\nbar"}  |] `shouldBe` "{\"foo\\\nbar\"}"
+        [qn| {"foo\\\\nbar"} |] `shouldBe` "{\"foo\\\\nbar\"}"
+
+      it "Escaping for multiline strings" $ do
+        [qn| {"foo\
+              \bar\
+              \baz"} |] `shouldBe` "{\"foo\\bar\\baz\"}"
+        [qn| {"foo \
+              \bar\
+              \ baz"} |] `shouldBe` "{\"foo \\bar baz\"}"
+        [qn| x  \
+             {"foo \
+             \bar\
+             \ baz"}  \
+             y |] `shouldBe` "x  {\"foo \\bar baz\"}  y"
+
+      it "Escaping of close-bracket '}'" $ do
+        [qn| { testFoo {testBar = 9000\} } |]
+          `shouldBe` "{ testFoo {testBar = 9000\\} }"
+        [qn| foo{ testFoo {testBar = 9000\} }bar |]
+          `shouldBe` "foo{ testFoo {testBar = 9000\\} }bar"
+        [qn|foo{testFoo2 {test1 = (test1 testFoo2) {testBar = 9000\}\}}bar|]
+          `shouldBe`
+            "foo{testFoo2 {test1 = (test1 testFoo2) {testBar = 9000\\}\\}}bar"
+        [qn| foo { testFoo2 {
+               test1 = (test1 testFoo2)
+                       { testBar = 9000 \}
+                           \}
+                 } bar |]
+          `shouldBe` "foo { testFoo2 {test1 = (test1 testFoo2)\
+                     \{ testBar = 9000 \\}\\}} bar"
+        [qn| {"\}"}   |] `shouldBe` "{\"\\}\"}"
+        [qn| {"\\\}"} |] `shouldBe` "{\"\\\\}\"}"
+        [qn| {123}}   |] `shouldBe` "{123}}"
+
+      it "When interpolation block is escaped\
+         \ everything must be interpreted as usual (not really)" $ do
+        [qn| \{ foo\nbar\\baz\} } |] `shouldBe` "\\{ foo\nbar\\baz\\} }"
+        [qn| \{ foo\
+                bar } |] `shouldBe` "\\{ foobar }"
+
+      it "Tabs characters in string inside interpolation block\
+         \ (not really!)" $ do
+        [qn| {"foo\t\tbar" } |] `shouldBe` "{\"foo\t\tbar\" }"
+        [qn| {"foo		bar" } |] `shouldBe` "{\"foo\t\tbar\" }"
+        [qn| {"foo\\t\tbar"} |] `shouldBe` "{\"foo\\t\tbar\"}"
+
   describe "Tabs as indentation" $ do
 
     it "Tabs is only indentation at left side" $ do
@@ -104,7 +173,13 @@ 
   describe "New README examples" $ do
 
-    it "Simple usage example" $ do
+    it "First example" $
+      [qn| Hello,
+           world!
+           Pi is {floor pi}.{floor $ (pi - 3) * 100}… |]
+        `shouldBe` "Hello,world!Pi is {floor pi}.{floor $ (pi - 3) * 100}…"
+
+    it "Simple usage example" $
       [qn|
         <article>
           <h1>{title}</h1>
@@ -112,23 +187,40 @@         </article>
       |] `shouldBe` "<article><h1>{title}</h1><p>{text}</p></article>"
 
+    it "Can escape spaces" $
+      [qn|   you can escape spaces
+           \ when you need them    |]
+        `shouldBe`
+          "you can escape spaces when you need them"
+
+    it "Indentation and line breaks are ignored" $
+      [qn|
+              indentation and li
+        ne bre
+         aks are i
+             gno
+           red
+      |]
+      `shouldBe` "indentation and line breaks are ignored"
+
+    it "Escaping indentation or line breaks" $
+      [qn|  \  You can escape indentation or\n
+               line breaks when you need them! \  |]
+        `shouldBe`
+          "  You can escape indentation or\nline breaks when you need them!  "
+
+    it "Interpolation blocks can be escaped too" $
+      [qn| Interpolation blocks can be escaped too: {1+2} \{3+4} |]
+        `shouldBe`
+          "Interpolation blocks can be escaped too: {1+2} \\{3+4}"
+
     it "Interpolation" $ [qn| foo {1+2} |] `shouldBe` "foo {1+2}"
 
-  it "Haddock example" $
+  it "Haddock example" $ do
     [qn| foo {'b':'a':'r':""}
        \ baz |] `shouldBe` "foo {'b':'a':'r':\"\"} baz"
-
-  it "Escaping backslash itself when it makes sense" $ do
-    [qn| foo\nbar   |] `shouldBe` "foo\nbar"
-    [qn| foo\\nbar  |] `shouldBe` "foo\\nbar"
-    [qn| foo\tbar   |] `shouldBe` "foo\tbar"
-    [qn| foo\\tbar  |] `shouldBe` "foo\\tbar"
-    [qn| foo\	bar   |] `shouldBe` "foo\tbar"
-    [qn| foo\\	bar |] `shouldBe` "foo\\\tbar"
-    [qn| foo\ bar   |] `shouldBe` "foo bar"
-    [qn| foo\\ bar  |] `shouldBe` "foo\\ bar"
-
-    [qn| foo\
-         bar  |] `shouldBe` "foobar"
-    [qn| foo\\
-         bar  |] `shouldBe` "foo\\bar"
+    [qn| foo
+       \ {'b':'a':'r':""}
+       \ baz |] `shouldBe` "foo {'b':'a':'r':\"\"} baz"
+    [qn| foo {'b':'a':'r':""}
+         baz |] `shouldBe` "foo {'b':'a':'r':\"\"}baz"
test/LineBreaks/CRLF/QNB/Spec.hs view
@@ -1,4 +1,7 @@ -- This file automatically generated by generate-cr-and-crlf-tests.sh (do not modify!)
+-- WARNING! Do not remove trailing whitespace or tabs, it's part of the test!
+{-# OPTIONS_GHC -fno-warn-tabs #-}
+
 {-# LANGUAGE PackageImports #-}
 {-# LANGUAGE QuasiQuotes #-}
 
@@ -57,34 +60,101 @@     it "Fourth (escaping interpolation blocks to show them as text)" $
       [qnb| {1+2} \{3+4} |] `shouldBe` "{1+2} \\{3+4}"
 
-    it "Example of `qnb` QuasiQuoter" $
-      [qnb| foo {1+2} |] `shouldBe` "foo {1+2}"
+  it "Empty string" $ [qnb|  |] `shouldBe` ""
 
   it "Type annotation in interpolation block" $
     [qnb|{10 :: Float}|] `shouldBe` "{10 :: Float}"
 
-  it "Escaping interpolation symbols inside interpolation block" $ do
-    [qnb|foo {"b{a{r"} baz|] `shouldBe` "foo {\"b{a{r\"} baz"
-    [qnb|foo {"b\}a\}r"} baz|] `shouldBe` "foo {\"b\\}a\\}r\"} baz"
+  describe "Escaping" $ do
 
-  it "Example from generated docs (double-space)" $
-    [qnb| foo {'b':'a':'r':""}
-        \ baz |] `shouldBe` "foo {'b':'a':'r':\"\"}\n baz"
+    it "Escaping interpolation symbols inside interpolation block" $ do
+      [qnb|foo {"b{a{r"} baz|] `shouldBe` "foo {\"b{a{r\"} baz"
+      [qnb|foo {"b\}a\}r"} baz|] `shouldBe` "foo {\"b\\}a\\}r\"} baz"
 
-  it "Escaping backslashes" $ do [qnb| foo\bar |]    `shouldBe` "foo\\bar"
-                                 [qnb| foo\\bar |]   `shouldBe` "foo\\bar"
-                                 [qnb| foo\\\bar |]  `shouldBe` "foo\\\\bar"
-                                 [qnb| foo\\\\bar |] `shouldBe` "foo\\\\bar"
+    it "Escaping backslashes" $ do [qnb| foo\bar |]    `shouldBe` "foo\\bar"
+                                   [qnb| foo\\bar |]   `shouldBe` "foo\\bar"
+                                   [qnb| foo\\\bar |]  `shouldBe` "foo\\\\bar"
+                                   [qnb| foo\\\\bar |] `shouldBe` "foo\\\\bar"
 
-  it "Empty string" $ [qnb|  |] `shouldBe` ""
+    it "Escaping space by backslash at EOL after space\
+       \ (line break is cutted off)" $
+      [qnb| foo \
+            bar |] `shouldBe` "foo bar"
 
-  it "Escaping space by backslash at EOL after space (line break is cutted off)" $
-    [qnb| foo \
-          bar |] `shouldBe` "foo bar"
+    it "Escaped spaces at the edges" $ do [qnb| foo\ |] `shouldBe` "foo "
+                                          [qnb|\ foo |] `shouldBe` " foo"
 
-  it "Escaped spaces at the edges" $ do [qnb| foo\ |] `shouldBe` "foo "
-                                        [qnb|\ foo |] `shouldBe` " foo"
+    it "Escaping backslash itself when it makes sense" $ do
+      [qnb| foo\nbar  |] `shouldBe` "foo\nbar"
+      [qnb| foo\\nbar |] `shouldBe` "foo\\nbar"
+      [qnb| foo\tbar  |] `shouldBe` "foo\tbar"
+      [qnb| foo\\tbar |] `shouldBe` "foo\\tbar"
+      [qnb| foo\	bar |] `shouldBe` "foo\tbar"
+      [qnb| foo\\	bar |] `shouldBe` "foo\\\tbar"
+      [qnb| foo\ bar  |] `shouldBe` "foo bar"
+      [qnb| foo\\ bar |] `shouldBe` "foo\\ bar"
 
+      [qnb| foo\
+            bar  |] `shouldBe` "foobar"
+      [qnb| foo\\
+            bar  |] `shouldBe` "foo\\\nbar"
+
+    -- By 'not really' it means we just shows here what happens with examples
+    -- for QMB when we use them with QNB quoter.
+    describe "Escaping inside interpolation blocks (not really!)" $ do
+
+      it "Line-breaks must be interpreted as just haskell code\
+         \ (not really!)" $ do
+        [qnb| {'\n'}          |] `shouldBe` "{'\n'}"
+        [qnb| {"foo\nbar"}    |] `shouldBe` "{\"foo\nbar\"}"
+        [qnb| {"foo\\nbar"}   |] `shouldBe` "{\"foo\\nbar\"}"
+        [qnb| {"foo\\\nbar"}  |] `shouldBe` "{\"foo\\\nbar\"}"
+        [qnb| {"foo\\\\nbar"} |] `shouldBe` "{\"foo\\\\nbar\"}"
+
+      it "Escaping for multiline strings" $ do
+        [qnb| {"foo\
+               \bar\
+               \baz"} |] `shouldBe` "{\"foo\\bar\\baz\"}"
+        [qnb| {"foo \
+               \bar\
+               \ baz"} |] `shouldBe` "{\"foo \\bar baz\"}"
+        [qnb| x  \
+              {"foo \
+              \bar\
+              \ baz"}  \
+              y |] `shouldBe` "x  {\"foo \\bar baz\"}  y"
+
+      it "Escaping of close-bracket '}'" $ do
+        [qnb| { testFoo {testBar = 9000\} } |]
+          `shouldBe` "{ testFoo {testBar = 9000\\} }"
+        [qnb| foo{ testFoo {testBar = 9000\} }bar |]
+          `shouldBe` "foo{ testFoo {testBar = 9000\\} }bar"
+        [qnb|foo{testFoo2 {test1 = (test1 testFoo2) {testBar = 9000\}\}}bar|]
+          `shouldBe`
+            "foo{testFoo2 {test1 = (test1 testFoo2) {testBar = 9000\\}\\}}bar"
+        [qnb| foo { testFoo2 {
+                test1 = (test1 testFoo2)
+                        { testBar = 9000 \}
+                            \}
+                  } bar |]
+          `shouldBe` "foo { testFoo2 {\ntest1 = (test1 testFoo2)\n\
+                     \{ testBar = 9000 \\}\n\\}\n} bar"
+        [qnb| {"\}"}   |] `shouldBe` "{\"\\}\"}"
+        [qnb| {"\\\}"} |] `shouldBe` "{\"\\\\}\"}"
+        [qnb| {123}}   |] `shouldBe` "{123}}"
+
+      it "When interpolation block is escaped\
+         \ everything must be interpreted as usual (not really)" $ do
+        [qnb| \{ foo\nbar\\baz\} } |] `shouldBe` "\\{ foo\nbar\\baz\\} }"
+        [qnb| \{ foo\
+                 bar } |] `shouldBe` "\\{ foobar }"
+
+      it "Tabs characters in string inside interpolation block\
+         \ (not really)" $ do
+        [qnb| {"foo\t\tbar" } |] `shouldBe` "{\"foo\t\tbar\" }"
+        [qnb| {"foo		bar"  } |] `shouldBe` "{\"foo\t\tbar\"  }"
+        [qnb| {"foo\\t\tbar"} |] `shouldBe` "{\"foo\\t\tbar\"}"
+
   describe "Tabs as indentation" $ do
 
     it "Tabs is only indentation at left side" $ do
@@ -125,7 +195,13 @@ 
   describe "New README examples" $ do
 
-    it "Simple usage example" $ do
+    it "First example" $
+      [qnb| Hello,
+            world!
+            Pi is {floor pi}.{floor $ (pi - 3) * 100}… |]
+        `shouldBe` "Hello,\nworld!\nPi is {floor pi}.{floor $ (pi - 3) * 100}…"
+
+    it "Simple usage example" $
       [qnb|
         <article>
           <h1>{title}</h1>
@@ -135,24 +211,43 @@         `shouldBe`
           "<article>\n<h1>{title}</h1>\n<p>{text}</p>\n</article>"
 
+    it "Can escape spaces" $
+      [qnb|   you can escape spaces
+            \ when you need them    |]
+        `shouldBe`
+          "you can escape spaces\n when you need them"
+
+    -- By 'not really' it means that it just copied from `QM` and shows what
+    -- happens with the same input if you use it with this quoter.
+    it "Indentation and line breaks are ignored (not really)" $
+      [qnb|
+              indentation and li
+        ne bre
+         aks are i
+             gno
+           red
+             (not really)
+      |]
+      `shouldBe` "indentation and li\nne bre\naks are i\ngno\nred\n(not really)"
+
+    it "Escaping indentation or line breaks" $
+      [qnb|  \  You can escape indentation or\n
+                line breaks when you need them! \  |]
+        `shouldBe`
+          "  You can escape indentation or\n\nline breaks when you need them!  "
+
+    it "Interpolation blocks can be escaped too" $
+      [qnb| Interpolation blocks can be escaped too: {1+2} \{3+4} |]
+        `shouldBe`
+          "Interpolation blocks can be escaped too: {1+2} \\{3+4}"
+
     it "Interpolation" $ [qnb| foo {1+2} |] `shouldBe` "foo {1+2}"
 
-  it "Haddock example" $
+  it "Haddock example" $ do
+    [qnb| foo {'b':'a':'r':""}
+          baz |] `shouldBe` "foo {'b':'a':'r':\"\"}\nbaz"
     [qnb| foo
           {'b':'a':'r':""}
           baz |] `shouldBe` "foo\n{'b':'a':'r':\"\"}\nbaz"
-
-  it "Escaping backslash itself when it makes sense" $ do
-    [qnb| foo\nbar  |] `shouldBe` "foo\nbar"
-    [qnb| foo\\nbar |] `shouldBe` "foo\\nbar"
-    [qnb| foo\tbar  |] `shouldBe` "foo\tbar"
-    [qnb| foo\\tbar |] `shouldBe` "foo\\tbar"
-    [qnb| foo\	bar |] `shouldBe` "foo\tbar"
-    [qnb| foo\\	bar |] `shouldBe` "foo\\\tbar"
-    [qnb| foo\ bar  |] `shouldBe` "foo bar"
-    [qnb| foo\\ bar |] `shouldBe` "foo\\ bar"
-
-    [qnb| foo\
-          bar  |] `shouldBe` "foobar"
-    [qnb| foo\\
-          bar  |] `shouldBe` "foo\\\nbar"
+    [qnb| foo {'b':'a':'r':""}
+        \ baz |] `shouldBe` "foo {'b':'a':'r':\"\"}\n baz"
test/LineBreaks/CRLF/QNS/Spec.hs view
@@ -1,4 +1,7 @@ -- This file automatically generated by generate-cr-and-crlf-tests.sh (do not modify!)
+-- WARNING! Do not remove trailing whitespace or tabs, it's part of the test!
+{-# OPTIONS_GHC -fno-warn-tabs #-}
+
 {-# LANGUAGE PackageImports #-}
 {-# LANGUAGE QuasiQuotes #-}
 
@@ -57,34 +60,101 @@     it "Fourth (escaping interpolation blocks to show them as text)" $
       [qns| {1+2} \{3+4} |] `shouldBe` "{1+2} \\{3+4}"
 
-    it "Example of `qns` QuasiQuoter" $
-      [qns| foo {1+2} |] `shouldBe` "foo {1+2}"
+  it "Empty string" $ [qns|  |] `shouldBe` ""
 
   it "Type annotation in interpolation block" $
     [qns|{10 :: Float}|] `shouldBe` "{10 :: Float}"
 
-  it "Escaping interpolation symbols inside interpolation block" $ do
-    [qns|foo {"b{a{r"} baz|] `shouldBe` "foo {\"b{a{r\"} baz"
-    [qns|foo {"b\}a\}r"} baz|] `shouldBe` "foo {\"b\\}a\\}r\"} baz"
+  describe "Escaping" $ do
 
-  it "Example from generated docs (double-space)" $
-    [qns| foo {'b':'a':'r':""}
-        \ baz |] `shouldBe` "foo {'b':'a':'r':\"\"}  baz"
+    it "Escaping interpolation symbols inside interpolation block" $ do
+      [qns|foo {"b{a{r"} baz|] `shouldBe` "foo {\"b{a{r\"} baz"
+      [qns|foo {"b\}a\}r"} baz|] `shouldBe` "foo {\"b\\}a\\}r\"} baz"
 
-  it "Escaping backslashes" $ do [qns| foo\bar |]    `shouldBe` "foo\\bar"
-                                 [qns| foo\\bar |]   `shouldBe` "foo\\bar"
-                                 [qns| foo\\\bar |]  `shouldBe` "foo\\\\bar"
-                                 [qns| foo\\\\bar |] `shouldBe` "foo\\\\bar"
+    it "Escaping backslashes" $ do [qns| foo\bar |]    `shouldBe` "foo\\bar"
+                                   [qns| foo\\bar |]   `shouldBe` "foo\\bar"
+                                   [qns| foo\\\bar |]  `shouldBe` "foo\\\\bar"
+                                   [qns| foo\\\\bar |] `shouldBe` "foo\\\\bar"
 
-  it "Empty string" $ [qns|  |] `shouldBe` ""
+    it "Escaping space by backslash at EOL after space\
+       \ (line break is cutted off)" $
+      [qns| foo \
+            bar |] `shouldBe` "foo bar"
 
-  it "Escaping space by backslash at EOL after space (line break is cutted off)" $
-    [qns| foo \
-          bar |] `shouldBe` "foo bar"
+    it "Escaped spaces at the edges" $ do [qns| foo\ |] `shouldBe` "foo "
+                                          [qns|\ foo |] `shouldBe` " foo"
 
-  it "Escaped spaces at the edges" $ do [qns| foo\ |] `shouldBe` "foo "
-                                        [qns|\ foo |] `shouldBe` " foo"
+    it "Escaping backslash itself when it makes sense" $ do
+      [qns| foo\nbar  |] `shouldBe` "foo\nbar"
+      [qns| foo\\nbar |] `shouldBe` "foo\\nbar"
+      [qns| foo\tbar  |] `shouldBe` "foo\tbar"
+      [qns| foo\\tbar |] `shouldBe` "foo\\tbar"
+      [qns| foo\	bar |] `shouldBe` "foo\tbar"
+      [qns| foo\\	bar |] `shouldBe` "foo\\\tbar"
+      [qns| foo\ bar  |] `shouldBe` "foo bar"
+      [qns| foo\\ bar |] `shouldBe` "foo\\ bar"
 
+      [qns| foo\
+            bar  |] `shouldBe` "foobar"
+      [qns| foo\\
+            bar  |] `shouldBe` "foo\\ bar"
+
+    -- By 'not really' it means we just shows here what happens with examples
+    -- for QMS when we use them with QNS quoter.
+    describe "Escaping inside interpolation blocks (not really!)" $ do
+
+      it "Line-breaks must be interpreted as just haskell code\
+         \ (not really!)" $ do
+        [qns| {'\n'}          |] `shouldBe` "{'\n'}"
+        [qns| {"foo\nbar"}    |] `shouldBe` "{\"foo\nbar\"}"
+        [qns| {"foo\\nbar"}   |] `shouldBe` "{\"foo\\nbar\"}"
+        [qns| {"foo\\\nbar"}  |] `shouldBe` "{\"foo\\\nbar\"}"
+        [qns| {"foo\\\\nbar"} |] `shouldBe` "{\"foo\\\\nbar\"}"
+
+      it "Escaping for multiline strings" $ do
+        [qns| {"foo\
+               \bar\
+               \baz"} |] `shouldBe` "{\"foo\\bar\\baz\"}"
+        [qns| {"foo \
+               \bar\
+               \ baz"} |] `shouldBe` "{\"foo \\bar baz\"}"
+        [qns| x  \
+              {"foo \
+              \bar\
+              \ baz"}  \
+              y |] `shouldBe` "x  {\"foo \\bar baz\"}  y"
+
+      it "Escaping of close-bracket '}'" $ do
+        [qns| { testFoo {testBar = 9000\} } |]
+          `shouldBe` "{ testFoo {testBar = 9000\\} }"
+        [qns| foo{ testFoo {testBar = 9000\} }bar |]
+          `shouldBe` "foo{ testFoo {testBar = 9000\\} }bar"
+        [qns|foo{testFoo2 {test1 = (test1 testFoo2) {testBar = 9000\}\}}bar|]
+          `shouldBe`
+            "foo{testFoo2 {test1 = (test1 testFoo2) {testBar = 9000\\}\\}}bar"
+        [qns| foo { testFoo2 {
+                test1 = (test1 testFoo2)
+                        { testBar = 9000 \}
+                            \}
+                  } bar |]
+          `shouldBe` "foo { testFoo2 { test1 = (test1 testFoo2)\
+                     \ { testBar = 9000 \\} \\} } bar"
+        [qns| {"\}"}   |] `shouldBe` "{\"\\}\"}"
+        [qns| {"\\\}"} |] `shouldBe` "{\"\\\\}\"}"
+        [qns| {123}}   |] `shouldBe` "{123}}"
+
+      it "When interpolation block is escaped\
+         \ everything must be interpreted as usual (not really)" $ do
+        [qns| \{ foo\nbar\\baz\} } |] `shouldBe` "\\{ foo\nbar\\baz\\} }"
+        [qns| \{ foo\
+                 bar } |] `shouldBe` "\\{ foobar }"
+
+      it "Tabs characters in string inside interpolation block\
+         \ (not really)" $ do
+        [qns| {"foo\t\tbar" } |] `shouldBe` "{\"foo\t\tbar\" }"
+        [qns| {"foo		bar"  } |] `shouldBe` "{\"foo\t\tbar\"  }"
+        [qns| {"foo\\t\tbar"} |] `shouldBe` "{\"foo\\t\tbar\"}"
+
   describe "Tabs as indentation" $ do
 
     it "Tabs is only indentation at left side" $ do
@@ -125,7 +195,13 @@ 
   describe "New README examples" $ do
 
-    it "Simple usage example" $ do
+    it "First example" $
+      [qns| Hello,
+            world!
+            Pi is {floor pi}.{floor $ (pi - 3) * 100}… |]
+        `shouldBe` "Hello, world! Pi is {floor pi}.{floor $ (pi - 3) * 100}…"
+
+    it "Simple usage example" $
       [qns|
         <article>
           <h1>{title}</h1>
@@ -135,24 +211,44 @@         `shouldBe`
           "<article> <h1>{title}</h1> <p>{text}</p> </article>"
 
+    it "Can escape spaces" $
+      [qns|   you can escape spaces
+            \ when you need them    |]
+        `shouldBe`
+          "you can escape spaces  when you need them"
+
+    -- By 'not really' it means that it just copied from `QM` and shows what
+    -- happens with the same input if you use it with this quoter.
+    it "Indentation and line breaks are ignored (not really)" $
+      [qns|
+              indentation and li
+        ne bre
+         aks are i
+             gno
+           red
+             (not really)
+      |]
+      `shouldBe` "indentation and li ne bre aks are i gno red (not really)"
+
+    it "Escaping indentation or line breaks" $
+      [qns|  \  You can escape indentation or\n
+                line breaks when you need them! \  |]
+        `shouldBe`
+          "  You can escape indentation or\n line breaks when you need them!  "
+
+    it "Interpolation blocks can be escaped too" $
+      [qns| Interpolation blocks can be escaped too: {1+2} \{3+4} |]
+        `shouldBe`
+          "Interpolation blocks can be escaped too: {1+2} \\{3+4}"
+
     it "Interpolation" $ [qns| foo {1+2} |] `shouldBe` "foo {1+2}"
 
-  it "Haddock example" $
+  it "Haddock example" $ do
+    [qns| foo {'b':'a':'r':""}
+          baz |] `shouldBe` "foo {'b':'a':'r':\"\"} baz"
     [qns| foo
           {'b':'a':'r':""}
           baz |] `shouldBe` "foo {'b':'a':'r':\"\"} baz"
-
-  it "Escaping backslash itself when it makes sense" $ do
-    [qns| foo\nbar  |] `shouldBe` "foo\nbar"
-    [qns| foo\\nbar |] `shouldBe` "foo\\nbar"
-    [qns| foo\tbar  |] `shouldBe` "foo\tbar"
-    [qns| foo\\tbar |] `shouldBe` "foo\\tbar"
-    [qns| foo\	bar |] `shouldBe` "foo\tbar"
-    [qns| foo\\	bar |] `shouldBe` "foo\\\tbar"
-    [qns| foo\ bar  |] `shouldBe` "foo bar"
-    [qns| foo\\ bar |] `shouldBe` "foo\\ bar"
-
-    [qns| foo\
-          bar  |] `shouldBe` "foobar"
-    [qns| foo\\
-          bar  |] `shouldBe` "foo\\ bar"
+    -- Double-space with escaping
+    [qns| foo {'b':'a':'r':""}
+        \ baz |] `shouldBe` "foo {'b':'a':'r':\"\"}  baz"
test/QM/Spec.hs view
@@ -1,3 +1,6 @@+-- WARNING! Do not remove trailing whitespace or tabs, it's part of the test!+{-# OPTIONS_GHC -fno-warn-tabs #-}+ {-# LANGUAGE PackageImports #-} {-# LANGUAGE QuasiQuotes #-} @@ -8,7 +11,16 @@ -- local imports import "qm-interpolated-string" Text.InterpolatedString.QM (qm) +newtype TestFoo = TestFoo {testBar :: Int} deriving (Show)+newtype TestFoo2 = TestFoo2 {test1 :: TestFoo} deriving (Show) +testFoo :: TestFoo+testFoo = TestFoo 42++testFoo2 :: TestFoo2+testFoo2 = TestFoo2 testFoo++ spec :: Spec spec = do @@ -35,30 +47,94 @@     it "Fourth (escaping interpolation blocks to show them as text)" $       [qm| {1+2} \{3+4} |] `shouldBe` "3 {3+4}" +  it "Empty string" $ [qm|  |] `shouldBe` ""+   it "Type annotation in interpolation block" $     [qm|{10 :: Float}|] `shouldBe` "10.0" -  it "Escaping interpolation symbols inside interpolation block" $ do-    [qm|foo {"b{a{r"} baz|]   `shouldBe` "foo b{a{r baz"-    [qm|foo {"b\}a\}r"} baz|] `shouldBe` "foo b}a}r baz"+  describe "Escaping" $ do -  it "Example from generated docs" $ [qm| foo {'b':'a':'r':""}-                                        \ baz |] `shouldBe` "foo bar baz"+    it "Escaping interpolation symbols inside interpolation block" $ do+      [qm|foo {"b{a{r"} baz|]   `shouldBe` "foo b{a{r baz"+      [qm|foo {"b\}a\}r"} baz|] `shouldBe` "foo b}a}r baz" -  it "Escaping backslashes" $ do [qm| foo\bar |]    `shouldBe` "foo\\bar"-                                 [qm| foo\\bar |]   `shouldBe` "foo\\bar"-                                 [qm| foo\\\bar |]  `shouldBe` "foo\\\\bar"-                                 [qm| foo\\\\bar |] `shouldBe` "foo\\\\bar"+    it "Escaping backslashes" $ do [qm| foo\bar |]    `shouldBe` "foo\\bar"+                                   [qm| foo\\bar |]   `shouldBe` "foo\\bar"+                                   [qm| foo\\\bar |]  `shouldBe` "foo\\\\bar"+                                   [qm| foo\\\\bar |] `shouldBe` "foo\\\\bar" -  it "Empty string" $ [qm|  |] `shouldBe` ""+    it "Escaping space by slash at EOL after space" $+      [qm| foo \+           bar |] `shouldBe` "foo bar" -  it "Escaping space by slash at EOL after space" $-    [qm| foo \-         bar |] `shouldBe` "foo bar"+    it "Escaped spaces at the edges" $ do [qm| foo\ |] `shouldBe` "foo "+                                          [qm|\ foo |] `shouldBe` " foo" -  it "Escaped spaces at the edges" $ do [qm| foo\ |] `shouldBe` "foo "-                                        [qm|\ foo |] `shouldBe` " foo"+    it "Escaping backslash itself when it makes sense" $ do+      [qm| foo\nbar   |] `shouldBe` "foo\nbar"+      [qm| foo\\nbar  |] `shouldBe` "foo\\nbar"+      [qm| foo\tbar   |] `shouldBe` "foo\tbar"+      [qm| foo\\tbar  |] `shouldBe` "foo\\tbar"+      [qm| foo\	bar   |] `shouldBe` "foo\tbar"+      [qm| foo\\	bar |] `shouldBe` "foo\\\tbar"+      [qm| foo\ bar   |] `shouldBe` "foo bar"+      [qm| foo\\ bar  |] `shouldBe` "foo\\ bar" +      [qm| foo\+           bar  |] `shouldBe` "foobar"+      [qm| foo\\+           bar  |] `shouldBe` "foo\\bar"++    describe "Escaping inside interpolation blocks" $ do++      it "Line-breaks must be interpreted as just haskell code" $ do+        [qm| {'\n'}          |] `shouldBe` "\n"+        [qm| {"foo\nbar"}    |] `shouldBe` "foo\nbar"+        [qm| {"foo\\nbar"}   |] `shouldBe` "foo\\nbar"+        [qm| {"foo\\\nbar"}  |] `shouldBe` "foo\\\nbar"+        [qm| {"foo\\\\nbar"} |] `shouldBe` "foo\\\\nbar"++      it "Escaping for multiline strings" $ do+        [qm| {"foo\+              \bar\+              \baz"} |] `shouldBe` "foobarbaz"+        [qm| {"foo \+              \bar\+              \ baz"} |] `shouldBe` "foo bar baz"+        [qm| x  \+             {"foo \+             \bar\+             \ baz"}  \+             y |] `shouldBe` "x  foo bar baz  y"++      it "Escaping of close-bracket '}'" $ do+        [qm| { testFoo {testBar = 9000\} } |]+          `shouldBe` show testFoo {testBar = 9000}+        [qm| foo{ testFoo {testBar = 9000\} }bar |]+          `shouldBe` "foo" ++ show testFoo {testBar = 9000} ++ "bar"+        [qm|foo{testFoo2 {test1 = (test1 testFoo2) {testBar = 9000\}\}}bar|]+          `shouldBe` "foo" ++ show testFoo2 {test1 = TestFoo 9000} ++ "bar"+        [qm| foo { testFoo2 {+               test1 = (test1 testFoo2)+                       { testBar = 9000 \}+                           \}+                 } bar |]+          `shouldBe` "foo " ++ show testFoo2 {test1 = TestFoo 9000} ++ " bar"+        [qm| {"\}"}   |] `shouldBe` "}"+        [qm| {"\\\}"} |] `shouldBe` "\\}"+        [qm| {123}}   |] `shouldBe` "123}"++      it "When interpolation block is escaped\+         \ everything must be interpreted as usual" $ do+        [qm| \{ foo\nbar\\baz\} } |] `shouldBe` "{ foo\nbar\\baz\\} }"+        [qm| \{ foo\+                bar } |] `shouldBe` "{ foobar }"++      it "Tabs characters in string inside interpolation block" $ do+        [qm| {"foo\t\tbar" } |] `shouldBe` "foo\t\tbar"+        [qm| {"foo		bar" } |] `shouldBe` "foo\t\tbar"+        [qm| {"foo\\t\tbar"} |] `shouldBe` "foo\\t\tbar"+   describe "Tabs as indentation" $ do      it "Tabs is only indentation at left side" $ do@@ -99,6 +175,12 @@    describe "New README examples" $ do +    it "First example" $+      [qm| Hello,+           world!+           Pi is {floor pi}.{floor $ (pi - 3) * 100}… |]+        `shouldBe` "Hello,world!Pi is 3.14…"+     it "Simple usage example" $ do       let title = "Testing"           text = "Some testing text"@@ -117,7 +199,7 @@         `shouldBe`           "you can escape spaces when you need them" -    it "Indentation and line breaks are ignored" $ +    it "Indentation and line breaks are ignored" $       [qm|               indentation and li         ne bre@@ -140,21 +222,11 @@      it "Interpolation" $ [qm| foo {1+2} |] `shouldBe` "foo 3" -  it "Haddock example" $+  it "Haddock example" $ do     [qm| foo {'b':'a':'r':""}        \ baz |] `shouldBe` "foo bar baz"--  it "Escaping backslash itself when it makes sense" $ do-    [qm| foo\nbar   |] `shouldBe` "foo\nbar"-    [qm| foo\\nbar  |] `shouldBe` "foo\\nbar"-    [qm| foo\tbar   |] `shouldBe` "foo\tbar"-    [qm| foo\\tbar  |] `shouldBe` "foo\\tbar"-    [qm| foo\	bar   |] `shouldBe` "foo\tbar"-    [qm| foo\\	bar |] `shouldBe` "foo\\\tbar"-    [qm| foo\ bar   |] `shouldBe` "foo bar"-    [qm| foo\\ bar  |] `shouldBe` "foo\\ bar"--    [qm| foo\-         bar  |] `shouldBe` "foobar"-    [qm| foo\\-         bar  |] `shouldBe` "foo\\bar"+    [qm| foo+       \ {'b':'a':'r':""}+       \ baz |] `shouldBe` "foo bar baz"+    [qm| foo {'b':'a':'r':""}+         baz |] `shouldBe` "foo barbaz"
test/QMB/Spec.hs view
@@ -1,3 +1,6 @@+-- WARNING! Do not remove trailing whitespace or tabs, it's part of the test!+{-# OPTIONS_GHC -fno-warn-tabs #-}+ {-# LANGUAGE PackageImports #-} {-# LANGUAGE QuasiQuotes #-} @@ -8,7 +11,16 @@ -- local imports import "qm-interpolated-string" Text.InterpolatedString.QM (qmb) +newtype TestFoo = TestFoo {testBar :: Int} deriving (Show)+newtype TestFoo2 = TestFoo2 {test1 :: TestFoo} deriving (Show) +testFoo :: TestFoo+testFoo = TestFoo 42++testFoo2 :: TestFoo2+testFoo2 = TestFoo2 testFoo++ spec :: Spec spec = do @@ -56,30 +68,95 @@     it "Fourth (escaping interpolation blocks to show them as text)" $       [qmb| {1+2} \{3+4} |] `shouldBe` "3 {3+4}" +  it "Empty string" $ [qmb|  |] `shouldBe` ""+   it "Type annotation in interpolation block" $     [qmb|{10 :: Float}|] `shouldBe` "10.0" -  it "Escaping interpolation symbols inside interpolation block" $ do-    [qmb|foo {"b{a{r"} baz|]   `shouldBe` "foo b{a{r baz"-    [qmb|foo {"b\}a\}r"} baz|] `shouldBe` "foo b}a}r baz"+  describe "Escaping" $ do -  it "Example from generated docs" $ [qmb| foo {'b':'a':'r':""}-                                         \ baz |] `shouldBe` "foo bar\n baz"+    it "Escaping interpolation symbols inside interpolation block" $ do+      [qmb|foo {"b{a{r"} baz|]   `shouldBe` "foo b{a{r baz"+      [qmb|foo {"b\}a\}r"} baz|] `shouldBe` "foo b}a}r baz" -  it "Escaping backslashes" $ do [qmb| foo\bar |]    `shouldBe` "foo\\bar"-                                 [qmb| foo\\bar |]   `shouldBe` "foo\\bar"-                                 [qmb| foo\\\bar |]  `shouldBe` "foo\\\\bar"-                                 [qmb| foo\\\\bar |] `shouldBe` "foo\\\\bar"+    it "Escaping backslashes" $ do [qmb| foo\bar |]    `shouldBe` "foo\\bar"+                                   [qmb| foo\\bar |]   `shouldBe` "foo\\bar"+                                   [qmb| foo\\\bar |]  `shouldBe` "foo\\\\bar"+                                   [qmb| foo\\\\bar |] `shouldBe` "foo\\\\bar" -  it "Empty string" $ [qmb|  |] `shouldBe` ""+    it "Escaping space by backslash at EOL after space\+       \ (line break is cutted off)" $+      [qmb| foo \+            bar |] `shouldBe` "foo bar" -  it "Escaping space by backslash at EOL after space (line break is cutted off)" $-    [qmb| foo \-          bar |] `shouldBe` "foo bar"+    it "Escaped spaces at the edges" $ do [qmb| foo\ |] `shouldBe` "foo "+                                          [qmb|\ foo |] `shouldBe` " foo" -  it "Escaped spaces at the edges" $ do [qmb| foo\ |] `shouldBe` "foo "-                                        [qmb|\ foo |] `shouldBe` " foo"+    it "Escaping backslash itself when it makes sense" $ do+      [qmb| foo\nbar  |] `shouldBe` "foo\nbar"+      [qmb| foo\\nbar |] `shouldBe` "foo\\nbar"+      [qmb| foo\tbar  |] `shouldBe` "foo\tbar"+      [qmb| foo\\tbar |] `shouldBe` "foo\\tbar"+      [qmb| foo\	bar |] `shouldBe` "foo\tbar"+      [qmb| foo\\	bar |] `shouldBe` "foo\\\tbar"+      [qmb| foo\ bar  |] `shouldBe` "foo bar"+      [qmb| foo\\ bar |] `shouldBe` "foo\\ bar" +      [qmb| foo\+            bar  |] `shouldBe` "foobar"+      [qmb| foo\\+            bar  |] `shouldBe` "foo\\\nbar"++    describe "Escaping inside interpolation blocks" $ do++      it "Line-breaks must be interpreted as just haskell code" $ do+        [qmb| {'\n'}          |] `shouldBe` "\n"+        [qmb| {"foo\nbar"}    |] `shouldBe` "foo\nbar"+        [qmb| {"foo\\nbar"}   |] `shouldBe` "foo\\nbar"+        [qmb| {"foo\\\nbar"}  |] `shouldBe` "foo\\\nbar"+        [qmb| {"foo\\\\nbar"} |] `shouldBe` "foo\\\\nbar"++      it "Escaping for multiline strings" $ do+        [qmb| {"foo\+               \bar\+               \baz"} |] `shouldBe` "foobarbaz"+        [qmb| {"foo \+               \bar\+               \ baz"} |] `shouldBe` "foo bar baz"+        [qmb| x  \+              {"foo \+              \bar\+              \ baz"}  \+              y |] `shouldBe` "x  foo bar baz  y"++      it "Escaping of close-bracket '}'" $ do+        [qmb| { testFoo {testBar = 9000\} } |]+          `shouldBe` show testFoo {testBar = 9000}+        [qmb| foo{ testFoo {testBar = 9000\} }bar |]+          `shouldBe` "foo" ++ show testFoo {testBar = 9000} ++ "bar"+        [qmb|foo{testFoo2 {test1 = (test1 testFoo2) {testBar = 9000\}\}}bar|]+          `shouldBe` "foo" ++ show testFoo2 {test1 = TestFoo 9000} ++ "bar"+        [qmb| foo { testFoo2 {+                test1 = (test1 testFoo2)+                        { testBar = 9000 \}+                            \}+                  } bar |]+          `shouldBe` "foo " ++ show testFoo2 {test1 = TestFoo 9000} ++ " bar"+        [qmb| {"\}"}   |] `shouldBe` "}"+        [qmb| {"\\\}"} |] `shouldBe` "\\}"+        [qmb| {123}}   |] `shouldBe` "123}"++      it "When interpolation block is escaped\+         \ everything must be interpreted as usual" $ do+        [qmb| \{ foo\nbar\\baz\} } |] `shouldBe` "{ foo\nbar\\baz\\} }"+        [qmb| \{ foo\+                 bar } |] `shouldBe` "{ foobar }"++      it "Tabs characters in string inside interpolation block" $ do+        [qmb| {"foo\t\tbar" } |] `shouldBe` "foo\t\tbar"+        [qmb| {"foo		bar"  } |] `shouldBe` "foo\t\tbar"+        [qmb| {"foo\\t\tbar"} |] `shouldBe` "foo\\t\tbar"+   describe "Tabs as indentation" $ do      it "Tabs is only indentation at left side" $ do@@ -120,6 +197,12 @@    describe "New README examples" $ do +    it "First example" $+      [qmb| Hello,+            world!+            Pi is {floor pi}.{floor $ (pi - 3) * 100}… |]+        `shouldBe` "Hello,\nworld!\nPi is 3.14…"+     it "Simple usage example" $ do       let title = "Testing"           text = "Some testing text"@@ -132,24 +215,43 @@         `shouldBe`           "<article>\n<h1>Testing</h1>\n<p>Some testing text</p>\n</article>" +    it "Can escape spaces" $+      [qmb|   you can escape spaces+            \ when you need them    |]+        `shouldBe`+          "you can escape spaces\n when you need them"++    -- By 'not really' it means that it just copied from `QM` and shows what+    -- happens with the same input if you use it with this quoter.+    it "Indentation and line breaks are ignored (not really)" $+      [qmb|+              indentation and li+        ne bre+         aks are i+             gno+           red+             (not really)+      |]+      `shouldBe` "indentation and li\nne bre\naks are i\ngno\nred\n(not really)"++    it "Escaping indentation or line breaks" $+      [qmb|  \  You can escape indentation or\n+                line breaks when you need them! \  |]+        `shouldBe`+          "  You can escape indentation or\n\nline breaks when you need them!  "++    it "Interpolation blocks can be escaped too" $+      [qmb| Interpolation blocks can be escaped too: {1+2} \{3+4} |]+        `shouldBe`+          "Interpolation blocks can be escaped too: 3 {3+4}"+     it "Interpolation" $ [qmb| foo {1+2} |] `shouldBe` "foo 3" -  it "Haddock example" $+  it "Haddock example" $ do+    [qmb| foo {'b':'a':'r':""}+          baz |] `shouldBe` "foo bar\nbaz"     [qmb| foo           {'b':'a':'r':""}           baz |] `shouldBe` "foo\nbar\nbaz"--  it "Escaping backslash itself when it makes sense" $ do-    [qmb| foo\nbar  |] `shouldBe` "foo\nbar"-    [qmb| foo\\nbar |] `shouldBe` "foo\\nbar"-    [qmb| foo\tbar  |] `shouldBe` "foo\tbar"-    [qmb| foo\\tbar |] `shouldBe` "foo\\tbar"-    [qmb| foo\	bar |] `shouldBe` "foo\tbar"-    [qmb| foo\\	bar |] `shouldBe` "foo\\\tbar"-    [qmb| foo\ bar  |] `shouldBe` "foo bar"-    [qmb| foo\\ bar |] `shouldBe` "foo\\ bar"--    [qmb| foo\-          bar  |] `shouldBe` "foobar"-    [qmb| foo\\-          bar  |] `shouldBe` "foo\\\nbar"+    [qmb| foo {'b':'a':'r':""}+        \ baz |] `shouldBe` "foo bar\n baz"
test/QMS/Spec.hs view
@@ -1,3 +1,6 @@+-- WARNING! Do not remove trailing whitespace or tabs, it's part of the test!+{-# OPTIONS_GHC -fno-warn-tabs #-}+ {-# LANGUAGE PackageImports #-} {-# LANGUAGE QuasiQuotes #-} @@ -8,7 +11,16 @@ -- local imports import "qm-interpolated-string" Text.InterpolatedString.QM (qms) +newtype TestFoo = TestFoo {testBar :: Int} deriving (Show)+newtype TestFoo2 = TestFoo2 {test1 :: TestFoo} deriving (Show) +testFoo :: TestFoo+testFoo = TestFoo 42++testFoo2 :: TestFoo2+testFoo2 = TestFoo2 testFoo++ spec :: Spec spec = do @@ -56,30 +68,95 @@     it "Fourth (escaping interpolation blocks to show them as text)" $       [qms| {1+2} \{3+4} |] `shouldBe` "3 {3+4}" +  it "Empty string" $ [qms|  |] `shouldBe` ""+   it "Type annotation in interpolation block" $     [qms|{10 :: Float}|] `shouldBe` "10.0" -  it "Escaping interpolation symbols inside interpolation block" $ do-    [qms|foo {"b{a{r"} baz|]   `shouldBe` "foo b{a{r baz"-    [qms|foo {"b\}a\}r"} baz|] `shouldBe` "foo b}a}r baz"+  describe "Escaping" $ do -  it "Example from generated docs" $ [qms| foo {'b':'a':'r':""}-                                         \ baz |] `shouldBe` "foo bar  baz"+    it "Escaping interpolation symbols inside interpolation block" $ do+      [qms|foo {"b{a{r"} baz|]   `shouldBe` "foo b{a{r baz"+      [qms|foo {"b\}a\}r"} baz|] `shouldBe` "foo b}a}r baz" -  it "Escaping backslashes" $ do [qms| foo\bar |]    `shouldBe` "foo\\bar"-                                 [qms| foo\\bar |]   `shouldBe` "foo\\bar"-                                 [qms| foo\\\bar |]  `shouldBe` "foo\\\\bar"-                                 [qms| foo\\\\bar |] `shouldBe` "foo\\\\bar"+    it "Escaping backslashes" $ do [qms| foo\bar |]    `shouldBe` "foo\\bar"+                                   [qms| foo\\bar |]   `shouldBe` "foo\\bar"+                                   [qms| foo\\\bar |]  `shouldBe` "foo\\\\bar"+                                   [qms| foo\\\\bar |] `shouldBe` "foo\\\\bar" -  it "Empty string" $ [qms|  |] `shouldBe` ""+    it "Escaping space by backslash at EOL after space\+       \ (line break is cutted off)" $+      [qms| foo \+            bar |] `shouldBe` "foo bar" -  it "Escaping space by backslash at EOL after space (line break is cutted off)" $-    [qms| foo \-          bar |] `shouldBe` "foo bar"+    it "Escaped spaces at the edges" $ do [qms| foo\ |] `shouldBe` "foo "+                                          [qms|\ foo |] `shouldBe` " foo" -  it "Escaped spaces at the edges" $ do [qms| foo\ |] `shouldBe` "foo "-                                        [qms|\ foo |] `shouldBe` " foo"+    it "Escaping backslash itself when it makes sense" $ do+      [qms| foo\nbar  |] `shouldBe` "foo\nbar"+      [qms| foo\\nbar |] `shouldBe` "foo\\nbar"+      [qms| foo\tbar  |] `shouldBe` "foo\tbar"+      [qms| foo\\tbar |] `shouldBe` "foo\\tbar"+      [qms| foo\	bar |] `shouldBe` "foo\tbar"+      [qms| foo\\	bar |] `shouldBe` "foo\\\tbar"+      [qms| foo\ bar  |] `shouldBe` "foo bar"+      [qms| foo\\ bar |] `shouldBe` "foo\\ bar" +      [qms| foo\+            bar  |] `shouldBe` "foobar"+      [qms| foo\\+            bar  |] `shouldBe` "foo\\ bar"++    describe "Escaping inside interpolation blocks" $ do++      it "Line-breaks must be interpreted as just haskell code" $ do+        [qms| {'\n'}          |] `shouldBe` "\n"+        [qms| {"foo\nbar"}    |] `shouldBe` "foo\nbar"+        [qms| {"foo\\nbar"}   |] `shouldBe` "foo\\nbar"+        [qms| {"foo\\\nbar"}  |] `shouldBe` "foo\\\nbar"+        [qms| {"foo\\\\nbar"} |] `shouldBe` "foo\\\\nbar"++      it "Escaping for multiline strings" $ do+        [qms| {"foo\+               \bar\+               \baz"} |] `shouldBe` "foobarbaz"+        [qms| {"foo \+               \bar\+               \ baz"} |] `shouldBe` "foo bar baz"+        [qms| x  \+              {"foo \+              \bar\+              \ baz"}  \+              y |] `shouldBe` "x  foo bar baz  y"++      it "Escaping of close-bracket '}'" $ do+        [qms| { testFoo {testBar = 9000\} } |]+          `shouldBe` show testFoo {testBar = 9000}+        [qms| foo{ testFoo {testBar = 9000\} }bar |]+          `shouldBe` "foo" ++ show testFoo {testBar = 9000} ++ "bar"+        [qms|foo{testFoo2 {test1 = (test1 testFoo2) {testBar = 9000\}\}}bar|]+          `shouldBe` "foo" ++ show testFoo2 {test1 = TestFoo 9000} ++ "bar"+        [qms| foo { testFoo2 {+                test1 = (test1 testFoo2)+                        { testBar = 9000 \}+                            \}+                  } bar |]+          `shouldBe` "foo " ++ show testFoo2 {test1 = TestFoo 9000} ++ " bar"+        [qms| {"\}"}   |] `shouldBe` "}"+        [qms| {"\\\}"} |] `shouldBe` "\\}"+        [qms| {123}}   |] `shouldBe` "123}"++      it "When interpolation block is escaped\+         \ everything must be interpreted as usual" $ do+        [qms| \{ foo\nbar\\baz\} } |] `shouldBe` "{ foo\nbar\\baz\\} }"+        [qms| \{ foo\+                 bar } |] `shouldBe` "{ foobar }"++      it "Tabs characters in string inside interpolation block" $ do+        [qms| {"foo\t\tbar" } |] `shouldBe` "foo\t\tbar"+        [qms| {"foo		bar"  } |] `shouldBe` "foo\t\tbar"+        [qms| {"foo\\t\tbar"} |] `shouldBe` "foo\\t\tbar"+   describe "Tabs as indentation" $ do      it "Tabs is only indentation at left side" $ do@@ -138,24 +215,44 @@         `shouldBe`           "<article> <h1>Testing</h1> <p>Some testing text</p> </article>" +    it "Can escape spaces" $+      [qms|   you can escape spaces+            \ when you need them    |]+        `shouldBe`+          "you can escape spaces  when you need them"++    -- By 'not really' it means that it just copied from `QM` and shows what+    -- happens with the same input if you use it with this quoter.+    it "Indentation and line breaks are ignored (not really)" $+      [qms|+              indentation and li+        ne bre+         aks are i+             gno+           red+             (not really)+      |]+      `shouldBe` "indentation and li ne bre aks are i gno red (not really)"++    it "Escaping indentation or line breaks" $+      [qms|  \  You can escape indentation or\n+                line breaks when you need them! \  |]+        `shouldBe`+          "  You can escape indentation or\n line breaks when you need them!  "++    it "Interpolation blocks can be escaped too" $+      [qms| Interpolation blocks can be escaped too: {1+2} \{3+4} |]+        `shouldBe`+          "Interpolation blocks can be escaped too: 3 {3+4}"+     it "Interpolation" $ [qms| foo {1+2} |] `shouldBe` "foo 3" -  it "Haddock example" $+  it "Haddock example" $ do+    [qms| foo {'b':'a':'r':""}+          baz |] `shouldBe` "foo bar baz"     [qms| foo           {'b':'a':'r':""}           baz |] `shouldBe` "foo bar baz"--  it "Escaping backslash itself when it makes sense" $ do-    [qms| foo\nbar  |] `shouldBe` "foo\nbar"-    [qms| foo\\nbar |] `shouldBe` "foo\\nbar"-    [qms| foo\tbar  |] `shouldBe` "foo\tbar"-    [qms| foo\\tbar |] `shouldBe` "foo\\tbar"-    [qms| foo\	bar |] `shouldBe` "foo\tbar"-    [qms| foo\\	bar |] `shouldBe` "foo\\\tbar"-    [qms| foo\ bar  |] `shouldBe` "foo bar"-    [qms| foo\\ bar |] `shouldBe` "foo\\ bar"--    [qms| foo\-          bar  |] `shouldBe` "foobar"-    [qms| foo\\-          bar  |] `shouldBe` "foo\\ bar"+    -- Double-space with escaping+    [qms| foo {'b':'a':'r':""}+        \ baz |] `shouldBe` "foo bar  baz"
test/QN/Spec.hs view
@@ -1,3 +1,6 @@+-- WARNING! Do not remove trailing whitespace or tabs, it's part of the test!+{-# OPTIONS_GHC -fno-warn-tabs #-}+ {-# LANGUAGE PackageImports #-} {-# LANGUAGE QuasiQuotes #-} @@ -35,34 +38,100 @@     it "Fourth (escaping interpolation blocks to show them as text)" $       [qn| {1+2} \{3+4} |] `shouldBe` "{1+2} \\{3+4}" -    it "Example of `qn` QuasiQuoter" $-      [qn| foo {1+2} |] `shouldBe` "foo {1+2}"+  it "Empty string" $ [qn|  |] `shouldBe` ""    it "Type annotation in interpolation block" $     [qn|{10 :: Float}|] `shouldBe` "{10 :: Float}" -  it "Escaping interpolation symbols inside interpolation block" $ do-    [qn|foo {"b{a{r"} baz|] `shouldBe` "foo {\"b{a{r\"} baz"-    [qn|foo {"b\}a\}r"} baz|] `shouldBe` "foo {\"b\\}a\\}r\"} baz"+  describe "Escaping" $ do -  it "Example from generated docs" $-    [qn| foo {'b':'a':'r':""}-       \ baz |] `shouldBe` "foo {'b':'a':'r':\"\"} baz"+    it "Escaping interpolation symbols inside interpolation block" $ do+      [qn|foo {"b{a{r"} baz|] `shouldBe` "foo {\"b{a{r\"} baz"+      [qn|foo {"b\}a\}r"} baz|] `shouldBe` "foo {\"b\\}a\\}r\"} baz" -  it "Escaping backslashes" $ do [qn| foo\bar |]    `shouldBe` "foo\\bar"-                                 [qn| foo\\bar |]   `shouldBe` "foo\\bar"-                                 [qn| foo\\\bar |]  `shouldBe` "foo\\\\bar"-                                 [qn| foo\\\\bar |] `shouldBe` "foo\\\\bar"+    it "Escaping backslashes" $ do [qn| foo\bar |]    `shouldBe` "foo\\bar"+                                   [qn| foo\\bar |]   `shouldBe` "foo\\bar"+                                   [qn| foo\\\bar |]  `shouldBe` "foo\\\\bar"+                                   [qn| foo\\\\bar |] `shouldBe` "foo\\\\bar" -  it "Empty string" $ [qn|  |] `shouldBe` ""+    it "Escaping space by slash at EOL after space" $+      [qn| foo \+           bar |] `shouldBe` "foo bar" -  it "Escaping space by slash at EOL after space" $-    [qn| foo \-         bar |] `shouldBe` "foo bar"+    it "Escaped spaces at the edges" $ do [qn| foo\ |] `shouldBe` "foo "+                                          [qn|\ foo |] `shouldBe` " foo" -  it "Escaped spaces at the edges" $ do [qn| foo\ |] `shouldBe` "foo "-                                        [qn|\ foo |] `shouldBe` " foo"+    it "Escaping backslash itself when it makes sense" $ do+      [qn| foo\nbar   |] `shouldBe` "foo\nbar"+      [qn| foo\\nbar  |] `shouldBe` "foo\\nbar"+      [qn| foo\tbar   |] `shouldBe` "foo\tbar"+      [qn| foo\\tbar  |] `shouldBe` "foo\\tbar"+      [qn| foo\	bar   |] `shouldBe` "foo\tbar"+      [qn| foo\\	bar |] `shouldBe` "foo\\\tbar"+      [qn| foo\ bar   |] `shouldBe` "foo bar"+      [qn| foo\\ bar  |] `shouldBe` "foo\\ bar" +      [qn| foo\+           bar  |] `shouldBe` "foobar"+      [qn| foo\\+           bar  |] `shouldBe` "foo\\bar"++    -- By 'not really' it means we just shows here what happens with examples+    -- for QM when we use them with QN quoter.+    describe "Escaping inside interpolation blocks (not really!)" $ do++      it "Line-breaks must be interpreted as just haskell code\+         \ (not really!)" $ do+        [qn| {'\n'}          |] `shouldBe` "{'\n'}"+        [qn| {"foo\nbar"}    |] `shouldBe` "{\"foo\nbar\"}"+        [qn| {"foo\\nbar"}   |] `shouldBe` "{\"foo\\nbar\"}"+        [qn| {"foo\\\nbar"}  |] `shouldBe` "{\"foo\\\nbar\"}"+        [qn| {"foo\\\\nbar"} |] `shouldBe` "{\"foo\\\\nbar\"}"++      it "Escaping for multiline strings" $ do+        [qn| {"foo\+              \bar\+              \baz"} |] `shouldBe` "{\"foo\\bar\\baz\"}"+        [qn| {"foo \+              \bar\+              \ baz"} |] `shouldBe` "{\"foo \\bar baz\"}"+        [qn| x  \+             {"foo \+             \bar\+             \ baz"}  \+             y |] `shouldBe` "x  {\"foo \\bar baz\"}  y"++      it "Escaping of close-bracket '}'" $ do+        [qn| { testFoo {testBar = 9000\} } |]+          `shouldBe` "{ testFoo {testBar = 9000\\} }"+        [qn| foo{ testFoo {testBar = 9000\} }bar |]+          `shouldBe` "foo{ testFoo {testBar = 9000\\} }bar"+        [qn|foo{testFoo2 {test1 = (test1 testFoo2) {testBar = 9000\}\}}bar|]+          `shouldBe`+            "foo{testFoo2 {test1 = (test1 testFoo2) {testBar = 9000\\}\\}}bar"+        [qn| foo { testFoo2 {+               test1 = (test1 testFoo2)+                       { testBar = 9000 \}+                           \}+                 } bar |]+          `shouldBe` "foo { testFoo2 {test1 = (test1 testFoo2)\+                     \{ testBar = 9000 \\}\\}} bar"+        [qn| {"\}"}   |] `shouldBe` "{\"\\}\"}"+        [qn| {"\\\}"} |] `shouldBe` "{\"\\\\}\"}"+        [qn| {123}}   |] `shouldBe` "{123}}"++      it "When interpolation block is escaped\+         \ everything must be interpreted as usual (not really)" $ do+        [qn| \{ foo\nbar\\baz\} } |] `shouldBe` "\\{ foo\nbar\\baz\\} }"+        [qn| \{ foo\+                bar } |] `shouldBe` "\\{ foobar }"++      it "Tabs characters in string inside interpolation block\+         \ (not really!)" $ do+        [qn| {"foo\t\tbar" } |] `shouldBe` "{\"foo\t\tbar\" }"+        [qn| {"foo		bar" } |] `shouldBe` "{\"foo\t\tbar\" }"+        [qn| {"foo\\t\tbar"} |] `shouldBe` "{\"foo\\t\tbar\"}"+   describe "Tabs as indentation" $ do      it "Tabs is only indentation at left side" $ do@@ -103,7 +172,13 @@    describe "New README examples" $ do -    it "Simple usage example" $ do+    it "First example" $+      [qn| Hello,+           world!+           Pi is {floor pi}.{floor $ (pi - 3) * 100}… |]+        `shouldBe` "Hello,world!Pi is {floor pi}.{floor $ (pi - 3) * 100}…"++    it "Simple usage example" $       [qn|         <article>           <h1>{title}</h1>@@ -111,23 +186,40 @@         </article>       |] `shouldBe` "<article><h1>{title}</h1><p>{text}</p></article>" +    it "Can escape spaces" $+      [qn|   you can escape spaces+           \ when you need them    |]+        `shouldBe`+          "you can escape spaces when you need them"++    it "Indentation and line breaks are ignored" $+      [qn|+              indentation and li+        ne bre+         aks are i+             gno+           red+      |]+      `shouldBe` "indentation and line breaks are ignored"++    it "Escaping indentation or line breaks" $+      [qn|  \  You can escape indentation or\n+               line breaks when you need them! \  |]+        `shouldBe`+          "  You can escape indentation or\nline breaks when you need them!  "++    it "Interpolation blocks can be escaped too" $+      [qn| Interpolation blocks can be escaped too: {1+2} \{3+4} |]+        `shouldBe`+          "Interpolation blocks can be escaped too: {1+2} \\{3+4}"+     it "Interpolation" $ [qn| foo {1+2} |] `shouldBe` "foo {1+2}" -  it "Haddock example" $+  it "Haddock example" $ do     [qn| foo {'b':'a':'r':""}        \ baz |] `shouldBe` "foo {'b':'a':'r':\"\"} baz"--  it "Escaping backslash itself when it makes sense" $ do-    [qn| foo\nbar   |] `shouldBe` "foo\nbar"-    [qn| foo\\nbar  |] `shouldBe` "foo\\nbar"-    [qn| foo\tbar   |] `shouldBe` "foo\tbar"-    [qn| foo\\tbar  |] `shouldBe` "foo\\tbar"-    [qn| foo\	bar   |] `shouldBe` "foo\tbar"-    [qn| foo\\	bar |] `shouldBe` "foo\\\tbar"-    [qn| foo\ bar   |] `shouldBe` "foo bar"-    [qn| foo\\ bar  |] `shouldBe` "foo\\ bar"--    [qn| foo\-         bar  |] `shouldBe` "foobar"-    [qn| foo\\-         bar  |] `shouldBe` "foo\\bar"+    [qn| foo+       \ {'b':'a':'r':""}+       \ baz |] `shouldBe` "foo {'b':'a':'r':\"\"} baz"+    [qn| foo {'b':'a':'r':""}+         baz |] `shouldBe` "foo {'b':'a':'r':\"\"}baz"
test/QNB/Spec.hs view
@@ -1,3 +1,6 @@+-- WARNING! Do not remove trailing whitespace or tabs, it's part of the test!+{-# OPTIONS_GHC -fno-warn-tabs #-}+ {-# LANGUAGE PackageImports #-} {-# LANGUAGE QuasiQuotes #-} @@ -56,34 +59,101 @@     it "Fourth (escaping interpolation blocks to show them as text)" $       [qnb| {1+2} \{3+4} |] `shouldBe` "{1+2} \\{3+4}" -    it "Example of `qnb` QuasiQuoter" $-      [qnb| foo {1+2} |] `shouldBe` "foo {1+2}"+  it "Empty string" $ [qnb|  |] `shouldBe` ""    it "Type annotation in interpolation block" $     [qnb|{10 :: Float}|] `shouldBe` "{10 :: Float}" -  it "Escaping interpolation symbols inside interpolation block" $ do-    [qnb|foo {"b{a{r"} baz|] `shouldBe` "foo {\"b{a{r\"} baz"-    [qnb|foo {"b\}a\}r"} baz|] `shouldBe` "foo {\"b\\}a\\}r\"} baz"+  describe "Escaping" $ do -  it "Example from generated docs (double-space)" $-    [qnb| foo {'b':'a':'r':""}-        \ baz |] `shouldBe` "foo {'b':'a':'r':\"\"}\n baz"+    it "Escaping interpolation symbols inside interpolation block" $ do+      [qnb|foo {"b{a{r"} baz|] `shouldBe` "foo {\"b{a{r\"} baz"+      [qnb|foo {"b\}a\}r"} baz|] `shouldBe` "foo {\"b\\}a\\}r\"} baz" -  it "Escaping backslashes" $ do [qnb| foo\bar |]    `shouldBe` "foo\\bar"-                                 [qnb| foo\\bar |]   `shouldBe` "foo\\bar"-                                 [qnb| foo\\\bar |]  `shouldBe` "foo\\\\bar"-                                 [qnb| foo\\\\bar |] `shouldBe` "foo\\\\bar"+    it "Escaping backslashes" $ do [qnb| foo\bar |]    `shouldBe` "foo\\bar"+                                   [qnb| foo\\bar |]   `shouldBe` "foo\\bar"+                                   [qnb| foo\\\bar |]  `shouldBe` "foo\\\\bar"+                                   [qnb| foo\\\\bar |] `shouldBe` "foo\\\\bar" -  it "Empty string" $ [qnb|  |] `shouldBe` ""+    it "Escaping space by backslash at EOL after space\+       \ (line break is cutted off)" $+      [qnb| foo \+            bar |] `shouldBe` "foo bar" -  it "Escaping space by backslash at EOL after space (line break is cutted off)" $-    [qnb| foo \-          bar |] `shouldBe` "foo bar"+    it "Escaped spaces at the edges" $ do [qnb| foo\ |] `shouldBe` "foo "+                                          [qnb|\ foo |] `shouldBe` " foo" -  it "Escaped spaces at the edges" $ do [qnb| foo\ |] `shouldBe` "foo "-                                        [qnb|\ foo |] `shouldBe` " foo"+    it "Escaping backslash itself when it makes sense" $ do+      [qnb| foo\nbar  |] `shouldBe` "foo\nbar"+      [qnb| foo\\nbar |] `shouldBe` "foo\\nbar"+      [qnb| foo\tbar  |] `shouldBe` "foo\tbar"+      [qnb| foo\\tbar |] `shouldBe` "foo\\tbar"+      [qnb| foo\	bar |] `shouldBe` "foo\tbar"+      [qnb| foo\\	bar |] `shouldBe` "foo\\\tbar"+      [qnb| foo\ bar  |] `shouldBe` "foo bar"+      [qnb| foo\\ bar |] `shouldBe` "foo\\ bar" +      [qnb| foo\+            bar  |] `shouldBe` "foobar"+      [qnb| foo\\+            bar  |] `shouldBe` "foo\\\nbar"++    -- By 'not really' it means we just shows here what happens with examples+    -- for QMB when we use them with QNB quoter.+    describe "Escaping inside interpolation blocks (not really!)" $ do++      it "Line-breaks must be interpreted as just haskell code\+         \ (not really!)" $ do+        [qnb| {'\n'}          |] `shouldBe` "{'\n'}"+        [qnb| {"foo\nbar"}    |] `shouldBe` "{\"foo\nbar\"}"+        [qnb| {"foo\\nbar"}   |] `shouldBe` "{\"foo\\nbar\"}"+        [qnb| {"foo\\\nbar"}  |] `shouldBe` "{\"foo\\\nbar\"}"+        [qnb| {"foo\\\\nbar"} |] `shouldBe` "{\"foo\\\\nbar\"}"++      it "Escaping for multiline strings" $ do+        [qnb| {"foo\+               \bar\+               \baz"} |] `shouldBe` "{\"foo\\bar\\baz\"}"+        [qnb| {"foo \+               \bar\+               \ baz"} |] `shouldBe` "{\"foo \\bar baz\"}"+        [qnb| x  \+              {"foo \+              \bar\+              \ baz"}  \+              y |] `shouldBe` "x  {\"foo \\bar baz\"}  y"++      it "Escaping of close-bracket '}'" $ do+        [qnb| { testFoo {testBar = 9000\} } |]+          `shouldBe` "{ testFoo {testBar = 9000\\} }"+        [qnb| foo{ testFoo {testBar = 9000\} }bar |]+          `shouldBe` "foo{ testFoo {testBar = 9000\\} }bar"+        [qnb|foo{testFoo2 {test1 = (test1 testFoo2) {testBar = 9000\}\}}bar|]+          `shouldBe`+            "foo{testFoo2 {test1 = (test1 testFoo2) {testBar = 9000\\}\\}}bar"+        [qnb| foo { testFoo2 {+                test1 = (test1 testFoo2)+                        { testBar = 9000 \}+                            \}+                  } bar |]+          `shouldBe` "foo { testFoo2 {\ntest1 = (test1 testFoo2)\n\+                     \{ testBar = 9000 \\}\n\\}\n} bar"+        [qnb| {"\}"}   |] `shouldBe` "{\"\\}\"}"+        [qnb| {"\\\}"} |] `shouldBe` "{\"\\\\}\"}"+        [qnb| {123}}   |] `shouldBe` "{123}}"++      it "When interpolation block is escaped\+         \ everything must be interpreted as usual (not really)" $ do+        [qnb| \{ foo\nbar\\baz\} } |] `shouldBe` "\\{ foo\nbar\\baz\\} }"+        [qnb| \{ foo\+                 bar } |] `shouldBe` "\\{ foobar }"++      it "Tabs characters in string inside interpolation block\+         \ (not really)" $ do+        [qnb| {"foo\t\tbar" } |] `shouldBe` "{\"foo\t\tbar\" }"+        [qnb| {"foo		bar"  } |] `shouldBe` "{\"foo\t\tbar\"  }"+        [qnb| {"foo\\t\tbar"} |] `shouldBe` "{\"foo\\t\tbar\"}"+   describe "Tabs as indentation" $ do      it "Tabs is only indentation at left side" $ do@@ -124,7 +194,13 @@    describe "New README examples" $ do -    it "Simple usage example" $ do+    it "First example" $+      [qnb| Hello,+            world!+            Pi is {floor pi}.{floor $ (pi - 3) * 100}… |]+        `shouldBe` "Hello,\nworld!\nPi is {floor pi}.{floor $ (pi - 3) * 100}…"++    it "Simple usage example" $       [qnb|         <article>           <h1>{title}</h1>@@ -134,24 +210,43 @@         `shouldBe`           "<article>\n<h1>{title}</h1>\n<p>{text}</p>\n</article>" +    it "Can escape spaces" $+      [qnb|   you can escape spaces+            \ when you need them    |]+        `shouldBe`+          "you can escape spaces\n when you need them"++    -- By 'not really' it means that it just copied from `QM` and shows what+    -- happens with the same input if you use it with this quoter.+    it "Indentation and line breaks are ignored (not really)" $+      [qnb|+              indentation and li+        ne bre+         aks are i+             gno+           red+             (not really)+      |]+      `shouldBe` "indentation and li\nne bre\naks are i\ngno\nred\n(not really)"++    it "Escaping indentation or line breaks" $+      [qnb|  \  You can escape indentation or\n+                line breaks when you need them! \  |]+        `shouldBe`+          "  You can escape indentation or\n\nline breaks when you need them!  "++    it "Interpolation blocks can be escaped too" $+      [qnb| Interpolation blocks can be escaped too: {1+2} \{3+4} |]+        `shouldBe`+          "Interpolation blocks can be escaped too: {1+2} \\{3+4}"+     it "Interpolation" $ [qnb| foo {1+2} |] `shouldBe` "foo {1+2}" -  it "Haddock example" $+  it "Haddock example" $ do+    [qnb| foo {'b':'a':'r':""}+          baz |] `shouldBe` "foo {'b':'a':'r':\"\"}\nbaz"     [qnb| foo           {'b':'a':'r':""}           baz |] `shouldBe` "foo\n{'b':'a':'r':\"\"}\nbaz"--  it "Escaping backslash itself when it makes sense" $ do-    [qnb| foo\nbar  |] `shouldBe` "foo\nbar"-    [qnb| foo\\nbar |] `shouldBe` "foo\\nbar"-    [qnb| foo\tbar  |] `shouldBe` "foo\tbar"-    [qnb| foo\\tbar |] `shouldBe` "foo\\tbar"-    [qnb| foo\	bar |] `shouldBe` "foo\tbar"-    [qnb| foo\\	bar |] `shouldBe` "foo\\\tbar"-    [qnb| foo\ bar  |] `shouldBe` "foo bar"-    [qnb| foo\\ bar |] `shouldBe` "foo\\ bar"--    [qnb| foo\-          bar  |] `shouldBe` "foobar"-    [qnb| foo\\-          bar  |] `shouldBe` "foo\\\nbar"+    [qnb| foo {'b':'a':'r':""}+        \ baz |] `shouldBe` "foo {'b':'a':'r':\"\"}\n baz"
test/QNS/Spec.hs view
@@ -1,3 +1,6 @@+-- WARNING! Do not remove trailing whitespace or tabs, it's part of the test!+{-# OPTIONS_GHC -fno-warn-tabs #-}+ {-# LANGUAGE PackageImports #-} {-# LANGUAGE QuasiQuotes #-} @@ -56,34 +59,101 @@     it "Fourth (escaping interpolation blocks to show them as text)" $       [qns| {1+2} \{3+4} |] `shouldBe` "{1+2} \\{3+4}" -    it "Example of `qns` QuasiQuoter" $-      [qns| foo {1+2} |] `shouldBe` "foo {1+2}"+  it "Empty string" $ [qns|  |] `shouldBe` ""    it "Type annotation in interpolation block" $     [qns|{10 :: Float}|] `shouldBe` "{10 :: Float}" -  it "Escaping interpolation symbols inside interpolation block" $ do-    [qns|foo {"b{a{r"} baz|] `shouldBe` "foo {\"b{a{r\"} baz"-    [qns|foo {"b\}a\}r"} baz|] `shouldBe` "foo {\"b\\}a\\}r\"} baz"+  describe "Escaping" $ do -  it "Example from generated docs (double-space)" $-    [qns| foo {'b':'a':'r':""}-        \ baz |] `shouldBe` "foo {'b':'a':'r':\"\"}  baz"+    it "Escaping interpolation symbols inside interpolation block" $ do+      [qns|foo {"b{a{r"} baz|] `shouldBe` "foo {\"b{a{r\"} baz"+      [qns|foo {"b\}a\}r"} baz|] `shouldBe` "foo {\"b\\}a\\}r\"} baz" -  it "Escaping backslashes" $ do [qns| foo\bar |]    `shouldBe` "foo\\bar"-                                 [qns| foo\\bar |]   `shouldBe` "foo\\bar"-                                 [qns| foo\\\bar |]  `shouldBe` "foo\\\\bar"-                                 [qns| foo\\\\bar |] `shouldBe` "foo\\\\bar"+    it "Escaping backslashes" $ do [qns| foo\bar |]    `shouldBe` "foo\\bar"+                                   [qns| foo\\bar |]   `shouldBe` "foo\\bar"+                                   [qns| foo\\\bar |]  `shouldBe` "foo\\\\bar"+                                   [qns| foo\\\\bar |] `shouldBe` "foo\\\\bar" -  it "Empty string" $ [qns|  |] `shouldBe` ""+    it "Escaping space by backslash at EOL after space\+       \ (line break is cutted off)" $+      [qns| foo \+            bar |] `shouldBe` "foo bar" -  it "Escaping space by backslash at EOL after space (line break is cutted off)" $-    [qns| foo \-          bar |] `shouldBe` "foo bar"+    it "Escaped spaces at the edges" $ do [qns| foo\ |] `shouldBe` "foo "+                                          [qns|\ foo |] `shouldBe` " foo" -  it "Escaped spaces at the edges" $ do [qns| foo\ |] `shouldBe` "foo "-                                        [qns|\ foo |] `shouldBe` " foo"+    it "Escaping backslash itself when it makes sense" $ do+      [qns| foo\nbar  |] `shouldBe` "foo\nbar"+      [qns| foo\\nbar |] `shouldBe` "foo\\nbar"+      [qns| foo\tbar  |] `shouldBe` "foo\tbar"+      [qns| foo\\tbar |] `shouldBe` "foo\\tbar"+      [qns| foo\	bar |] `shouldBe` "foo\tbar"+      [qns| foo\\	bar |] `shouldBe` "foo\\\tbar"+      [qns| foo\ bar  |] `shouldBe` "foo bar"+      [qns| foo\\ bar |] `shouldBe` "foo\\ bar" +      [qns| foo\+            bar  |] `shouldBe` "foobar"+      [qns| foo\\+            bar  |] `shouldBe` "foo\\ bar"++    -- By 'not really' it means we just shows here what happens with examples+    -- for QMS when we use them with QNS quoter.+    describe "Escaping inside interpolation blocks (not really!)" $ do++      it "Line-breaks must be interpreted as just haskell code\+         \ (not really!)" $ do+        [qns| {'\n'}          |] `shouldBe` "{'\n'}"+        [qns| {"foo\nbar"}    |] `shouldBe` "{\"foo\nbar\"}"+        [qns| {"foo\\nbar"}   |] `shouldBe` "{\"foo\\nbar\"}"+        [qns| {"foo\\\nbar"}  |] `shouldBe` "{\"foo\\\nbar\"}"+        [qns| {"foo\\\\nbar"} |] `shouldBe` "{\"foo\\\\nbar\"}"++      it "Escaping for multiline strings" $ do+        [qns| {"foo\+               \bar\+               \baz"} |] `shouldBe` "{\"foo\\bar\\baz\"}"+        [qns| {"foo \+               \bar\+               \ baz"} |] `shouldBe` "{\"foo \\bar baz\"}"+        [qns| x  \+              {"foo \+              \bar\+              \ baz"}  \+              y |] `shouldBe` "x  {\"foo \\bar baz\"}  y"++      it "Escaping of close-bracket '}'" $ do+        [qns| { testFoo {testBar = 9000\} } |]+          `shouldBe` "{ testFoo {testBar = 9000\\} }"+        [qns| foo{ testFoo {testBar = 9000\} }bar |]+          `shouldBe` "foo{ testFoo {testBar = 9000\\} }bar"+        [qns|foo{testFoo2 {test1 = (test1 testFoo2) {testBar = 9000\}\}}bar|]+          `shouldBe`+            "foo{testFoo2 {test1 = (test1 testFoo2) {testBar = 9000\\}\\}}bar"+        [qns| foo { testFoo2 {+                test1 = (test1 testFoo2)+                        { testBar = 9000 \}+                            \}+                  } bar |]+          `shouldBe` "foo { testFoo2 { test1 = (test1 testFoo2)\+                     \ { testBar = 9000 \\} \\} } bar"+        [qns| {"\}"}   |] `shouldBe` "{\"\\}\"}"+        [qns| {"\\\}"} |] `shouldBe` "{\"\\\\}\"}"+        [qns| {123}}   |] `shouldBe` "{123}}"++      it "When interpolation block is escaped\+         \ everything must be interpreted as usual (not really)" $ do+        [qns| \{ foo\nbar\\baz\} } |] `shouldBe` "\\{ foo\nbar\\baz\\} }"+        [qns| \{ foo\+                 bar } |] `shouldBe` "\\{ foobar }"++      it "Tabs characters in string inside interpolation block\+         \ (not really)" $ do+        [qns| {"foo\t\tbar" } |] `shouldBe` "{\"foo\t\tbar\" }"+        [qns| {"foo		bar"  } |] `shouldBe` "{\"foo\t\tbar\"  }"+        [qns| {"foo\\t\tbar"} |] `shouldBe` "{\"foo\\t\tbar\"}"+   describe "Tabs as indentation" $ do      it "Tabs is only indentation at left side" $ do@@ -124,7 +194,13 @@    describe "New README examples" $ do -    it "Simple usage example" $ do+    it "First example" $+      [qns| Hello,+            world!+            Pi is {floor pi}.{floor $ (pi - 3) * 100}… |]+        `shouldBe` "Hello, world! Pi is {floor pi}.{floor $ (pi - 3) * 100}…"++    it "Simple usage example" $       [qns|         <article>           <h1>{title}</h1>@@ -134,24 +210,44 @@         `shouldBe`           "<article> <h1>{title}</h1> <p>{text}</p> </article>" +    it "Can escape spaces" $+      [qns|   you can escape spaces+            \ when you need them    |]+        `shouldBe`+          "you can escape spaces  when you need them"++    -- By 'not really' it means that it just copied from `QM` and shows what+    -- happens with the same input if you use it with this quoter.+    it "Indentation and line breaks are ignored (not really)" $+      [qns|+              indentation and li+        ne bre+         aks are i+             gno+           red+             (not really)+      |]+      `shouldBe` "indentation and li ne bre aks are i gno red (not really)"++    it "Escaping indentation or line breaks" $+      [qns|  \  You can escape indentation or\n+                line breaks when you need them! \  |]+        `shouldBe`+          "  You can escape indentation or\n line breaks when you need them!  "++    it "Interpolation blocks can be escaped too" $+      [qns| Interpolation blocks can be escaped too: {1+2} \{3+4} |]+        `shouldBe`+          "Interpolation blocks can be escaped too: {1+2} \\{3+4}"+     it "Interpolation" $ [qns| foo {1+2} |] `shouldBe` "foo {1+2}" -  it "Haddock example" $+  it "Haddock example" $ do+    [qns| foo {'b':'a':'r':""}+          baz |] `shouldBe` "foo {'b':'a':'r':\"\"} baz"     [qns| foo           {'b':'a':'r':""}           baz |] `shouldBe` "foo {'b':'a':'r':\"\"} baz"--  it "Escaping backslash itself when it makes sense" $ do-    [qns| foo\nbar  |] `shouldBe` "foo\nbar"-    [qns| foo\\nbar |] `shouldBe` "foo\\nbar"-    [qns| foo\tbar  |] `shouldBe` "foo\tbar"-    [qns| foo\\tbar |] `shouldBe` "foo\\tbar"-    [qns| foo\	bar |] `shouldBe` "foo\tbar"-    [qns| foo\\	bar |] `shouldBe` "foo\\\tbar"-    [qns| foo\ bar  |] `shouldBe` "foo bar"-    [qns| foo\\ bar |] `shouldBe` "foo\\ bar"--    [qns| foo\-          bar  |] `shouldBe` "foobar"-    [qns| foo\\-          bar  |] `shouldBe` "foo\\ bar"+    -- Double-space with escaping+    [qns| foo {'b':'a':'r':""}+        \ baz |] `shouldBe` "foo {'b':'a':'r':\"\"}  baz"