packages feed

interpolatedstring-perl6 (empty) → 0.1

raw patch · 5 files changed

+178/−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,18 @@+Copyright 2009 by Audrey Tang++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to+deal in the Software without restriction, including without limitation the+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+sell copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:+  +The above copyright notice and this permission notice shall be included in+all copies or substantial portions of the Software.+   +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL+THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ 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-perl6.cabal view
@@ -0,0 +1,21 @@+Name:          interpolatedstring-perl6+Version:       0.1+License:       BSD3+License-file:  LICENSE+Category:      Data+Author:        Audrey Tang+Copyright:     Audrey Tang+Maintainer:    Audrey Tang <audreyt@audreyt.org>+Stability:     unstable+Cabal-Version: >= 1.2+Build-Depends: base+Build-Type:    Custom+Synopsis:      QuasiQuoter for Perl6-style multi-line interpolated strings.+Description:   QuasiQuoter for Perl6-style multi-line interpolated strings.+Data-Files:    tests/Test.hs++library+    extensions:      TemplateHaskell, TypeSynonymInstances, FlexibleInstances, UndecidableInstances, OverlappingInstances+    build-depends:   base < 5, template-haskell, haskell-src-meta+    hs-source-dirs:  src+    exposed-modules: Text.InterpolatedString.Perl6
+ src/Text/InterpolatedString/Perl6.hs view
@@ -0,0 +1,98 @@+{-# LANGUAGE TemplateHaskell, TypeSynonymInstances, FlexibleInstances, UndecidableInstances, OverlappingInstances #-}
+
+-- | QuasiQuoter for interpolated strings using Perl 6 syntax.
+--
+--   The "q" form does one thing and does it well: It contains a multi-line string with
+--   no interpolation at all:
+--
+-- @
+-- {-# LANGUAGE QuasiQuotes, ExtendedDefaultRules #-}
+-- import Text.InterpolatedString.Perl6 (q)
+-- foo :: String
+-- foo = [$q|
+-- 
+-- Well here is a
+--     multi-line string!
+-- 
+-- |]
+-- @
+--
+-- The "qc" form interpolates curly braces: Expressions inside {} will be
+-- directly interpolated if it's a String, or have 'show' called if it is not.
+--
+-- Escaping of '{' is done with backslash.
+--
+-- For interpolating numeric expressions without an explicit type signature,
+-- use the ExtendedDefaultRules language pragma, as shown below:
+--
+-- @
+-- {-# LANGUAGE QuasiQuotes, ExtendedDefaultRules #-}
+-- import Text.InterpolatedString.Perl6 (qc)
+-- bar :: String
+-- bar = [$qc| Well {\"hello\" ++ \" there\"} {6 * 7} |]
+-- @
+--
+-- bar will have the value \" Well hello there 42 \".
+--
+-- If you want control over how 'show' works on your types, define a custom
+-- 'ShowQ' instance:
+--
+-- @
+-- import Text.InterpolatedString.Perl6 (qc, ShowQ(..))
+-- instance ShowQ ByteString where
+--     showQ = unpack
+-- @
+--
+-- That way you interpolate bytestrings will not result in double quotes or
+-- character escapes.
+--
+module Text.InterpolatedString.Perl6 (qc, q, ShowQ(..)) where
+
+import qualified Language.Haskell.TH as TH
+import Language.Haskell.TH.Quote
+import Language.Haskell.Meta.Parse
+
+class Show a => ShowQ a where
+    showQ :: a -> String
+
+instance ShowQ Char where
+    showQ = (:[])
+
+instance ShowQ String where
+    showQ = id
+
+instance (Show a) => ShowQ a where
+    showQ = show
+
+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 [| (++) (showQ $(reify a)) |] $ makeExpr xs
+
+reify s = 
+    case parseExp s of
+        Left s  -> TH.report True s >> [| "" |]
+        Right e ->  return e
+
+-- | QuasiQuoter for interpolating Haskell values into a string literal. The pattern portion is undefined.
+qc :: QuasiQuoter
+qc = QuasiQuoter (makeExpr . parseStr [] . filter (/= '\r'))
+    $ error "Cannot use qc as a pattern"
+
+q :: QuasiQuoter
+q = QuasiQuoter ((\a -> [|a|]) . filter (/= '\r'))
+    $ error "Cannot use q as a pattern"
+
+ tests/Test.hs view
@@ -0,0 +1,35 @@+{-# LANGUAGE QuasiQuotes, ExtendedDefaultRules #-}++module Main where++import Text.InterpolatedString.Perl6+import Test.HUnit++data Foo = Foo Int String deriving Show++t1 = "字元"++testEmpty       = assertBool "" ([$qc||] == "")+testCharLiteral = assertBool "" ([$qc|{1+2}|] == "3")+testString      = assertBool "" ([$qc|a string {t1} is here|] == "a string 字元 is here")+testEscape      = assertBool "" ([$qc|#\{}|] == "#{}" && [$qc|\{}|] == "{}")+testComplex     = assertBool "" ([$qc|+        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 "Character Literal" $ TestCase testCharLiteral+    , TestLabel "String Variable" $ TestCase testString+    , TestLabel "Escape Sequences" $ TestCase testEscape+    , TestLabel "Complex Expression" $ TestCase testComplex+    ]++main = runTestTT tests+