@@ -32,7 +32,7 @@ import Text.Pandoc.Definition
3232import Text.Pandoc.Shared
3333import Text.Pandoc.Templates
3434import Text.Printf ( printf )
35−import Data.List ( (\\), isSuffixOf, isPrefixOf, intersperse )
35+import Data.List ( (\\), isSuffixOf, isPrefixOf, intersperse, intercalate )
3636import Data.Char ( toLower )
3737import Control.Monad.State
3838import Text.PrettyPrint.HughesPJ hiding ( Str )
@@ -76,7 +76,16 @@ pandocToLaTeX options (Pandoc (Meta title authors date) blocks) = do
7676 body <- blockListToLaTeX blocks
7777 let main = render body
7878 st <- get
79− let context = writerVariables options ++
79+ let biblio = takeWhile ((/=) '.') $ writerBiblioFile options
80+ citecontext = case writerCiteMethod options of
81+ Natbib -> [ ("biblio", biblio)
82+ , ("natbib", "yes")
83+ ]
84+ Biblatex -> [ ("biblio", biblio)
85+ , ("biblatex", "yes")
86+ ]
87+ _ -> []
88+ context = writerVariables options ++
8089 [ ("toc", if writerTableOfContents options then "yes" else "")
8190 , ("body", main)
8291 , ("title", titletext)
@@ -91,7 +100,8 @@ pandocToLaTeX options (Pandoc (Meta title authors date) blocks) = do
91100 [ ("url", "yes") | stUrl st ] ++
92101 [ ("numbersections", "yes") | writerNumberSections options ] ++
93102 [ ("lhs", "yes") | stLHS st ] ++
94− [ ("graphics", "yes") | stGraphics st ]
103+ [ ("graphics", "yes") | stGraphics st ] ++
104+ citecontext
95105 return $ if writerStandalone options
96106 then renderTemplate context template
97107 else main
@@ -298,8 +308,14 @@ inlineToLaTeX (Subscript lst) = do
298308 return $ inCmd "textsubscr" contents
299309inlineToLaTeX (SmallCaps lst) =
300310 inlineListToLaTeX (deVerb lst) >>= return . inCmd "textsc"
301−inlineToLaTeX (Cite _ lst) =
302− inlineListToLaTeX lst
311+inlineToLaTeX (Cite cits lst) = do
312+ st <- get
313+ let opts = stOptions st
314+ case writerCiteMethod opts of
315+ Natbib -> citationsToNatbib cits
316+ Biblatex -> citationsToBiblatex cits
317+ _ -> inlineListToLaTeX lst
318+
303319inlineToLaTeX (Code str) = do
304320 st <- get
305321 when (stInNote st) $ modify $ \s -> s{ stVerbInNote = True }
@@ -355,3 +371,95 @@ inlineToLaTeX (Note contents) = do
355371 let optNewline = "\\end{Verbatim}" `isSuffixOf` rawnote
356372 return $ text "\\footnote{" <>
357373 text rawnote <> (if optNewline then char '\n' else empty) <> char '}'
374+
375+
376+citationsToNatbib :: [Citation] -> State WriterState Doc
377+citationsToNatbib (one:[])
378+ = citeCommand c p s k
379+ where
380+ Citation { citationId = k
381+ , citationPrefix = p
382+ , citationSuffix = s
383+ , citationMode = m
384+ }
385+ = one
386+ c = case m of
387+ AuthorInText -> "citet"
388+ SuppressAuthor -> "citeyearpar"
389+ NormalCitation -> "citep"
390+
391+citationsToNatbib cits
392+ | noPrefix (tail cits) && noSuffix (init cits) && ismode NormalCitation cits
393+ = citeCommand "citep" p s ks
394+ where
395+ noPrefix = and . map (null . citationPrefix)
396+ noSuffix = and . map (null . citationSuffix)
397+ ismode m = and . map (((==) m) . citationMode)
398+ p = citationPrefix $ head $ cits
399+ s = citationSuffix $ last $ cits
400+ ks = intercalate ", " $ map citationId cits
401+
402+citationsToNatbib (c:cs) | citationMode c == AuthorInText = do
403+ author <- citeCommand "citeauthor" [] [] (citationId c)
404+ cits <- citationsToNatbib (c { citationMode = SuppressAuthor } : cs)
405+ return $ author <+> cits
406+
407+citationsToNatbib cits = do
408+ cits' <- mapM convertOne cits
409+ return $ text "\\citetext{" <> foldl combineTwo empty cits' <> text "}"
410+ where
411+ combineTwo a b | isEmpty a = b
412+ | otherwise = a <> text "; " <> b
413+ convertOne Citation { citationId = k
414+ , citationPrefix = p
415+ , citationSuffix = s
416+ , citationMode = m
417+ }
418+ = case m of
419+ AuthorInText -> citeCommand "citealt" p s k
420+ SuppressAuthor -> citeCommand "citeyear" p s k
421+ NormalCitation -> citeCommand "citealp" p s k
422+
423+citeCommand :: String -> [Inline] -> [Inline] -> String -> State WriterState Doc
424+citeCommand c p s k = do
425+ args <- citeArguments p s k
426+ return $ text ("\\" ++ c) <> args
427+
428+citeArguments :: [Inline] -> [Inline] -> String -> State WriterState Doc
429+citeArguments p s k = do
430+ pdoc <- inlineListToLaTeX p
431+ sdoc <- inlineListToLaTeX s
432+ let optargs = case (isEmpty pdoc, isEmpty sdoc) of
433+ (True, True ) -> empty
434+ (True, False) -> brackets sdoc
435+ (_ , _ ) -> brackets pdoc <> brackets sdoc
436+ return $ optargs <> braces (text k)
437+
438+citationsToBiblatex :: [Citation] -> State WriterState Doc
439+citationsToBiblatex (one:[])
440+ = citeCommand cmd p s k
441+ where
442+ Citation { citationId = k
443+ , citationPrefix = p
444+ , citationSuffix = s
445+ , citationMode = m
446+ } = one
447+ cmd = case m of
448+ SuppressAuthor -> "autocite*"
449+ AuthorInText -> "textcite"
450+ NormalCitation -> "autocite"
451+
452+citationsToBiblatex (c:cs) = do
453+ args <- mapM convertOne (c:cs)
454+ return $ text cmd <> foldl (<>) empty args
455+ where
456+ cmd = case citationMode c of
457+ AuthorInText -> "\\textcites"
458+ _ -> "\\autocites"
459+ convertOne Citation { citationId = k
460+ , citationPrefix = p
461+ , citationSuffix = s
462+ }
463+ = citeArguments p s k
464+
465+citationsToBiblatex _ = return empty