{- 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 = ""