@@ -20,10 +20,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2020{- |
2121 Module : Main
2222 Copyright : Copyright (C) 2006-8 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
2929Parses command-line options and calls the appropriate readers and
@@ -32,6 +32,7 @@ writers.
3232module Main where
3333import Text.Pandoc
3434import Text.Pandoc.ODT
35+import Text.Pandoc.PDF
3536import Text.Pandoc.Shared ( joinWithSep, HTMLMathMethod (..) )
3637import Text.Pandoc.Highlighting ( languages )
3738import System.Environment ( getArgs, getProgName, getEnvironment )
@@ -98,7 +99,7 @@ readers = [("native" , readPandoc)
9899-- | Reader for native Pandoc format.
99100readPandoc :: ParserState -> String -> Pandoc
100101readPandoc _ input = read input
101−
102+
102103-- | Association list of formats and pairs of writers and default headers.
103104writers :: [ ( String, ( WriterOptions -> Pandoc -> String, String ) ) ]
104105writers = [("native" , (writeDoc, ""))
@@ -108,6 +109,7 @@ writers = [("native" , (writeDoc, ""))
108109 ,("opendocument" , (writeOpenDocument, defaultOpenDocumentHeader))
109110 ,("odt" , (writeOpenDocument, defaultOpenDocumentHeader))
110111 ,("latex" , (writeLaTeX, defaultLaTeXHeader))
112+ ,("pdf" , (writeLaTeX, defaultLaTeXHeader))
111113 ,("context" , (writeConTeXt, defaultConTeXtHeader))
112114 ,("texinfo" , (writeTexinfo, ""))
113115 ,("man" , (writeMan, ""))
@@ -118,8 +120,7 @@ writers = [("native" , (writeDoc, ""))
118120 ]
119121
120122isNonTextOutput :: String -> Bool
121−isNonTextOutput "odt" = True
122−isNonTextOutput _ = False
123+isNonTextOutput = (`elem` ["odt", "pdf"])
123124
124125-- | Writer for Pandoc native format.
125126writeDoc :: WriterOptions -> Pandoc -> String
@@ -205,7 +206,7 @@ options =
205206 (\arg opt -> return opt { optWriter = map toLower arg })
206207 "FORMAT")
207208 "" -- ("(" ++ (joinWithSep ", " $ map fst writers) ++ ")")
208−
209+
209210 , Option "s" ["standalone"]
210211 (NoArg
211212 (\opt -> return opt { optStandalone = True }))
@@ -250,7 +251,7 @@ options =
250251
251252 , Option "m" ["asciimathml"]
252253 (OptArg
253− (\arg opt -> return opt { optHTMLMathMethod =
254+ (\arg opt -> return opt { optHTMLMathMethod =
254255 ASCIIMathML arg })
255256 "URL")
256257 "" -- "Use ASCIIMathML script in html output"
@@ -290,13 +291,13 @@ options =
290291 , Option "" ["toc", "table-of-contents"]
291292 (NoArg
292293 (\opt -> return opt { optTableOfContents = True }))
293− "" -- "Include table of contents"
294+ "" -- "Include table of contents"
294295
295296 , Option "c" ["css"]
296297 (ReqArg
297− (\arg opt -> do
298+ (\arg opt -> do
298299 let old = optCSS opt
299− return opt { optCSS = old ++ [arg],
300+ return opt { optCSS = old ++ [arg],
300301 optStandalone = True })
301302 "CSS")
302303 "" -- "Link to CSS style sheet"
@@ -340,17 +341,17 @@ options =
340341
341342 , Option "T" ["title-prefix"]
342343 (ReqArg
343− (\arg opt -> return opt { optTitlePrefix = arg,
344+ (\arg opt -> return opt { optTitlePrefix = arg,
344345 optStandalone = True })
345346 "STRING")
346347 "" -- "String to prefix to HTML window title"
347−
348+
348349 , Option "D" ["print-default-header"]
349350 (ReqArg
350351 (\arg _ -> do
351352 let header = case (lookup arg writers) of
352353 Just (_, h) -> h
353− Nothing -> error ("Unknown reader: " ++ arg)
354+ Nothing -> error ("Unknown reader: " ++ arg)
354355 hPutStr stdout header
355356 exitWith ExitSuccess)
356357 "FORMAT")
@@ -376,7 +377,7 @@ options =
376377 (NoArg
377378 (\opt -> return opt { optIgnoreArgs = True }))
378379 "" -- "Ignore command-line arguments."
379−
380+
380381 , Option "v" ["version"]
381382 (NoArg
382383 (\_ -> do
@@ -398,15 +399,15 @@ options =
398399-- Returns usage message
399400usageMessage :: String -> [OptDescr (Opt -> IO Opt)] -> String
400401usageMessage programName opts = usageInfo
401− (programName ++ " [OPTIONS] [FILES]" ++ "\nInput formats: " ++
402− (joinWithSep ", " $ map fst readers) ++ "\nOutput formats: " ++
402+ (programName ++ " [OPTIONS] [FILES]" ++ "\nInput formats: " ++
403+ (joinWithSep ", " $ map fst readers) ++ "\nOutput formats: " ++
403404 (joinWithSep ", " $ map fst writers) ++ "\nOptions:")
404405 opts
405−
406+
406407-- Determine default reader based on source file extensions
407408defaultReaderName :: [FilePath] -> String
408409defaultReaderName [] = "markdown"
409−defaultReaderName (x:xs) =
410+defaultReaderName (x:xs) =
410411 case takeExtension (map toLower x) of
411412 ".xhtml" -> "html"
412413 ".html" -> "html"
@@ -441,6 +442,7 @@ defaultWriterName x =
441442 ".texinfo" -> "texinfo"
442443 ".db" -> "docbook"
443444 ".odt" -> "odt"
445+ ".pdf" -> "pdf"
444446 ['.',y] | y `elem` ['1'..'9'] -> "man"
445447 _ -> "html"
446448
@@ -464,7 +466,7 @@ main = do
464466 else
465467 return ()
466468
467− let defaultOpts' = if compatMode
469+ let defaultOpts' = if compatMode
468470 then defaultOpts { optReader = "markdown"
469471 , optWriter = "html"
470472 , optStrict = True }
@@ -513,11 +515,11 @@ main = do
513515 let sources = if ignoreArgs then [] else args
514516
515517 -- assign reader and writer based on options and filenames
516− let readerName' = if null readerName
518+ let readerName' = if null readerName
517519 then defaultReaderName sources
518520 else readerName
519521
520− let writerName' = if null writerName
522+ let writerName' = if null writerName
521523 then defaultWriterName outputFile
522524 else writerName
523525
@@ -539,74 +541,76 @@ main = do
539541 -- remove DOS line endings
540542 tabFilter _ ('\r':'\n':xs) = '\n':(tabFilter tabStop xs)
541543 tabFilter _ ('\r':xs) = '\n':(tabFilter tabStop xs)
542− tabFilter spsToNextStop ('\t':xs) =
544+ tabFilter spsToNextStop ('\t':xs) =
543545 if preserveTabs
544− then '\t':(tabFilter tabStop xs)
545− else replicate spsToNextStop ' ' ++ tabFilter tabStop xs
546− tabFilter 1 (x:xs) =
546+ then '\t':(tabFilter tabStop xs)
547+ else replicate spsToNextStop ' ' ++ tabFilter tabStop xs
548+ tabFilter 1 (x:xs) =
547549 x:(tabFilter tabStop xs)
548− tabFilter spsToNextStop (x:xs) =
550+ tabFilter spsToNextStop (x:xs) =
549551 x:(tabFilter (spsToNextStop - 1) xs)
550552
551− let standalone' = (standalone && not strict) || writerName' == "odt"
553+ let standalone' = (standalone && not strict) || isNonTextOutput writerName'
552554
553555#ifdef _CITEPROC
554556 refs <- if null modsFile then return [] else readModsColletionFile modsFile
555557#endif
556558
557− let startParserState =
559+ let startParserState =
558560 defaultParserState { stateParseRaw = parseRaw,
559− stateTabStop = tabStop,
561+ stateTabStop = tabStop,
560562 stateSanitizeHTML = sanitize,
561563 stateStandalone = standalone',
562564#ifdef _CITEPROC
563565 stateCitations = map citeKey refs,
564566#endif
565− stateSmart = smart || writerName' `elem`
567+ stateSmart = smart || writerName' `elem`
566568 ["latex", "context"],
567569 stateColumns = columns,
568570 stateStrict = strict }
569571 let csslink = if null css
570572 then ""
571− else concatMap
573+ else concatMap
572574 (\f -> "<link rel=\"stylesheet\" href=\"" ++
573575 f ++ "\" type=\"text/css\" media=\"all\" />\n")
574576 css
575− let header = (if (customHeader == "DEFAULT")
577+ let header = (if (customHeader == "DEFAULT")
576578 then defaultHeader
577579 else customHeader) ++ csslink ++ includeHeader
578580 let writerOptions = WriterOptions { writerStandalone = standalone',
579− writerHeader = header,
581+ writerHeader = header,
580582 writerTitlePrefix = titlePrefix,
581− writerTabStop = tabStop,
583+ writerTabStop = tabStop,
582584 writerTableOfContents = toc &&
583585 (not strict) &&
584586 writerName' /= "s5",
585587 writerHTMLMathMethod = mathMethod,
586588 writerS5 = (writerName' == "s5"),
587589 writerIgnoreNotes = False,
588− writerIncremental = incremental,
590+ writerIncremental = incremental,
589591 writerNumberSections = numberSections,
590− writerIncludeBefore = includeBefore,
592+ writerIncludeBefore = includeBefore,
591593 writerIncludeAfter = includeAfter,
592594 writerStrictMarkdown = strict,
593595 writerReferenceLinks = referenceLinks,
594596 writerWrapText = wrap }
595597
596− let writeOutput = if writerName' == "odt"
597− then if outputFile == "-"
598− then \_ -> do
599− hPutStrLn stderr ("Error: Cannot write " ++ writerName ++
600− " output to stdout.\n" ++
601− "Specify an output file using the -o option.")
602− exitWith $ ExitFailure 5
603− else let sourceDirRelative = if null sources
604− then ""
605− else takeDirectory (head sources)
606− in saveOpenDocumentAsODT outputFile sourceDirRelative
607− else if outputFile == "-"
608− then putStrLn
609− else writeFile outputFile . (++ "\n")
598+ if isNonTextOutput writerName' && outputFile == "-"
599+ then do hPutStrLn stderr ("Error: Cannot write " ++ writerName ++ " output to stdout.\n" ++
600+ "Specify an output file using the -o option.")
601+ exitWith $ ExitFailure 5
602+ else return ()
603+
604+ let sourceDirRelative = if null sources
605+ then ""
606+ else takeDirectory (head sources)
607+
608+ let writeOutput = case writerName' of
609+ "odt" -> saveOpenDocumentAsODT outputFile sourceDirRelative
610+ "pdf" -> saveLaTeXAsPDF outputFile sourceDirRelative
611+ _ -> if outputFile == "-"
612+ then putStrLn
613+ else writeFile outputFile . (++ "\n")
610614
611615 fmap (reader startParserState . tabFilter tabStop . joinWithSep "\n")
612616 (readSources sources) >>=
@@ -615,7 +619,7 @@ main = do
615619#endif
616620 writeOutput . writer writerOptions
617621
618− where
622+ where
619623 readSources [] = mapM readSource ["-"]
620624 readSources sources = mapM readSource sources
621625 readSource "-" = getContents