{-# LANGUAGE CPP #-}
#if __GLASGOW_HASKELL__ >= 802
{-# LANGUAGE Safe #-}
#else
{-# LANGUAGE Trustworthy #-}
#endif
#if __GLASGOW_HASKELL__ >= 800
{-# LANGUAGE TemplateHaskellQuotes #-}
#else
{-# LANGUAGE TemplateHaskell #-}
#endif
module System.Path.QQ
( fspath
, unrooted
) where
import Language.Haskell.TH
import qualified Language.Haskell.TH.Quote as QQ
import qualified System.FilePath.Posix as FP.Posix
import System.Path.Internal
fspath :: QQ.QuasiQuoter
fspath = quoter qfspath
qfspath :: FilePath -> Q Exp
qfspath fp
| FP.Posix.isAbsolute fp = qPath fp [t|Absolute|]
| Just fp' <- atHome fp = qPath fp' [t|HomeDir|]
| otherwise = qPath fp [t|CWD|]
where
atHome :: FilePath -> Maybe FilePath
atHome "~" = Just ""
atHome ('~':sep:fp') | FP.Posix.isPathSeparator sep = Just fp'
atHome _otherwise = Nothing
unrooted :: QQ.QuasiQuoter
unrooted = quoter qunrooted
qunrooted :: FilePath -> Q Exp
qunrooted fp
| FP.Posix.isAbsolute fp = fail "Unrooted path must be relative"
| otherwise = qPath fp [t|Unrooted|]
qPath :: FilePath -> Q Type -> Q Exp
qPath fp qtagTy = do
pathCon <- [|Path|]
pathTy <- [t|Path|]
tagTy <- qtagTy
return (SigE (AppE pathCon (LitE (StringL fp))) (AppT pathTy tagTy))
quoter :: (String -> Q Exp) -> QQ.QuasiQuoter
quoter x = QQ.QuasiQuoter { QQ.quoteExp = x
, QQ.quotePat = \_ -> fail "pattern position not supported"
, QQ.quoteType = \_ -> fail "using as type not supported"
, QQ.quoteDec = \_ -> fail "using as declaration not supported"
}