{- This file is part of reformat
Reformat is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 or the License,
or (at your option) any later version.
Reformat is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Yu. If not, see .
-}
{-|
Module: Text.Reformat.Render
Description: Render of Reformat
Copyright: (C) 2018 Johann Lee
License: GPL3
Maintainer: me@qinka.pro
Stability: experimental
Portablility: unknown
-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
module Text.Reformat.Render
( renderFromReformat
) where
import Text.Reformat.Types (Reformat(..), Value(..))
import Text.Parsec
import Text.Printf
data Render = Text String -- ^ Plain text
| Var String String -- ^ variable with name and format
| Nil
deriving (Show,Eq)
-- | parser of variable
parserVar :: Stream String m Char => ParsecT String () m [Render]
parserVar = do
char '$' >> char '{' >> spaces
varName <- many1 (lower <|> digit <|> char '_' <|> char '-')
spaces >> char ':' >> spaces
format <- many1 $ oneOf "cdoxXbufFgGeEs+-0123456789."
spaces >> char '}'
(Var varName ('%':format):) <$> parserRender
-- | parser of text
parserText :: Stream String m Char => ParsecT String () m [Render]
parserText = do
text <- many1 $ noneOf "$"
(Text text:) <$> parserRender
-- | parser of dollar
parserD :: Stream String m Char => ParsecT String () m [Render]
parserD = string "$$" >> (Text "$":) <$> parserRender
-- | parser of string's EOF
parserEOF :: Stream String m Char => ParsecT String () m [Render]
parserEOF = eof >> return [Nil]
-- | parser of render(s)
parserRender :: Stream String m Char => ParsecT String () m [Render]
parserRender = try parserEOF <|> try parserText <|> try parserD <|> parserVar
-- | render the string with given format and item
renderFromReformat :: (Monad m, Reformat t, Str t ~ String)
=> t -- ^ item
-> String -- ^ format string
-> m (Either ParseError String) -- output
renderFromReformat t str = (concat . step <$>) <$> runParserT parserRender () "render format" str
where pair = renderPair t
step [] = []
step (Text s:rs) = s:step rs
step (Var v f:rs) = prt f (pair v):step rs
step (Nil:rs) = step rs
prt f (I i) = printf f i
prt f (R r) = printf f r
prt f (S s) = printf f s
prt _ N = ""