summaryrefslogtreecommitdiff
path: root/src/Text/Pandoc
diff options
context:
space:
mode:
authorfiddlosopher <fiddlosopher@788f1e2b-df1e-0410-8736-df70ead52e1b>2009-12-31 01:14:04 +0000
committerfiddlosopher <fiddlosopher@788f1e2b-df1e-0410-8736-df70ead52e1b>2009-12-31 01:14:04 +0000
commit213895f033e60707123b42f8a780f1a3a9ef6196 (patch)
tree3661f33ed794a36d8cecdf0738f08a5c4ba4ab43 /src/Text/Pandoc
parent3d8cccc7e373f9fd28e0276f7ac513cc089f1450 (diff)
Modified templates to respect indentation.
git-svn-id: https://pandoc.googlecode.com/svn/trunk@1708 788f1e2b-df1e-0410-8736-df70ead52e1b
Diffstat (limited to 'src/Text/Pandoc')
-rw-r--r--src/Text/Pandoc/Templates.hs78
1 files changed, 48 insertions, 30 deletions
diff --git a/src/Text/Pandoc/Templates.hs b/src/Text/Pandoc/Templates.hs
index b8c70c569..69cd5c554 100644
--- a/src/Text/Pandoc/Templates.hs
+++ b/src/Text/Pandoc/Templates.hs
@@ -46,10 +46,11 @@ is used.
module Text.Pandoc.Templates (renderTemplate, getDefaultTemplate) where
import Text.ParserCombinators.Parsec
-import Control.Monad (liftM)
+import Control.Monad (liftM, when)
import qualified Control.Exception as E (try, IOException)
import System.FilePath
import Text.Pandoc.Shared (readDataFile)
+import Data.List (intercalate)
-- | Get the default template, either from the application's user data
-- directory (~/.pandoc on unix) or from the cabal data directory.
@@ -60,51 +61,67 @@ getDefaultTemplate "odt" = getDefaultTemplate "opendocument"
getDefaultTemplate format = do
let format' = takeWhile (/='+') format -- strip off "+lhs" if present
E.try $ readDataFile $ "templates" </> format' <.> "template"
-
+
+data TemplateState = TemplateState Int [(String,String)]
+
+adjustPosition :: String -> GenParser Char TemplateState String
+adjustPosition str = do
+ let lastline = takeWhile (/= '\n') $ reverse str
+ updateState $ \(TemplateState pos x) ->
+ if str == lastline
+ then TemplateState (pos + length lastline) x
+ else TemplateState (length lastline) x
+ return str
+
-- | Renders a template
renderTemplate :: [(String,String)] -- ^ Assoc. list of values for variables
-> String -- ^ Template
-> String
renderTemplate vals templ =
- case runParser (do x <- parseTemplate; eof; return x) vals "template" templ of
+ case runParser (do x <- parseTemplate; eof; return x) (TemplateState 0 vals) "template" templ of
Left e -> error $ show e
Right r -> concat r
reservedWords :: [String]
reservedWords = ["else","endif"]
-parseTemplate :: GenParser Char [(String,String)] [String]
+parseTemplate :: GenParser Char TemplateState [String]
parseTemplate =
- many $ plaintext <|> escapedDollar <|> conditional <|> variable
+ many $ (plaintext <|> escapedDollar <|> conditional <|> variable)
+ >>= adjustPosition
-plaintext :: GenParser Char [(String,String)] String
-plaintext = many1 $ satisfy (/='$')
+plaintext :: GenParser Char TemplateState String
+plaintext = many1 $ noneOf "$"
-escapedDollar :: GenParser Char [(String,String)] String
+escapedDollar :: GenParser Char TemplateState String
escapedDollar = try $ string "$$" >> return "$"
-conditional :: GenParser Char [(String,String)] String
+conditional :: GenParser Char TemplateState String
conditional = try $ do
+ TemplateState pos vars <- getState
string "$if("
id' <- ident
string ")$"
- skipMany (oneOf " \t")
- optional newline
- ifContents <- liftM concat parseTemplate
- elseContents <- option "" $ do try (string "$else$")
- skipMany (oneOf " \t")
- optional newline
- liftM concat parseTemplate
+ -- if newline after the "if", then a newline after "endif" will be swallowed
+ multiline <- option False $ try $
+ newline >> count pos (char ' ') >> return True
+ let conditionSatisfied = case lookup id' vars of
+ Nothing -> False
+ Just "" -> False
+ Just _ -> True
+ contents <- if conditionSatisfied
+ then liftM concat parseTemplate
+ else do
+ parseTemplate -- skip if part, then reset position
+ setState $ TemplateState pos vars
+ option "" $ do try (string "$else$")
+ optional newline
+ liftM concat parseTemplate
string "$endif$"
- skipMany (oneOf " \t")
- optional newline
- st <- getState
- return $ case lookup id' st of
- Just "" -> elseContents
- Just _ -> ifContents
- Nothing -> elseContents
-
-ident :: GenParser Char [(String,String)] String
+ when multiline $ optional $ newline
+ return contents
+
+ident :: GenParser Char TemplateState String
ident = do
first <- letter
rest <- many (alphaNum <|> oneOf "_-")
@@ -113,12 +130,13 @@ ident = do
then pzero
else return id'
-variable :: GenParser Char [(String,String)] String
+variable :: GenParser Char TemplateState String
variable = try $ do
char '$'
id' <- ident
char '$'
- st <- getState
- return $ case lookup id' st of
- Just val -> val
- Nothing -> ""
+ TemplateState pos vars <- getState
+ let indent = replicate pos ' '
+ return $ case lookup id' vars of
+ Just val -> intercalate ('\n' : indent) $ lines val
+ Nothing -> ""