@@ -62,6 +62,8 @@ data WriterState =
62 , stBook :: Bool -- true if document uses book or memoir class
62 , stBook :: Bool -- true if document uses book or memoir class
63 , stCsquotes :: Bool -- true if document uses csquotes
63 , stCsquotes :: Bool -- true if document uses csquotes
64 , stHighlighting :: Bool -- true if document has highlighted code
64 , stHighlighting :: Bool -- true if document has highlighted code
65+ , stFirstFrame :: Bool -- true til we've written first beamer frame
66+ , stIncremental :: Bool -- true if beamer lists should be displayed bit by bit
67-- | Convert Pandoc to LaTeX.
69-- | Convert Pandoc to LaTeX.
@@ -74,23 +76,24 @@ writeLaTeX options document =
74 stTable = False, stStrikeout = False, stSubscript = False,
76 stTable = False, stStrikeout = False, stSubscript = False,
75 stUrl = False, stGraphics = False,
77 stUrl = False, stGraphics = False,
76 stLHS = False, stBook = writerChapters options,
78 stLHS = False, stBook = writerChapters options,
77− stCsquotes = False, stHighlighting = False }
79+ stCsquotes = False, stHighlighting = False,
80+ stFirstFrame = True, stIncremental = writerIncremental options }
79pandocToLaTeX :: WriterOptions -> Pandoc -> State WriterState String
82pandocToLaTeX :: WriterOptions -> Pandoc -> State WriterState String
80pandocToLaTeX options (Pandoc (Meta title authors date) blocks) = do
83pandocToLaTeX options (Pandoc (Meta title authors date) blocks) = do
81 let template = writerTemplate options
84 let template = writerTemplate options
85+ let templateLines = lines template
82 let usesBookClass x = "\\documentclass" `isPrefixOf` x &&
86 let usesBookClass x = "\\documentclass" `isPrefixOf` x &&
83 ("{memoir}" `isSuffixOf` x || "{book}" `isSuffixOf` x ||
87 ("{memoir}" `isSuffixOf` x || "{book}" `isSuffixOf` x ||
84 "{report}" `isSuffixOf` x)
88 "{report}" `isSuffixOf` x)
85− when (any usesBookClass (lines template)) $
89+ when (any usesBookClass templateLines) $
86 modify $ \s -> s{stBook = True}
90 modify $ \s -> s{stBook = True}
87 -- check for \usepackage...{csquotes}; if present, we'll use
91 -- check for \usepackage...{csquotes}; if present, we'll use
88 -- \enquote{...} for smart quotes:
92 -- \enquote{...} for smart quotes:
89 when ("{csquotes}" `isInfixOf` template) $
93 when ("{csquotes}" `isInfixOf` template) $
90 modify $ \s -> s{stCsquotes = True}
94 modify $ \s -> s{stCsquotes = True}
91− opts <- liftM stOptions get
92− let colwidth = if writerWrapText opts
95+ let colwidth = if writerWrapText options
93− then Just $ writerColumns opts
96+ then Just $ writerColumns options
94 else Nothing
97 else Nothing
95 titletext <- liftM (render colwidth) $ inlineListToLaTeX title
98 titletext <- liftM (render colwidth) $ inlineListToLaTeX title
96 authorsText <- mapM (liftM (render colwidth) . inlineListToLaTeX) authors
99 authorsText <- mapM (liftM (render colwidth) . inlineListToLaTeX) authors
@@ -100,7 +103,10 @@ pandocToLaTeX options (Pandoc (Meta title authors date) blocks) = do
100 else case last blocks of
103 else case last blocks of
101 Header 1 il -> (init blocks, il)
104 Header 1 il -> (init blocks, il)
102 _ -> (blocks, [])
105 _ -> (blocks, [])
106+ blocks'' <- if writerBeamer options
107+ then toSlides blocks'
103− body <- blockListToLaTeX blocks'
109+ body <- blockListToLaTeX blocks''
104 biblioTitle <- liftM (render colwidth) $ inlineListToLaTeX lastHeader
110 biblioTitle <- liftM (render colwidth) $ inlineListToLaTeX lastHeader
105 let main = render colwidth body
111 let main = render colwidth body
106 st <- get
112 st <- get
@@ -119,7 +125,12 @@ pandocToLaTeX options (Pandoc (Meta title authors date) blocks) = do
119 [ ("toc", if writerTableOfContents options then "yes" else "")
125 [ ("toc", if writerTableOfContents options then "yes" else "")
120 , ("body", main)
126 , ("body", main)
121 , ("title", titletext)
127 , ("title", titletext)
122− , ("date", dateText) ] ++
128+ , ("date", dateText)
129+ , ("documentclass", if writerBeamer options
131+ else if writerChapters options
133+ else "article") ] ++
123 [ ("author", a) | a <- authorsText ] ++
134 [ ("author", a) | a <- authorsText ] ++
124 [ ("verbatim-in-note", "yes") | stVerbInNote st ] ++
135 [ ("verbatim-in-note", "yes") | stVerbInNote st ] ++
125 [ ("fancy-enums", "yes") | stEnumerate st ] ++
136 [ ("fancy-enums", "yes") | stEnumerate st ] ++
@@ -132,8 +143,9 @@ pandocToLaTeX options (Pandoc (Meta title authors date) blocks) = do
132 [ ("graphics", "yes") | stGraphics st ] ++
143 [ ("graphics", "yes") | stGraphics st ] ++
133 [ ("book-class", "yes") | stBook st] ++
144 [ ("book-class", "yes") | stBook st] ++
134 [ ("listings", "yes") | writerListings options || stLHS st ] ++
145 [ ("listings", "yes") | writerListings options || stLHS st ] ++
146+ [ ("beamer", "yes") | writerBeamer options ] ++
135 [ ("highlighting-macros", styleToLaTeX
147 [ ("highlighting-macros", styleToLaTeX
136− $ writerHighlightStyle opts ) | stHighlighting st ] ++
148+ $ writerHighlightStyle options ) | stHighlighting st ] ++
137 citecontext
149 citecontext
138 return $ if writerStandalone options
150 return $ if writerStandalone options
139 then renderTemplate context template
151 then renderTemplate context template
@@ -171,6 +183,42 @@ stringToLaTeX isUrl = escapeStringUsing latexEscapes
171inCmd :: String -> Doc -> Doc
183inCmd :: String -> Doc -> Doc
172inCmd cmd contents = char '\\' <> text cmd <> braces contents
184inCmd cmd contents = char '\\' <> text cmd <> braces contents
186+toSlides :: [Block] -> State WriterState [Block]
187+toSlides (Header n ils : bs) = do
188+ tit <- inlineListToLaTeX ils
189+ firstFrame <- gets stFirstFrame
190+ modify $ \s -> s{ stFirstFrame = False }
191+ -- note: [fragile] is required or verbatim breaks
192+ result <- ((Header n ils :) .
193+ (RawBlock "latex" ("\\begin{frame}[fragile]\n" ++
194+ "\\frametitle{" ++ render Nothing tit ++ "}") :))
198+ else return $ RawBlock "latex" "\\end{frame}" : result
199+toSlides (HorizontalRule : Header n ils : bs) =
200+ toSlides (Header n ils : bs)
201+toSlides (HorizontalRule : bs) = do
202+ firstFrame <- gets stFirstFrame
203+ modify $ \s -> s{ stFirstFrame = False }
204+ result <- (RawBlock "latex" "\\begin{frame}[fragile]" :)
208+ else return $ RawBlock "latex" "\\end{frame}" : result
209+toSlides (b:bs) = (b:) `fmap` toSlides bs
211+ firstFrame <- gets stFirstFrame
214+ else return [RawBlock "latex" "\\end{frame}"]
216+isListBlock :: Block -> Bool
217+isListBlock (BulletList _) = True
218+isListBlock (OrderedList _ _) = True
219+isListBlock (DefinitionList _) = True
220+isListBlock _ = False
174-- | Convert Pandoc block element to LaTeX.
222-- | Convert Pandoc block element to LaTeX.
175blockToLaTeX :: Block -- ^ Block to convert
223blockToLaTeX :: Block -- ^ Block to convert
176 -> State WriterState Doc
224 -> State WriterState Doc
@@ -185,8 +233,17 @@ blockToLaTeX (Para lst) = do
185 result <- inlineListToLaTeX lst
233 result <- inlineListToLaTeX lst
186 return $ result <> blankline
234 return $ result <> blankline
187blockToLaTeX (BlockQuote lst) = do
235blockToLaTeX (BlockQuote lst) = do
236+ beamer <- writerBeamer `fmap` gets stOptions
238+ [b] | beamer && isListBlock b -> do
239+ oldIncremental <- gets stIncremental
240+ modify $ \s -> s{ stIncremental = True }
241+ result <- blockToLaTeX b
242+ modify $ \s -> s{ stIncremental = oldIncremental }
188− contents <- blockListToLaTeX lst
245+ contents <- blockListToLaTeX lst
189− return $ "\\begin{quote}" $$ contents $$ "\\end{quote}"
246+ return $ "\\begin{quote}" $$ contents $$ "\\end{quote}"
190blockToLaTeX (CodeBlock (_,classes,keyvalAttr) str) = do
247blockToLaTeX (CodeBlock (_,classes,keyvalAttr) str) = do
191 opts <- gets stOptions
248 opts <- gets stOptions
192 case () of
249 case () of
@@ -243,10 +300,13 @@ blockToLaTeX (CodeBlock (_,classes,keyvalAttr) str) = do
243blockToLaTeX (RawBlock "latex" x) = return $ text x <> blankline
300blockToLaTeX (RawBlock "latex" x) = return $ text x <> blankline
244blockToLaTeX (RawBlock _ _) = return empty
301blockToLaTeX (RawBlock _ _) = return empty
245blockToLaTeX (BulletList lst) = do
302blockToLaTeX (BulletList lst) = do
303+ incremental <- gets stIncremental
304+ let inc = if incremental then "[<+->]" else ""
246 items <- mapM listItemToLaTeX lst
305 items <- mapM listItemToLaTeX lst
247− return $ "\\begin{itemize}" $$ vcat items $$ "\\end{itemize}"
306+ return $ text ("\\begin{itemize}" ++ inc) $$ vcat items $$ "\\end{itemize}"
248blockToLaTeX (OrderedList (start, numstyle, numdelim) lst) = do
307blockToLaTeX (OrderedList (start, numstyle, numdelim) lst) = do
249 st <- get
308 st <- get
309+ let inc = if stIncremental st then "[<+->]" else ""
250 let oldlevel = stOLLevel st
310 let oldlevel = stOLLevel st
251 put $ st {stOLLevel = oldlevel + 1}
311 put $ st {stOLLevel = oldlevel + 1}
252 items <- mapM listItemToLaTeX lst
312 items <- mapM listItemToLaTeX lst
@@ -263,11 +323,13 @@ blockToLaTeX (OrderedList (start, numstyle, numdelim) lst) = do
263 map toLower (toRomanNumeral oldlevel) ++
323 map toLower (toRomanNumeral oldlevel) ++
264 "}{" ++ show (start - 1) ++ "}"
324 "}{" ++ show (start - 1) ++ "}"
265 else empty
325 else empty
266− return $ "\\begin{enumerate}" <> exemplar $$ resetcounter $$
326+ return $ text ("\\begin{enumerate}" ++ inc) <> exemplar $$ resetcounter $$
267 vcat items $$ "\\end{enumerate}"
327 vcat items $$ "\\end{enumerate}"
268blockToLaTeX (DefinitionList lst) = do
328blockToLaTeX (DefinitionList lst) = do
329+ incremental <- gets stIncremental
330+ let inc = if incremental then "[<+->]" else ""
269 items <- mapM defListItemToLaTeX lst
331 items <- mapM defListItemToLaTeX lst
270− return $ "\\begin{description}" $$ vcat items $$ "\\end{description}"
332+ return $ text ("\\begin{description}" ++ inc) $$ vcat items $$ "\\end{description}"
271blockToLaTeX HorizontalRule = return $
333blockToLaTeX HorizontalRule = return $
272 "\\begin{center}\\rule{3in}{0.4pt}\\end{center}" $$ blankline
334 "\\begin{center}\\rule{3in}{0.4pt}\\end{center}" $$ blankline
273blockToLaTeX (Header level lst) = do
335blockToLaTeX (Header level lst) = do