{-# LANGUAGE OverloadedStrings, CPP #-} module Text.Inject ( inject #ifdef TEST , Element (..) , pBraces #endif ) where import Prelude hiding (takeWhile) import Control.Applicative import Data.Text (Text) import qualified Data.Text as T import Data.Attoparsec.Text import Util type Template = [Element] data Element = Plain Text | Braces Text deriving (Eq, Show) inject :: Text -> IO Text inject = fmap T.concat . mapM f . parseTemplate where f :: Element -> IO Text f element = case element of Plain text -> return text Braces cmd -> system (T.unpack cmd) parseTemplate :: Text -> Template parseTemplate = either parseError id . parseOnly (pTemplate <* endOfInput) where parseError = (error . unwords) [ "Parsing failed." , "This should never happen" , "Please report a bug!" ] pTemplate :: Parser Template pTemplate = many (pBraces <|> (Plain <$> pText)) pText :: Parser Text pText = T.cons <$> anyChar <*> takeWhile (/= '{') pBraces :: Parser Element pBraces = Braces . T.init <$> ("{{" *> scan 0 f <* "}") where f 0 '}' = Just 1 f 1 '}' = Nothing f _ _ = Just (0 :: Int)