packages feed

interpolatedstring-perl6 0.8.1 → 0.9.0

raw patch · 3 files changed

+93/−27 lines, 3 filesdep +bytestringdep +text

Dependencies added: bytestring, text

Files

interpolatedstring-perl6.cabal view
@@ -1,5 +1,5 @@ Name:          interpolatedstring-perl6-Version:       0.8.1+Version:       0.9.0 License:       BSD3 License-file:  LICENSE Category:      Data@@ -11,7 +11,7 @@ Build-Depends: base Build-Type:    Custom Synopsis:      QuasiQuoter for Perl6-style multi-line interpolated strings-Description:   QuasiQuoter for Perl6-style multi-line interpolated strings with "q", "qq" and "qc" support.+Description:   QuasiQuoter for Perl6-style multi-line interpolated strings with \"q\", \"qq\" and \"qc\" support. Data-Files:    tests/Test.hs  Source-Repository head@@ -20,6 +20,6 @@  library     extensions:      TemplateHaskell, TypeSynonymInstances, FlexibleInstances, UndecidableInstances, OverlappingInstances-    build-depends:   base > 4 && < 5, template-haskell >= 2.5, haskell-src-meta >= 0.3+    build-depends:   base > 4 && < 5, template-haskell >= 2.5, haskell-src-meta >= 0.3, text, bytestring     hs-source-dirs:  src     exposed-modules: Text.InterpolatedString.Perl6
src/Text/InterpolatedString/Perl6.hs view
@@ -1,14 +1,17 @@-{-# LANGUAGE TemplateHaskell, TypeSynonymInstances, FlexibleInstances, UndecidableInstances, OverlappingInstances #-}+{-# LANGUAGE TemplateHaskell, TypeSynonymInstances, FlexibleInstances, +  UndecidableInstances, OverlappingInstances, MultiParamTypeClasses,+  IncoherentInstances+  #-}  -- | 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+-- 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 :: String -- 'Text', 'ByteString' etc also works -- foo = [q| --  -- Well here is a@@ -17,11 +20,14 @@ -- |] -- @ ----- 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.+-- Any instance of the 'IsString' class is permitted. ----- Escaping of '{' is done with backslash.+-- The 'qc' form interpolates curly braces: expressions inside {} will be+-- directly interpolated if it's a 'Char', 'String', 'Text' or 'ByteString', or +-- it will 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 lanuage pragma, as shown below: --@@ -37,16 +43,17 @@ -- If you want control over how 'show' works on your types, define a custom -- 'ShowQ' instance: --+-- For example, this instance allows you to display interpolated lists of strings as +-- a sequence of words, removing those pesky brackets, quotes, and escape sequences.+-- -- @+-- {-\# LANGUAGE FlexibleInstances #-} -- import Text.InterpolatedString.Perl6 (qc, ShowQ(..))--- instance ShowQ ByteString where---     showQ = unpack+-- instance ShowQ [String] where+--     showQ = unwords -- @ ----- That way you interpolate bytestrings will not result in double quotes or--- character escapes.------ The "qq" form adds to the "qc" form with a simple shorthand: '$foo' means '{foo}',+-- The 'qq' form adds to the 'qc' form with a simple shorthand: '$foo' means '{foo}', -- namely interpolating a single variable into the string. -- -- @@@ -55,12 +62,24 @@ -- baz :: String -- baz = [qc| Hello, $who |] --     where---     who = "World"+--     who = \"World\" -- @ ----- The ability to define custom "ShowQ" instances is particularly powerful with--- cascading instances using "qq".+-- Both 'qc' and 'qq' permit output to any types with both 'IsString' and 'Monoid' +-- instances.+-- +-- @+-- {-# LANGUAGE QuasiQuotes, OverloadedStrings #-}+-- import Text.InterpolatedString.Perl6 (qc)+-- import Data.Text (Text)+-- import Data.ByteString.Char8 (ByteString)+-- qux :: ByteString+-- qux = [qc| This will convert {\"Text\" :: Text} to {\"ByteString\" :: ByteString} |]+-- @ --+-- The ability to define custom 'ShowQ' instances is particularly powerful with+-- cascading instances using 'qq'.+-- -- Below is a sample snippet from a script that converts Shape objects into -- AppleScript suitable for drawing in OmniGraffle: --@@ -121,25 +140,65 @@ -- |] -- @ --+ module Text.InterpolatedString.Perl6 (qq, qc, q, ShowQ(..)) where  import qualified Language.Haskell.TH as TH import Language.Haskell.TH.Quote import Language.Haskell.Meta.Parse+import GHC.Exts (IsString(..))+import Data.Monoid (Monoid(..))+import Data.ByteString.Char8 as Strict (ByteString, unpack)+import Data.ByteString.Lazy.Char8 as Lazy (ByteString, unpack)+import Data.Text as T (Text, unpack)+import Data.Text.Lazy as LazyT(Text, unpack) import Data.Char (isAlpha, isAlphaNum) +-- |A class for types that use special interpolation rules.+-- Instances of 'ShowQ' that are also instances of 'IsString' should obey the +-- following law: +--+-- @+-- fromString (showQ s) == s+-- @+--+-- because this library relies on this fact to optimize +-- away needless string conversions. class ShowQ a where     showQ :: a -> String  instance ShowQ Char where     showQ = (:[])-+     instance ShowQ String where     showQ = id -instance (Show a) => ShowQ a where+instance ShowQ Strict.ByteString where+    showQ = Strict.unpack++instance ShowQ Lazy.ByteString where+    showQ = Lazy.unpack++instance ShowQ T.Text where+    showQ = T.unpack++instance ShowQ LazyT.Text where+    showQ = LazyT.unpack++instance Show a => ShowQ a where     showQ = show +-- todo: this should really be rewritten into RULES pragmas, but so far+-- I can't convince GHC to let the rules fire.+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+ data StringPart = Literal String | AntiQuote String deriving Show  unQC a []          = [Literal (reverse a)]@@ -174,13 +233,15 @@ isIdent '\'' = True isIdent x    = isAlphaNum x -makeExpr [] = [| "" |]-makeExpr ((Literal a):xs)   = TH.appE [| (++) a |] $ makeExpr xs-makeExpr ((AntiQuote a):xs) = TH.appE [| (++) (showQ $(reify a)) |] $ makeExpr xs+makeExpr [] = [| mempty |]+makeExpr ((Literal a):xs)   = TH.appE [| mappend (fromString a) |] +                              $ makeExpr xs+makeExpr ((AntiQuote a):xs) = TH.appE [| mappend (toQQ $(reify a)) |] +                              $ makeExpr xs  reify s =      case parseExp s of-        Left s  -> TH.report True s >> [| "" |]+        Left s  -> TH.report True s >> [| mempty |]         Right e ->  return e  -- | QuasiQuoter for interpolating '$var' and '{expr}' into a string literal. The pattern portion is undefined.@@ -199,8 +260,7 @@  -- | QuasiQuoter for a non-interpolating string literal. The pattern portion is undefined. q :: QuasiQuoter-q = QuasiQuoter ((\a -> [|a|]) . filter (/= '\r'))+q = QuasiQuoter ((\a -> [|fromString a|]) . filter (/= '\r'))                  (error "Cannot use q as a pattern")                  (error "Cannot use q as a type")                  (error "Cannot use q as a dec")-
tests/Test.hs view
@@ -4,6 +4,9 @@  import Text.InterpolatedString.Perl6 import Test.HUnit+import GHC.Exts(fromString)+import Data.ByteString.Char8 as BS(ByteString, pack)+import Data.Text as T(Text, pack)  data Foo = Foo Int String deriving Show @@ -22,7 +25,9 @@     "        ok\n" ++     "[Foo 4 \"Great!\",Foo 3 \"Scott!\"]\n" ++     "        then\n"))-+testConvert = assertBool "" +              (([$qc|{fromString "a"::Text} {fromString "b"::ByteString}|] :: String)+               == "a b")  tests = TestList     [ TestLabel "Empty String" $ TestCase testEmpty@@ -31,6 +36,7 @@     , TestLabel "Dollar Variable" $ TestCase testVariable     , TestLabel "Escape Sequences" $ TestCase testEscape     , TestLabel "Complex Expression" $ TestCase testComplex+    , TestLabel "String Conversion" $ TestCase testConvert     ]  main = runTestTT tests