forked from OSS/graphql-spice
50 lines
1.7 KiB
Haskell
50 lines
1.7 KiB
Haskell
{- This Source Code Form is subject to the terms of the Mozilla Public License,
|
|
v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
|
obtain one at https://mozilla.org/MPL/2.0/. -}
|
|
|
|
module Language.GraphQL.TH
|
|
( gql
|
|
) where
|
|
|
|
import Language.Haskell.TH
|
|
( Exp(..)
|
|
, Lit(..)
|
|
)
|
|
import Language.Haskell.TH.Quote (QuasiQuoter(..))
|
|
|
|
stripIndentation :: String -> String
|
|
stripIndentation code = reverse
|
|
$ dropWhile isLineBreak
|
|
$ reverse
|
|
$ unlines
|
|
$ indent spaces <$> lines' withoutLeadingNewlines
|
|
where
|
|
indent 0 xs = xs
|
|
indent count (' ' : xs) = indent (count - 1) xs
|
|
indent _ xs = xs
|
|
withoutLeadingNewlines = dropWhile isLineBreak code
|
|
spaces = length $ takeWhile (== ' ') withoutLeadingNewlines
|
|
lines' "" = []
|
|
lines' string =
|
|
let (line, rest) = break isLineBreak string
|
|
reminder =
|
|
case rest of
|
|
[] -> []
|
|
'\r' : '\n' : strippedString -> lines' strippedString
|
|
_ : strippedString -> lines' strippedString
|
|
in line : reminder
|
|
isLineBreak = flip any ['\n', '\r'] . (==)
|
|
|
|
-- | Removes leading and trailing newlines. Indentation of the first line is
|
|
-- removed from each line of the string.
|
|
gql :: QuasiQuoter
|
|
gql = QuasiQuoter
|
|
{ quoteExp = pure . LitE . StringL . stripIndentation
|
|
, quotePat = const
|
|
$ fail "Illegal gql QuasiQuote (allowed as expression only, used as a pattern)"
|
|
, quoteType = const
|
|
$ fail "Illegal gql QuasiQuote (allowed as expression only, used as a type)"
|
|
, quoteDec = const
|
|
$ fail "Illegal gql QuasiQuote (allowed as expression only, used as a declaration)"
|
|
}
|