{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TypeFamilies #-} {-# OPTIONS_HADDOCK not-home #-} module Data.Text.Format.Simple.Internal where import Control.Applicative import Data.Attoparsec.Combinator import Data.Attoparsec.Text as A import Data.Either import qualified Data.Foldable as F import Data.String import Data.Text (Text) import qualified Data.Text as T import GHC.Exts -- | The name of a referenced variable. type Name = Text data Part = String Text | NamedVar Name deriving Eq -- | A precompiled format string. Can be used to render several times. newtype Compiled = Compiled { unCompiled :: [Part] } deriving Eq instance Show Compiled where show = show . T.unpack . T.concat . map f . unCompiled where f (String s) = s f (NamedVar n) = "${" `mappend` n `mappend` "}" instance IsString Compiled where fromString = either error id . Data.Text.Format.Simple.Internal.parse . fromString parse :: Text -> Either String Compiled parse = parseOnly parser parser :: Parser Compiled parser = Compiled <$> partParser `manyTill` endOfInput partParser :: Parser Part partParser = NamedVar <$> parseVar <|> String <$> parseString parseVar :: Parser Name parseVar = do char '$' char '{' str <- A.takeWhile (/= '}') char '}' return str parseString :: Parser Text parseString = do str <- A.takeWhile (/= '$') rest <- (lookAhead (string "${") >> return "") <|> (T.cons <$> char '$' <*> parseString) <|> return "" return $ str `mappend` rest