@@ -20,10 +20,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2020{- |
2121 Module : Text.Pandoc.Writers.LaTeX
2222 Copyright : Copyright (C) 2006-2010 John MacFarlane
23− License : GNU GPL, version 2 or above
23+ License : GNU GPL, version 2 or above
2424
2525 Maintainer : John MacFarlane <jgm@berkeley.edu>
26− Stability : alpha
26+ Stability : alpha
2727 Portability : portable
2828
2929Conversion of 'Pandoc' format into LaTeX.
@@ -41,37 +41,39 @@ import Data.Char ( toLower, isPunctuation )
4141import Control.Monad.State
4242import Text.Pandoc.Pretty
4343import System.FilePath (dropExtension)
44+import Text.Pandoc.Highlighting (highlightLaTeX, defaultLaTeXMacros)
4445
45−data WriterState =
46− WriterState { stInNote :: Bool -- @True@ if we're in a note
47− , stInTable :: Bool -- @True@ if we're in a table
48− , stTableNotes :: [(Char, Doc)] -- List of markers, notes
49− -- in current table
50− , stOLLevel :: Int -- level of ordered list nesting
51− , stOptions :: WriterOptions -- writer options, so they don't have to be parameter
52− , stVerbInNote :: Bool -- true if document has verbatim text in note
53− , stEnumerate :: Bool -- true if document needs fancy enumerated lists
54− , stTable :: Bool -- true if document has a table
55− , stStrikeout :: Bool -- true if document has strikeout
56− , stSubscript :: Bool -- true if document has subscript
57− , stUrl :: Bool -- true if document has visible URL link
58− , stGraphics :: Bool -- true if document contains images
59− , stLHS :: Bool -- true if document has literate haskell code
60− , stBook :: Bool -- true if document uses book or memoir class
61− , stCsquotes :: Bool -- true if document uses csquotes
46+data WriterState =
47+ WriterState { stInNote :: Bool -- true if we're in a note
48+ , stInTable :: Bool -- true if we're in a table
49+ , stTableNotes :: [(Char, Doc)] -- List of markers, notes
50+ -- in current table
51+ , stOLLevel :: Int -- level of ordered list nesting
52+ , stOptions :: WriterOptions -- writer options, so they don't have to be parameter
53+ , stVerbInNote :: Bool -- true if document has verbatim text in note
54+ , stEnumerate :: Bool -- true if document needs fancy enumerated lists
55+ , stTable :: Bool -- true if document has a table
56+ , stStrikeout :: Bool -- true if document has strikeout
57+ , stSubscript :: Bool -- true if document has subscript
58+ , stUrl :: Bool -- true if document has visible URL link
59+ , stGraphics :: Bool -- true if document contains images
60+ , stLHS :: Bool -- true if document has literate haskell code
61+ , stBook :: Bool -- true if document uses book or memoir class
62+ , stCsquotes :: Bool -- true if document uses csquotes
63+ , stHighlighting :: Bool -- true if document has highlighted code
6264 }
6365
6466-- | Convert Pandoc to LaTeX.
6567writeLaTeX :: WriterOptions -> Pandoc -> String
66−writeLaTeX options document =
67− evalState (pandocToLaTeX options document) $
68+writeLaTeX options document =
69+ evalState (pandocToLaTeX options document) $
6870 WriterState { stInNote = False, stInTable = False,
6971 stTableNotes = [], stOLLevel = 1, stOptions = options,
7072 stVerbInNote = False, stEnumerate = False,
7173 stTable = False, stStrikeout = False, stSubscript = False,
7274 stUrl = False, stGraphics = False,
7375 stLHS = False, stBook = writerChapters options,
74− stCsquotes = False }
76+ stCsquotes = False, stHighlighting = False }
7577
7678pandocToLaTeX :: WriterOptions -> Pandoc -> State WriterState String
7779pandocToLaTeX options (Pandoc (Meta title authors date) blocks) = do
@@ -129,6 +131,7 @@ pandocToLaTeX options (Pandoc (Meta title authors date) blocks) = do
129131 [ ("graphics", "yes") | stGraphics st ] ++
130132 [ ("book-class", "yes") | stBook st] ++
131133 [ ("listings", "yes") | writerListings options ] ++
134+ [ ("highlighting-macros", defaultLaTeXMacros) | stHighlighting st ] ++
132135 citecontext
133136 return $ if writerStandalone options
134137 then renderTemplate context template
@@ -180,48 +183,58 @@ blockToLaTeX (BlockQuote lst) = do
180183 contents <- blockListToLaTeX lst
181184 return $ "\\begin{quote}" $$ contents $$ "\\end{quote}"
182185blockToLaTeX (CodeBlock (_,classes,keyvalAttr) str) = do
183− st <- get
184− env <- if writerLiterateHaskell (stOptions st) && "haskell" `elem` classes &&
185− "literate" `elem` classes
186− then do
187− modify $ \s -> s{ stLHS = True }
188− return "code"
189− else if writerListings (stOptions st)
190− then return "lstlisting"
191− else if stInNote st
192− then do
193− modify $ \s -> s{ stVerbInNote = True }
194− return "Verbatim"
195− else return "verbatim"
196− let params = if writerListings (stOptions st)
197− then take 1
198− [ "language=" ++ lang | lang <- classes
199− , lang `elem` ["ABAP","IDL","Plasm","ACSL","inform"
200− ,"POV","Ada","Java","Prolog","Algol"
201− ,"JVMIS","Promela","Ant","ksh","Python"
202− ,"Assembler","Lisp","R","Awk","Logo"
203− ,"Reduce","bash","make","Rexx","Basic"
204− ,"Mathematica","RSL","C","Matlab","Ruby"
205− ,"C++","Mercury","S","Caml","MetaPost"
206− ,"SAS","Clean","Miranda","Scilab","Cobol"
207− ,"Mizar","sh","Comal","ML","SHELXL","csh"
208− ,"Modula-2","Simula","Delphi","MuPAD"
209− ,"SQL","Eiffel","NASTRAN","tcl","Elan"
210− ,"Oberon-2","TeX","erlang","OCL"
211− ,"VBScript","Euphoria","Octave","Verilog"
212− ,"Fortran","Oz","VHDL","GCL","Pascal"
213− ,"VRML","Gnuplot","Perl","XML","Haskell"
214− ,"PHP","XSLT","HTML","PL/I"]
215− ] ++
216− [ key ++ "=" ++ attr | (key,attr) <- keyvalAttr ]
217− else []
218− printParams
219− | null params = empty
220− | otherwise = "[" <> hsep (intersperse "," (map text params)) <>
221− "]"
222− return $ flush ("\\begin{" <> text env <> "}" <> printParams $$ text str $$
223− "\\end{" <> text env <> "}") $$ cr
224− -- final cr needed because of footnotes
186+ opts <- gets stOptions
187+ case () of
188+ _ | writerLiterateHaskell opts && "haskell" `elem` classes &&
189+ "literate" `elem` classes -> lhsCodeBlock
190+ | writerListings opts -> listingsCodeBlock
191+ | writerHighlight opts && not (null classes) -> highlightedCodeBlock
192+ | otherwise -> rawCodeBlock
193+ where lhsCodeBlock = do
194+ modify $ \s -> s{ stLHS = True }
195+ return $ flush ("\\begin{code}" $$ text str $$ "\\end{code}") $$ cr
196+ rawCodeBlock = do
197+ st <- get
198+ env <- if stInNote st
199+ then modify (\s -> s{ stVerbInNote = True }) >>
200+ return "Verbatim"
201+ else return "verbatim"
202+ return $ flush (text $ "\\begin{" ++ env ++ "}") $$ text str $$
203+ text ("\\end{" ++ env ++ "}") $$ cr -- final cr because of notes
204+ listingsCodeBlock = do
205+ st <- get
206+ let params = if writerListings (stOptions st)
207+ then take 1
208+ [ "language=" ++ lang | lang <- classes
209+ , lang `elem` ["ABAP","IDL","Plasm","ACSL","inform"
210+ ,"POV","Ada","Java","Prolog","Algol"
211+ ,"JVMIS","Promela","Ant","ksh","Python"
212+ ,"Assembler","Lisp","R","Awk","Logo"
213+ ,"Reduce","bash","make","Rexx","Basic"
214+ ,"Mathematica","RSL","C","Matlab","Ruby"
215+ ,"C++","Mercury","S","Caml","MetaPost"
216+ ,"SAS","Clean","Miranda","Scilab","Cobol"
217+ ,"Mizar","sh","Comal","ML","SHELXL","csh"
218+ ,"Modula-2","Simula","Delphi","MuPAD"
219+ ,"SQL","Eiffel","NASTRAN","tcl","Elan"
220+ ,"Oberon-2","TeX","erlang","OCL"
221+ ,"VBScript","Euphoria","Octave","Verilog"
222+ ,"Fortran","Oz","VHDL","GCL","Pascal"
223+ ,"VRML","Gnuplot","Perl","XML","Haskell"
224+ ,"PHP","XSLT","HTML","PL/I"]
225+ ] ++
226+ [ key ++ "=" ++ attr | (key,attr) <- keyvalAttr ]
227+ else []
228+ printParams
229+ | null params = empty
230+ | otherwise = brackets $ hsep (intersperse "," (map text params))
231+ return $ flush ("\\begin{lstlisting}" <> printParams $$ text str $$
232+ "\\end{lstlisting}") $$ cr
233+ highlightedCodeBlock =
234+ case highlightLaTeX False ("",classes,keyvalAttr) str of
235+ Nothing -> rawCodeBlock
236+ Just h -> modify (\st -> st{ stHighlighting = True }) >>
237+ return (text h)
225238blockToLaTeX (RawBlock "latex" x) = return $ text x <> blankline
226239blockToLaTeX (RawBlock _ _) = return empty
227240blockToLaTeX (BulletList lst) = do
@@ -236,15 +249,15 @@ blockToLaTeX (OrderedList (start, numstyle, numdelim) lst) = do
236249 exemplar <- if numstyle /= DefaultStyle || numdelim /= DefaultDelim
237250 then do
238251 modify $ \s -> s{ stEnumerate = True }
239− return $ char '[' <>
252+ return $ char '[' <>
240253 text (head (orderedListMarkers (1, numstyle,
241254 numdelim))) <> char ']'
242255 else return empty
243256 let resetcounter = if start /= 1 && oldlevel <= 4
244− then text $ "\\setcounter{enum" ++
257+ then text $ "\\setcounter{enum" ++
245258 map toLower (toRomanNumeral oldlevel) ++
246259 "}{" ++ show (start - 1) ++ "}"
247− else empty
260+ else empty
248261 return $ "\\begin{enumerate}" <> exemplar $$ resetcounter $$
249262 vcat items $$ "\\end{enumerate}"
250263blockToLaTeX (DefinitionList lst) = do
@@ -358,8 +371,8 @@ inlineToLaTeX :: Inline -- ^ Inline to convert
358371 -> State WriterState Doc
359372inlineToLaTeX (Emph lst) =
360373 inlineListToLaTeX lst >>= return . inCmd "emph"
361−inlineToLaTeX (Strong lst) =
362− inlineListToLaTeX lst >>= return . inCmd "textbf"
374+inlineToLaTeX (Strong lst) =
375+ inlineListToLaTeX lst >>= return . inCmd "textbf"
363376inlineToLaTeX (Strikeout lst) = do
364377 contents <- inlineListToLaTeX lst
365378 modify $ \s -> s{ stStrikeout = True }