packages feed

http-api-data-qq-0.1.0.1: src/Web/HttpApiData/QQ.hs

{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TemplateHaskellQuotes #-}

module Web.HttpApiData.QQ (
  url,
) where

import Data.String (fromString)
import qualified Data.Text as Text
import Language.Haskell.TH
import Language.Haskell.TH.Quote (QuasiQuoter (..))
import Web.HttpApiData (toUrlPiece)

import Web.HttpApiData.QQ.Parser

-- |
-- A quasiquoter to build a URL by interpolating values via ToHttpApiData.
-- The resulting value can be any IsString type.
--
-- Currently only supports single variable names being interpolated, not
-- arbitrary Haskell expressions.
--
-- Usage:
--
-- >>> [url|/foo/#{fooId}/bar|]
url :: QuasiQuoter
url =
  QuasiQuoter
    { quoteExp = toExpQ . either error id . parseUrlPieces
    , quotePat = error "'url' quasiquoter cannot be used as a pattern"
    , quoteType = error "'url' quasiquoter cannot be used as a type"
    , quoteDec = error "'url' quasiquoter cannot be used as a declaration"
    }
  where
    -- convert parsed URL pieces into the ExpQ to inject
    toExpQ = appE [|fromString . concat|] . listE . map urlPieceToExpQ
    urlPieceToExpQ = \case
      InterpolatedName name -> appE [|Text.unpack . toUrlPiece|] . varE . mkName $ name
      RawString s -> litE . stringL $ s