{-# LANGUAGE OverloadedStrings #-}
module Data.Text.Format.Heavy.Parse.Shell
(
parseShellFormat, parseShellFormat',
pShellFormat
) where
import Data.Maybe
import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Lazy.Builder as B
import Text.Parsec
import Data.Text.Format.Heavy.Types
import Data.Text.Format.Heavy.Formats
import Data.Text.Format.Heavy.Parse.Types
anyChar' :: Parser Char
anyChar' =
noneOf "$" <|> try ('$' <$ string "$$")
pVerbatim :: Parser FormatItem
pVerbatim = (FString . TL.pack) `fmap` many1 anyChar'
pVariable :: Parser FormatItem
pVariable = do
char '$'
(name, fmt) <- try bracedVariable <|> unbracedVariable
return $ FVariable (TL.pack name) fmt
where
bracedVariable = between (char '{') (char '}') $ do
name <- many $ try alphaNum <|> try (char '-') <|> char '.'
mbColon <- optionMaybe $ char ':'
fmt <- case mbColon of
Nothing -> return Nothing
Just _ -> do
fmtStr <- many (noneOf "}" <|> try ('}' <$ string "\\}"))
return $ Just $ TL.pack fmtStr
name' <- if null name
then do
st <- getState
let n = psNextIndex st
modifyState $ \st -> st {psNextIndex = psNextIndex st + 1}
return $ show n
else return name
return (name', fmt)
unbracedVariable = do
name <- many1 alphaNum
return (name, Nothing)
pShellFormat :: Parser Format
pShellFormat = Format `fmap` many (try pVariable <|> pVerbatim)
parseShellFormat :: TL.Text -> Either ParseError Format
parseShellFormat text = runParser pShellFormat initParserState "<format string>" text
parseShellFormat' :: TL.Text -> Format
parseShellFormat' text = either (error . show) id $ parseShellFormat text