packages feed

interpolatedstring-qq (empty) → 0.1

raw patch · 5 files changed

+136/−0 lines, 5 filesdep +basedep +haskell-src-metadep +template-haskellbuild-type:Customsetup-changed

Dependencies added: base, haskell-src-meta, template-haskell

Files

+ LICENSE view
@@ -0,0 +1,26 @@+Copyright (c) Erik Charlebois.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. The names of the author may not be used to endorse or promote
+   products derived from this software without specific prior written
+   permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,6 @@+import Distribution.Simple
+import System.Cmd(system)
+
+main = defaultMainWithHooks $ simpleUserHooks { runTests = runElfTests }
+
+runElfTests a b pd lb = system "runhaskell -i./src ./tests/Test.hs" >> return ()
+ interpolatedstring-qq.cabal view
@@ -0,0 +1,21 @@+Name:          interpolatedstring-qq
+Version:       0.1
+License:       BSD3
+License-file:  LICENSE
+Category:      Data
+Author:        Erik Charlebois
+Copyright:     Erik Charlebois
+Maintainer:    Erik Charlebois <erikcharlebois@gmail.com>
+Stability:     unstable
+Cabal-Version: >= 1.2
+Build-Depends: base
+Build-Type:    Custom
+Synopsis:      QuasiQuoter for Ruby-style multi-line interpolated strings.
+Description:   QuasiQuoter for Ruby-style multi-line interpolated strings.
+Data-Files:    tests/Test.hs
+
+library
+    extensions:      TemplateHaskell
+    build-depends:   base, template-haskell, haskell-src-meta
+    hs-source-dirs:  src
+    exposed-modules: Text.InterpolatedString.QQ
+ src/Text/InterpolatedString/QQ.hs view
@@ -0,0 +1,48 @@+{-# LANGUAGE TemplateHaskell #-}
+
+-- | QuasiQuoter for interpolated strings using Ruby syntax. Expressions inside #{} will have
+-- 'show' called. Multi-line strings are supported. Escaping of '#' and '{' is done with backslash.
+--
+-- @
+-- v :: String
+-- v = [$istr| well \#{\"hello\" ++ \" there\"} \#{6*7}]
+-- @
+--
+-- v will have the value \" well hello there 42\"
+module Text.InterpolatedString.QQ (istr) where
+
+import qualified Language.Haskell.TH as TH
+import Language.Haskell.TH.Quote
+import Language.Haskell.Meta.Parse
+
+data StringPart = Literal String | AntiQuote String deriving Show
+
+parseHaskell a []          = [Literal (reverse a)]
+parseHaskell a ('\\':x:xs) = parseHaskell (x:a) xs
+parseHaskell a ('\\':[])   = parseHaskell ('\\':a) []
+parseHaskell a ('}':xs)    = AntiQuote (reverse a) : parseStr [] xs
+parseHaskell a (x:xs)      = parseHaskell (x:a) xs
+
+parseStr a []           = [Literal (reverse a)]
+parseStr a ('\\':x:xs)  = parseStr (x:a) xs
+parseStr a ('\\':[])    = parseStr ('\\':a) []
+parseStr a ('#':'{':xs) = Literal (reverse a) : parseHaskell [] xs
+parseStr a (x:xs)       = parseStr (x:a) xs
+
+makeExpr [] = [| "" |]
+makeExpr ((Literal a):xs)   = TH.appE [| (++) a |] (makeExpr xs)
+makeExpr ((AntiQuote a):xs) = TH.appE [| (++) (trimQuotes (show $(reifyStringToHaskell a))) |] (makeExpr xs)
+
+trimQuotes s = reverse $ dropWhile (== '"') $ reverse $ dropWhile (== '"') s
+
+reifyStringToHaskell s = 
+    case parseExp s of
+        Left s  -> TH.report True s >> [| "" |]
+        Right e ->  return e
+
+rstrExp s = makeExpr $ parseStr [] $ filter (/= '\r') s
+
+-- | QuasiQuoter for interpolating Haskell values into a string literal. The pattern portion is undefined.
+istr :: QuasiQuoter
+istr = QuasiQuoter rstrExp undefined
+
+ tests/Test.hs view
@@ -0,0 +1,35 @@+{-# LANGUAGE QuasiQuotes #-}++module Main where++import Text.InterpolatedString.QQ+import Test.HUnit++data Foo = Foo Int String deriving Show++t1 = "value"++testEmpty = assertBool "" ([$istr||] == "")+testNumLiteral = assertBool "" ([$istr|#{3}|] == "3")+testString     = assertBool "" ([$istr|a string #{t1} is here|] == "a string value is here")+testEscape     = assertBool "" ([$istr|#\{}|] == "#{}" && [$istr|\#{}|] == "#{}")+testComplex    = assertBool "" ([$istr|+        ok+#{Foo 4 "Great!" : [Foo 3 "Scott!"]}+        then+|] == ("\n" +++    "        ok\n" +++    "[Foo 4 \"Great!\",Foo 3 \"Scott!\"]\n" +++    "        then\n"))+++tests = TestList+    [ TestLabel "Empty String" $ TestCase testEmpty+    , TestLabel "Number Literal" $ TestCase testNumLiteral+    , TestLabel "String Variable" $ TestCase testString+    , TestLabel "Escape Sequences" $ TestCase testEscape+    , TestLabel "Complex Expression" $ TestCase testComplex+    ]++main = runTestTT tests+