goldplate-0.1.1: src/Text/Splice.hs
module Text.Splice
( SpliceEnv
, MissingEnvVar (..)
, splice
) where
import Control.Exception (Exception)
import qualified Data.List as List
import Data.Typeable (Typeable)
-- | Environment for splicing in things.
type SpliceEnv = [(String, String)]
data MissingEnvVar = MissingEnvVar String
deriving (Typeable)
instance Show MissingEnvVar where
show (MissingEnvVar k) = "Missing environment variable: " ++ k
instance Exception MissingEnvVar
-- | Splice in a string with "Hello ${FOO}" syntax.
splice :: SpliceEnv -> String -> Either MissingEnvVar String
splice env = go
where
go str = case break (== '$') str of
-- Splice
(xs, '$' : '{' : ys) -> case break (== '}') ys of
(key, '}' : zs) -> case lookup key env of
Nothing -> Left $ MissingEnvVar key
Just val -> fmap ((xs ++ val) ++) (go zs)
(_, _) -> fmap ((xs ++ "${") ++) (go ys)
-- Escape
(xs, '$' : '$' : ys) ->
let (dollars, zs) = break (== '{') ys in
if all (== '$') dollars && "{" `List.isPrefixOf` zs
then (xs ++) . (dollars ++) . ("${" ++) <$> go (drop 1 zs)
else (xs ++) . ("$$" ++) <$> go ys
(xs, []) -> Right xs
(xs, (y : ys)) -> (xs ++) . (y :) <$> (go ys)