IStr (empty) → 0.1.0.0
raw patch · 4 files changed
+126/−0 lines, 4 filesdep +basedep +haskell-src-metadep +template-haskell
Dependencies added: base, haskell-src-meta, template-haskell
Files
- CHANGELOG.md +5/−0
- IStr.cabal +36/−0
- LICENSE +20/−0
- src/Text/IStr.hs +65/−0
+ CHANGELOG.md view
@@ -0,0 +1,5 @@+# Revision history for IStr++## 0.1.0.0 -- YYYY-mm-dd++* First version. Released on an unsuspecting world.
+ IStr.cabal view
@@ -0,0 +1,36 @@+cabal-version: 3.0+name: IStr+version: 0.1.0.0+synopsis:+ String Interpolation of Haskell expressions using #{expr} syntax +description:+ Easy string interpolation of arbitrary haskell expressions.++ This is done using a custom class similar to Show except that with IStr except that it doesn't escape instances of IsString.+license: MIT+license-file: LICENSE+author: lazyLambda+maintainer: galen.sprout@gmail.com+-- copyright:+category: Text+build-type: Simple+extra-doc-files: CHANGELOG.md+-- extra-source-files:++source-repository head+ type: git+ location: https://github.com/augyg/IStr +common warnings+ ghc-options: -Wall++library+ import: warnings+ exposed-modules: Text.IStr+ -- other-modules:+ -- other-extensions:+ + build-depends: base >= 4.20.2 && < 4.21+ , template-haskell >= 2.22.0 && < 2.23+ , haskell-src-meta >= 0.8.15 && < 0.9+ hs-source-dirs: src+ default-language: Haskell2010
+ LICENSE view
@@ -0,0 +1,20 @@+Copyright (c) 2025 lazyLambda++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 OR COPYRIGHT HOLDERS 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.
+ src/Text/IStr.hs view
@@ -0,0 +1,65 @@+{-# LANGUAGE TemplateHaskell #-}+module Text.IStr where++import Language.Haskell.TH+import Language.Haskell.TH.Quote+import Language.Haskell.Meta.Parse+import Debug.Trace++import qualified Language.Haskell.TH as TH++debug :: QuasiQuoter+debug = QuasiQuoter traceExp undefined undefined undefined++-- | e.g. traceExp "1+x" -> [| trace "1+x = $([|1+x|])" (1+x) |]+-- (or something)+traceExp :: String -> Q Exp+traceExp s = [|( trace $(showExp s) $(parseE s) )|]++-- | e.g. showExp "1+x" -> [| "1+x" ++ " = " ++ show (1+x) |]+showExp :: String -> Q Exp+showExp s = [|( $(stringE s) ++ " = " ++ show $(parseE s) )|]++-- | e.g. parseE "1+x" -> (UInfixE (LitE (IntegerL 1)) (VarE +) (VarE x))+parseE :: String -> Q Exp+parseE = return . either (const undefined) id . parseExp+++data StringPart = Literal String | AntiQuote String deriving Show++parseHaskell :: String -> String -> [StringPart]+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 :: String -> String -> [StringPart]+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 :: [StringPart] -> ExpQ+makeExpr [] = [| "" |]+makeExpr ((Literal a):xs) = TH.appE [| (++) a |] (makeExpr xs)+makeExpr ((AntiQuote a):xs) = TH.appE [| (++) (trimQuotes (show $(reifyStringToHaskell a))) |] (makeExpr xs)++trimQuotes :: String -> String +trimQuotes s = reverse $ dropWhile (== '"') $ reverse $ dropWhile (== '"') s++reifyStringToHaskell :: String -> Q Exp+reifyStringToHaskell s = + case parseExp s of+ Left s' -> TH.reportError s' >> [| "" |]+ Right e -> return e++rstrExp :: String -> ExpQ+rstrExp s = makeExpr $ parseStr [] $ filter (/= '\r') s++istr :: QuasiQuoter+istr = QuasiQuoter rstrExp undefined undefined undefined+++