packages feed

http-api-data-qq-0.1.0.0: 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