Ignoring leading whitespace in the "lazy-text" quasiquoter in Haskell Text.Shakespeare.Text

161 views Asked by At

I am writing a Haskell command line program and using the lt quasiquoter ("lazy-text") from Text.Shakespeare.Text. In the Yesod book, it says that the hamlet quasiquoter ignores leading whitespace if the first non-whitespace character is a backslash (\).

Does this work in the lt quasiquoter?

My code looks like this:

[lt|Usage: #{programName} [OPTION ...]
   \Version #{showVersion version}|]

but the output is

Usage: MyProg [OPTION ...]
    \Version 0.1.0.0

with the Version string indented too far (and still containing the backslash). I also tried it with a space between the backslash and V.

Is this possible with shakespeare-text?

1

There are 1 answers

1
David Miani On BEST ANSWER

It doesn't appear to, however it isn't hard to add the feature yourself. lt is just a QuasiQuoter, which is the data type:

QuasiQuoter {
   quoteExp :: String -> Q Exp
 , quotePat :: String -> Q Pat
 , quoteType :: String -> Q Type
 , quoteDec :: String -> Q [Dec]
}

They take a String, and return the appropriate template haskell type (depending on the context it is used in.

It is a simple matter to transform a string so it works as you described with a regex:

stripWhiteSpaceBeforeBackslash :: String -> String
stripWhiteSpaceBeforeBackslash str = subRegex (mkRegex "^[[:space:]]*\\\\") str ""

Also, a function that transforms a QuasiQuoter with a string transform function is simple:

transformQuasiQuoter :: (String -> String) -> QuasiQuoter -> QuasiQuoter
transformQuasiQuoter transform quasi = QuasiQuoter {
    quoteExp = (quoteExp quasi) . transform
  , quotePat = (quotePat quasi) . transform
  , quoteType = (quoteType quasi) . transform
  , quoteDec =  (quoteDec quasi) . transform
  }

Now you can make a version of lt that does what you need:

lt_ = transformQuasiQuoter stripWhiteSpaceBeforeBackslash lt

Using it works as expected:

programName = "SomeProgram"
showVersion _ = "42.42.42"
version = 34

x = [lt_|Usage: #{programName} [OPTIONS...]
        \Version #{showVersion version}|]

x evaluates to "Usage: SomeProgram [OPTIONS...]\nVersion 42.42.42" in ghci.