git.iko.soy/typeable/pandoc
on master help sign in
Further refactoring of App.

Moved option parsing code into App. pandoc.hs is now a 2-liner.

commit67dc15771d5ae89ff691adae0e1b1f8f7590182b authorJohn MacFarlane <jgm@berkeley.edu> dateMon 6 Feb 2017, 14:46 (10 years ago) parentfc8208e
2 files changed+726−750
pandoc.hs+2−742 src/Text/Pandoc/App.hs+724−8
pandoc.hs+2−742
@@ -30,750 +30,10 @@ Parses command-line options and calls the appropriate readers and
3030writers.
3131-}
3232module Main where
33−import Text.Pandoc.App (defaultOpts, convertWithOpts, Opt(..))
34−import Text.Pandoc
35−import Text.Pandoc.Shared
36−import Text.Pandoc.Class (PandocIO)
37−import Text.Pandoc.Highlighting (highlightingStyles)
38−import Skylighting (Syntax(..), defaultSyntaxMap)
39−import Data.List (sort, intercalate)
40−import Data.Char (toUpper)
41−import System.Console.GetOpt
42−import Control.Monad
43−import qualified Text.Pandoc.UTF8 as UTF8
44−import System.Environment
45−import System.FilePath (takeBaseName)
46−import Data.Maybe (fromMaybe)
47−import qualified Data.Text as T
48−import qualified Control.Exception as E
49−import qualified Data.ByteString as BS
50−import qualified Data.Map as M
51−import System.Exit
52−import System.IO (stdout)
53−import Control.Applicative ((<|>))
54−import System.Directory (getAppUserDataDirectory)
55−import Paths_pandoc (getDataDir)
56−import Text.Printf (printf)
33+import Text.Pandoc.App (defaultOpts, convertWithOpts, parseOptions, options)
5734
5835main :: IO ()
5936main = do
60−
61− rawArgs <- map UTF8.decodeArg <$> getArgs
62− prg <- getProgName
63−
64− let (actions, args, unrecognizedOpts, errors) =
65− getOpt' Permute options rawArgs
66−
67− let unknownOptionErrors = foldr addDeprecationNote [] unrecognizedOpts
68−
69− unless (null errors && null unknownOptionErrors) $
70− err 2 $ concat errors ++ unlines unknownOptionErrors ++
71− ("Try " ++ prg ++ " --help for more information.")
72−
73− -- thread option data structure through all supplied option actions
74− opts <- foldl (>>=) (return defaultOpts) actions
37+ (opts, args) <- parseOptions options defaultOpts
7538 convertWithOpts opts args
7639
77−-- | A list of functions, each transforming the options data structure
78−-- in response to a command-line option.
79−options :: [OptDescr (Opt -> IO Opt)]
80−options =
81− [ Option "fr" ["from","read"]
82− (ReqArg
83− (\arg opt -> return opt { optReader = Just arg })
84− "FORMAT")
85− ""
86−
87− , Option "tw" ["to","write"]
88− (ReqArg
89− (\arg opt -> return opt { optWriter = Just arg })
90− "FORMAT")
91− ""
92−
93− , Option "o" ["output"]
94− (ReqArg
95− (\arg opt -> return opt { optOutputFile = arg })
96− "FILENAME")
97− "" -- "Name of output file"
98−
99− , Option "" ["data-dir"]
100− (ReqArg
101− (\arg opt -> return opt { optDataDir = Just arg })
102− "DIRECTORY") -- "Directory containing pandoc data files."
103− ""
104−
105− , Option "R" ["parse-raw"]
106− (NoArg
107− (\opt -> return opt { optParseRaw = True }))
108− "" -- "Parse untranslatable HTML codes and LaTeX environments as raw"
109−
110− , Option "" ["base-header-level"]
111− (ReqArg
112− (\arg opt ->
113− case safeRead arg of
114− Just t | t > 0 && t < 6 -> do
115− return opt{ optBaseHeaderLevel = t }
116− _ -> err 19
117− "base-header-level must be 1-5")
118− "NUMBER")
119− "" -- "Headers base level"
120−
121− , Option "" ["indented-code-classes"]
122− (ReqArg
123− (\arg opt -> return opt { optIndentedCodeClasses = words $
124− map (\c -> if c == ',' then ' ' else c) arg })
125− "STRING")
126− "" -- "Classes (whitespace- or comma-separated) to use for indented code-blocks"
127−
128− , Option "F" ["filter"]
129− (ReqArg
130− (\arg opt -> return opt { optFilters = arg : optFilters opt })
131− "PROGRAM")
132− "" -- "External JSON filter"
133−
134− , Option "p" ["preserve-tabs"]
135− (NoArg
136− (\opt -> return opt { optPreserveTabs = True }))
137− "" -- "Preserve tabs instead of converting to spaces"
138−
139− , Option "" ["tab-stop"]
140− (ReqArg
141− (\arg opt ->
142− case safeRead arg of
143− Just t | t > 0 -> return opt { optTabStop = t }
144− _ -> err 31
145− "tab-stop must be a number greater than 0")
146− "NUMBER")
147− "" -- "Tab stop (default 4)"
148−
149− , Option "" ["track-changes"]
150− (ReqArg
151− (\arg opt -> do
152− action <- case arg of
153− "accept" -> return AcceptChanges
154− "reject" -> return RejectChanges
155− "all" -> return AllChanges
156− _ -> err 6
157− ("Unknown option for track-changes: " ++ arg)
158− return opt { optTrackChanges = action })
159− "accept|reject|all")
160− "" -- "Accepting or reject MS Word track-changes.""
161−
162− , Option "" ["file-scope"]
163− (NoArg
164− (\opt -> return opt { optFileScope = True }))
165− "" -- "Parse input files before combining"
166−
167− , Option "" ["extract-media"]
168− (ReqArg
169− (\arg opt ->
170− return opt { optExtractMedia = Just arg })
171− "PATH")
172− "" -- "Directory to which to extract embedded media"
173−
174− , Option "s" ["standalone"]
175− (NoArg
176− (\opt -> return opt { optStandalone = True }))
177− "" -- "Include needed header and footer on output"
178−
179− , Option "" ["template"]
180− (ReqArg
181− (\arg opt ->
182− return opt{ optTemplate = Just arg,
183− optStandalone = True })
184− "FILENAME")
185− "" -- "Use custom template"
186−
187− , Option "M" ["metadata"]
188− (ReqArg
189− (\arg opt -> do
190− let (key, val) = splitField arg
191− return opt{ optMetadata = (key, val) : optMetadata opt })
192− "KEY[:VALUE]")
193− ""
194−
195− , Option "V" ["variable"]
196− (ReqArg
197− (\arg opt -> do
198− let (key, val) = splitField arg
199− return opt{ optVariables = (key, val) : optVariables opt })
200− "KEY[:VALUE]")
201− ""
202−
203− , Option "D" ["print-default-template"]
204− (ReqArg
205− (\arg _ -> do
206− templ <- getDefaultTemplate Nothing arg
207− case templ of
208− Right t -> UTF8.hPutStr stdout t
209− Left e -> error $ show e
210− exitSuccess)
211− "FORMAT")
212− "" -- "Print default template for FORMAT"
213−
214− , Option "" ["print-default-data-file"]
215− (ReqArg
216− (\arg _ -> do
217− readDataFile Nothing arg >>= BS.hPutStr stdout
218− exitSuccess)
219− "FILE")
220− "" -- "Print default data file"
221−
222− , Option "" ["dpi"]
223− (ReqArg
224− (\arg opt ->
225− case safeRead arg of
226− Just t | t > 0 -> return opt { optDpi = t }
227− _ -> err 31
228− "dpi must be a number greater than 0")
229− "NUMBER")
230− "" -- "Dpi (default 96)"
231−
232− , Option "" ["wrap"]
233− (ReqArg
234− (\arg opt ->
235− case safeRead ("Wrap" ++ uppercaseFirstLetter arg) of
236− Just o -> return opt { optWrapText = o }
237− Nothing -> err 77 "--wrap must be auto, none, or preserve")
238− "auto|none|preserve")
239− "" -- "Option for wrapping text in output"
240−
241− , Option "" ["columns"]
242− (ReqArg
243− (\arg opt ->
244− case safeRead arg of
245− Just t | t > 0 -> return opt { optColumns = t }
246− _ -> err 33
247− "columns must be a number greater than 0")
248− "NUMBER")
249− "" -- "Length of line in characters"
250−
251− , Option "" ["toc", "table-of-contents"]
252− (NoArg
253− (\opt -> return opt { optTableOfContents = True }))
254− "" -- "Include table of contents"
255−
256− , Option "" ["toc-depth"]
257− (ReqArg
258− (\arg opt ->
259− case safeRead arg of
260− Just t | t >= 1 && t <= 6 ->
261− return opt { optTOCDepth = t }
262− _ -> err 57
263− "TOC level must be a number between 1 and 6")
264− "NUMBER")
265− "" -- "Number of levels to include in TOC"
266−
267− , Option "" ["no-highlight"]
268− (NoArg
269− (\opt -> return opt { optHighlightStyle = Nothing }))
270− "" -- "Don't highlight source code"
271−
272− , Option "" ["highlight-style"]
273− (ReqArg
274− (\arg opt -> return opt{ optHighlightStyle = Just arg })
275− "STYLE")
276− "" -- "Style for highlighted code"
277−
278− , Option "H" ["include-in-header"]
279− (ReqArg
280− (\arg opt -> return opt{ optIncludeInHeader =
281− arg : optIncludeInHeader opt,
282− optStandalone = True })
283− "FILENAME")
284− "" -- "File to include at end of header (implies -s)"
285−
286− , Option "B" ["include-before-body"]
287− (ReqArg
288− (\arg opt -> return opt{ optIncludeBeforeBody =
289− arg : optIncludeBeforeBody opt,
290− optStandalone = True })
291− "FILENAME")
292− "" -- "File to include before document body"
293−
294− , Option "A" ["include-after-body"]
295− (ReqArg
296− (\arg opt -> return opt{ optIncludeAfterBody =
297− arg : optIncludeAfterBody opt,
298− optStandalone = True })
299− "FILENAME")
300− "" -- "File to include after document body"
301−
302− , Option "" ["self-contained"]
303− (NoArg
304− (\opt -> return opt { optSelfContained = True,
305− optStandalone = True }))
306− "" -- "Make slide shows include all the needed js and css"
307−
308− , Option "" ["html-q-tags"]
309− (NoArg
310− (\opt ->
311− return opt { optHtmlQTags = True }))
312− "" -- "Use <q> tags for quotes in HTML"
313−
314− , Option "" ["ascii"]
315− (NoArg
316− (\opt -> return opt { optAscii = True }))
317− "" -- "Use ascii characters only in HTML output"
318−
319− , Option "" ["reference-links"]
320− (NoArg
321− (\opt -> return opt { optReferenceLinks = True } ))
322− "" -- "Use reference links in parsing HTML"
323−
324− , Option "" ["reference-location"]
325− (ReqArg
326− (\arg opt -> do
327− action <- case arg of
328− "block" -> return EndOfBlock
329− "section" -> return EndOfSection
330− "document" -> return EndOfDocument
331− _ -> err 6
332− ("Unknown option for reference-location: " ++ arg)
333− return opt { optReferenceLocation = action })
334− "block|section|document")
335− "" -- "Accepting or reject MS Word track-changes.""
336−
337− , Option "" ["atx-headers"]
338− (NoArg
339− (\opt -> return opt { optSetextHeaders = False } ))
340− "" -- "Use atx-style headers for markdown"
341−
342− , Option "" ["top-level-division"]
343− (ReqArg
344− (\arg opt -> do
345− let tldName = "TopLevel" ++ uppercaseFirstLetter arg
346− case safeRead tldName of
347− Just tlDiv -> return opt { optTopLevelDivision = tlDiv }
348− _ -> err 76 ("Top-level division must be " ++
349− "section, chapter, part, or default"))
350− "section|chapter|part")
351− "" -- "Use top-level division type in LaTeX, ConTeXt, DocBook"
352−
353− , Option "N" ["number-sections"]
354− (NoArg
355− (\opt -> return opt { optNumberSections = True }))
356− "" -- "Number sections in LaTeX"
357−
358− , Option "" ["number-offset"]
359− (ReqArg
360− (\arg opt ->
361− case safeRead ('[':arg ++ "]") of
362− Just ns -> return opt { optNumberOffset = ns,
363− optNumberSections = True }
364− _ -> err 57 "could not parse number-offset")
365− "NUMBERS")
366− "" -- "Starting number for sections, subsections, etc."
367−
368− , Option "" ["listings"]
369− (NoArg
370− (\opt -> return opt { optListings = True }))
371− "" -- "Use listings package for LaTeX code blocks"
372−
373− , Option "i" ["incremental"]
374− (NoArg
375− (\opt -> return opt { optIncremental = True }))
376− "" -- "Make list items display incrementally in Slidy/Slideous/S5"
377−
378− , Option "" ["slide-level"]
379− (ReqArg
380− (\arg opt ->
381− case safeRead arg of
382− Just t | t >= 1 && t <= 6 ->
383− return opt { optSlideLevel = Just t }
384− _ -> err 39
385− "slide level must be a number between 1 and 6")
386− "NUMBER")
387− "" -- "Force header level for slides"
388−
389− , Option "" ["section-divs"]
390− (NoArg
391− (\opt -> return opt { optSectionDivs = True }))
392− "" -- "Put sections in div tags in HTML"
393−
394− , Option "" ["default-image-extension"]
395− (ReqArg
396− (\arg opt -> return opt { optDefaultImageExtension = arg })
397− "extension")
398− "" -- "Default extension for extensionless images"
399−
400− , Option "" ["email-obfuscation"]
401− (ReqArg
402− (\arg opt -> do
403− method <- case arg of
404− "references" -> return ReferenceObfuscation
405− "javascript" -> return JavascriptObfuscation
406− "none" -> return NoObfuscation
407− _ -> err 6
408− ("Unknown obfuscation method: " ++ arg)
409− return opt { optEmailObfuscation = method })
410− "none|javascript|references")
411− "" -- "Method for obfuscating email in HTML"
412−
413− , Option "" ["id-prefix"]
414− (ReqArg
415− (\arg opt -> return opt { optIdentifierPrefix = arg })
416− "STRING")
417− "" -- "Prefix to add to automatically generated HTML identifiers"
418−
419− , Option "T" ["title-prefix"]
420− (ReqArg
421− (\arg opt -> do
422− let newvars = ("title-prefix", arg) : optVariables opt
423− return opt { optVariables = newvars,
424− optStandalone = True })
425− "STRING")
426− "" -- "String to prefix to HTML window title"
427−
428− , Option "c" ["css"]
429− (ReqArg
430− (\arg opt -> return opt{ optCss = arg : optCss opt })
431− -- add new link to end, so it is included in proper order
432− "URL")
433− "" -- "Link to CSS style sheet"
434−
435− , Option "" ["reference-doc"]
436− (ReqArg
437− (\arg opt ->
438− return opt { optReferenceDoc = Just arg })
439− "FILENAME")
440− "" -- "Path of custom reference doc"
441−
442− , Option "" ["epub-stylesheet"]
443− (ReqArg
444− (\arg opt -> return opt { optEpubStylesheet = Just arg })
445− "FILENAME")
446− "" -- "Path of epub.css"
447−
448− , Option "" ["epub-cover-image"]
449− (ReqArg
450− (\arg opt ->
451− return opt { optVariables =
452− ("epub-cover-image", arg) : optVariables opt })
453− "FILENAME")
454− "" -- "Path of epub cover image"
455−
456− , Option "" ["epub-metadata"]
457− (ReqArg
458− (\arg opt -> return opt { optEpubMetadata = Just arg })
459− "FILENAME")
460− "" -- "Path of epub metadata file"
461−
462− , Option "" ["epub-embed-font"]
463− (ReqArg
464− (\arg opt ->
465− return opt{ optEpubFonts = arg : optEpubFonts opt })
466− "FILE")
467− "" -- "Directory of fonts to embed"
468−
469− , Option "" ["epub-chapter-level"]
470− (ReqArg
471− (\arg opt ->
472− case safeRead arg of
473− Just t | t >= 1 && t <= 6 ->
474− return opt { optEpubChapterLevel = t }
475− _ -> err 59
476− "chapter level must be a number between 1 and 6")
477− "NUMBER")
478− "" -- "Header level at which to split chapters in EPUB"
479−
480− , Option "" ["latex-engine"]
481− (ReqArg
482− (\arg opt -> do
483− let b = takeBaseName arg
484− if b `elem` ["pdflatex", "lualatex", "xelatex"]
485− then return opt { optLaTeXEngine = arg }
486− else err 45 "latex-engine must be pdflatex, lualatex, or xelatex.")
487− "PROGRAM")
488− "" -- "Name of latex program to use in generating PDF"
489−
490− , Option "" ["latex-engine-opt"]
491− (ReqArg
492− (\arg opt -> do
493− let oldArgs = optLaTeXEngineArgs opt
494− return opt { optLaTeXEngineArgs = arg : oldArgs })
495− "STRING")
496− "" -- "Flags to pass to the LaTeX engine, all instances of this option are accumulated and used"
497−
498− , Option "" ["bibliography"]
499− (ReqArg
500− (\arg opt -> return opt{ optMetadata =
501− ("bibliography", arg) : optMetadata opt })
502− "FILE")
503− ""
504−
505− , Option "" ["csl"]
506− (ReqArg
507− (\arg opt ->
508− return opt{ optMetadata =
509− ("csl", arg) : optMetadata opt })
510− "FILE")
511− ""
512−
513− , Option "" ["citation-abbreviations"]
514− (ReqArg
515− (\arg opt ->
516− return opt{ optMetadata =
517− ("citation-abbreviations", arg): optMetadata opt })
518− "FILE")
519− ""
520−
521− , Option "" ["natbib"]
522− (NoArg
523− (\opt -> return opt { optCiteMethod = Natbib }))
524− "" -- "Use natbib cite commands in LaTeX output"
525−
526− , Option "" ["biblatex"]
527− (NoArg
528− (\opt -> return opt { optCiteMethod = Biblatex }))
529− "" -- "Use biblatex cite commands in LaTeX output"
530−
531− , Option "m" ["latexmathml", "asciimathml"]
532− (OptArg
533− (\arg opt ->
534− return opt { optHTMLMathMethod = LaTeXMathML arg })
535− "URL")
536− "" -- "Use LaTeXMathML script in html output"
537−
538− , Option "" ["mathml"]
539− (NoArg
540− (\opt ->
541− return opt { optHTMLMathMethod = MathML }))
542− "" -- "Use mathml for HTML math"
543−
544− , Option "" ["mimetex"]
545− (OptArg
546− (\arg opt -> do
547− let url' = case arg of
548− Just u -> u ++ "?"
549− Nothing -> "/cgi-bin/mimetex.cgi?"
550− return opt { optHTMLMathMethod = WebTeX url' })
551− "URL")
552− "" -- "Use mimetex for HTML math"
553−
554− , Option "" ["webtex"]
555− (OptArg
556− (\arg opt -> do
557− let url' = fromMaybe "https://latex.codecogs.com/png.latex?" arg
558− return opt { optHTMLMathMethod = WebTeX url' })
559− "URL")
560− "" -- "Use web service for HTML math"
561−
562− , Option "" ["jsmath"]
563− (OptArg
564− (\arg opt -> return opt { optHTMLMathMethod = JsMath arg})
565− "URL")
566− "" -- "Use jsMath for HTML math"
567−
568− , Option "" ["mathjax"]
569− (OptArg
570− (\arg opt -> do
571− let url' = fromMaybe "https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_CHTML-full" arg
572− return opt { optHTMLMathMethod = MathJax url'})
573− "URL")
574− "" -- "Use MathJax for HTML math"
575− , Option "" ["katex"]
576− (OptArg
577− (\arg opt ->
578− return opt
579− { optKaTeXJS =
580− arg <|> Just "https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.6.0/katex.min.js"})
581− "URL")
582− "" -- Use KaTeX for HTML Math
583−
584− , Option "" ["katex-stylesheet"]
585− (ReqArg
586− (\arg opt ->
587− return opt { optKaTeXStylesheet = Just arg })
588− "URL")
589− "" -- Set the KaTeX Stylesheet location
590−
591− , Option "" ["gladtex"]
592− (NoArg
593− (\opt -> return opt { optHTMLMathMethod = GladTeX }))
594− "" -- "Use gladtex for HTML math"
595−
596− , Option "" ["trace"]
597− (NoArg
598− (\opt -> return opt { optVerbosity = DEBUG }))
599− "" -- "Turn on diagnostic tracing in readers."
600−
601− , Option "" ["dump-args"]
602− (NoArg
603− (\opt -> return opt { optDumpArgs = True }))
604− "" -- "Print output filename and arguments to stdout."
605−
606− , Option "" ["ignore-args"]
607− (NoArg
608− (\opt -> return opt { optIgnoreArgs = True }))
609− "" -- "Ignore command-line arguments."
610−
611− , Option "" ["verbose"]
612− (NoArg
613− (\opt -> return opt { optVerbosity = INFO }))
614− "" -- "Verbose diagnostic output."
615−
616− , Option "" ["quiet"]
617− (NoArg
618− (\opt -> return opt { optVerbosity = ERROR }))
619− "" -- "Suppress warnings."
620−
621− , Option "" ["fail-if-warnings"]
622− (NoArg
623− (\opt -> return opt { optFailIfWarnings = True }))
624− "" -- "Exit with error status if there were warnings."
625−
626− , Option "" ["bash-completion"]
627− (NoArg
628− (\_ -> do
629− ddir <- getDataDir
630− tpl <- readDataFileUTF8 Nothing "bash_completion.tpl"
631− let optnames (Option shorts longs _ _) =
632− map (\c -> ['-',c]) shorts ++
633− map ("--" ++) longs
634− let allopts = unwords (concatMap optnames options)
635− UTF8.hPutStrLn stdout $ printf tpl allopts
636− (unwords readers'names)
637− (unwords writers'names)
638− (unwords $ map fst highlightingStyles)
639− ddir
640− exitSuccess ))
641− "" -- "Print bash completion script"
642−
643− , Option "" ["list-input-formats"]
644− (NoArg
645− (\_ -> do
646− mapM_ (UTF8.hPutStrLn stdout) readers'names
647− exitSuccess ))
648− ""
649−
650− , Option "" ["list-output-formats"]
651− (NoArg
652− (\_ -> do
653− mapM_ (UTF8.hPutStrLn stdout) writers'names
654− exitSuccess ))
655− ""
656−
657− , Option "" ["list-extensions"]
658− (NoArg
659− (\_ -> do
660− let showExt x = drop 4 (show x) ++
661− if extensionEnabled x pandocExtensions
662− then " +"
663− else " -"
664− mapM_ (UTF8.hPutStrLn stdout . showExt)
665− ([minBound..maxBound] :: [Extension])
666− exitSuccess ))
667− ""
668−
669− , Option "" ["list-highlight-languages"]
670− (NoArg
671− (\_ -> do
672− let langs = [ T.unpack (T.toLower (sShortname s))
673− | s <- M.elems defaultSyntaxMap
674− , sShortname s `notElem`
675− [T.pack "Alert", T.pack "Alert_indent"]
676− ]
677− mapM_ (UTF8.hPutStrLn stdout) langs
678− exitSuccess ))
679− ""
680−
681− , Option "" ["list-highlight-styles"]
682− (NoArg
683− (\_ -> do
684− mapM_ (UTF8.hPutStrLn stdout) $
685− map fst highlightingStyles
686− exitSuccess ))
687− ""
688−
689− , Option "v" ["version"]
690− (NoArg
691− (\_ -> do
692− prg <- getProgName
693− defaultDatadir <- E.catch
694− (getAppUserDataDirectory "pandoc")
695− (\e -> let _ = (e :: E.SomeException)
696− in return "")
697− UTF8.hPutStrLn stdout (prg ++ " " ++ pandocVersion ++
698− compileInfo ++ "\nDefault user data directory: " ++
699− defaultDatadir ++ copyrightMessage)
700− exitSuccess ))
701− "" -- "Print version"
702−
703− , Option "h" ["help"]
704− (NoArg
705− (\_ -> do
706− prg <- getProgName
707− UTF8.hPutStr stdout (usageMessage prg options)
708− exitSuccess ))
709− "" -- "Show help"
710−
711− ]
712−
713−-- Returns usage message
714−usageMessage :: String -> [OptDescr (Opt -> IO Opt)] -> String
715−usageMessage programName = usageInfo (programName ++ " [OPTIONS] [FILES]")
716−
717−copyrightMessage :: String
718−copyrightMessage = intercalate "\n" [
719− "",
720− "Copyright (C) 2006-2016 John MacFarlane",
721− "Web: http://pandoc.org",
722− "This is free software; see the source for copying conditions.",
723− "There is no warranty, not even for merchantability or fitness",
724− "for a particular purpose." ]
725−
726−compileInfo :: String
727−compileInfo =
728− "\nCompiled with pandoc-types " ++ VERSION_pandoc_types ++ ", texmath " ++
729− VERSION_texmath ++ ", skylighting " ++ VERSION_skylighting
730−
731−-- | Converts a list of strings into a single string with the items printed as
732−-- comma separated words in lines with a maximum line length.
733−wrapWords :: Int -> Int -> [String] -> String
734−wrapWords indent c = wrap' (c - indent) (c - indent)
735− where
736− wrap' _ _ [] = ""
737− wrap' cols remaining (x:xs)
738− | remaining == cols =
739− x ++ wrap' cols (remaining - length x) xs
740− | (length x + 1) > remaining =
741− ",\n" ++ replicate indent ' ' ++ x ++
742− wrap' cols (cols - length x) xs
743− | otherwise =
744− ", " ++ x ++
745− wrap' cols (remaining - length x - 2) xs
746−
747−addDeprecationNote :: String -> [String] -> [String]
748−addDeprecationNote "--smart" =
749− (("--smart has been removed. Use +smart or -smart extension instead.\n" ++
750− "For example: pandoc -f markdown+smart -t markdown-smart.") :)
751−addDeprecationNote "-S" = addDeprecationNote "--smart"
752−addDeprecationNote "--old-dashes" =
753− ("--old-dashes has been removed. Use +old_dashes extension instead." :)
754−addDeprecationNote "--no-wrap" =
755− ("--no-wrap has been removed. Use --wrap=none instead." :)
756−addDeprecationNote "--chapters" =
757− ("--chapters has been removed. Use --top-level-division=chapter instead." :)
758−addDeprecationNote "--reference-docx" =
759− ("--reference-docx has been removed. Use --reference-doc instead." :)
760−addDeprecationNote "--reference-odt" =
761− ("--reference-odt has been removed. Use --reference-doc instead." :)
762−addDeprecationNote x =
763− (("Unknown option " ++ x ++ ".") :)
764−
765−uppercaseFirstLetter :: String -> String
766−uppercaseFirstLetter (c:cs) = toUpper c : cs
767−uppercaseFirstLetter [] = []
768−
769−readers'names :: [String]
770−readers'names = sort (map fst (readers :: [(String, Reader PandocIO)]))
771−
772−writers'names :: [String]
773−writers'names = sort (map fst (writers :: [(String, Writer PandocIO)]))
774−
775−splitField :: String -> (String, String)
776−splitField s =
777− case break (`elem` ":=") s of
778− (k,_:v) -> (k,v)
779− (k,[]) -> (k,"true")
src/Text/Pandoc/App.hs+724−8
@@ -32,24 +32,29 @@ module Text.Pandoc.App (
3232 convertWithOpts
3333 , Opt(..)
3434 , defaultOpts
35+ , parseOptions
36+ , options
3537 ) where
3638import Text.Pandoc
3739import Text.Pandoc.Builder (setMeta)
3840import Text.Pandoc.PDF (makePDF)
3941import Text.Pandoc.Walk (walk)
4042import Text.Pandoc.Shared ( tabFilter, readDataFileUTF8,
41− headerShift, err, openURL )
43+ headerShift, err, openURL, safeRead,
44+ readDataFile )
4245import Text.Pandoc.MediaBag ( mediaDirectory, extractMediaBag, MediaBag )
4346import Text.Pandoc.XML ( toEntities )
4447import Text.Pandoc.Highlighting (highlightingStyles)
4548import Text.Pandoc.SelfContained ( makeSelfContained )
4649import Text.Pandoc.Process (pipeProcess)
47−import Skylighting ( Style )
48−import System.Environment ( getEnvironment )
50+import Skylighting ( Style, defaultSyntaxMap, Syntax(..) )
51+import Text.Printf
52+import System.Environment ( getEnvironment, getProgName, getArgs )
53+import Control.Applicative ((<|>))
4954import System.Exit ( ExitCode (..), exitSuccess )
5055import System.FilePath
51−import Data.Char ( toLower )
52−import Data.List ( intercalate, isPrefixOf, isSuffixOf )
56+import Data.Char ( toLower, toUpper )
57+import Data.List ( intercalate, isPrefixOf, isSuffixOf, sort )
5358import System.Directory ( getAppUserDataDirectory, findExecutable,
5459 doesFileExist, Permissions(..), getPermissions )
5560import System.IO ( stdout, stderr )
@@ -57,21 +62,43 @@ import System.IO.Error ( isDoesNotExistError )
5762import qualified Control.Exception as E
5863import Control.Exception.Extensible ( throwIO )
5964import qualified Text.Pandoc.UTF8 as UTF8
60−import Control.Monad (when, unless, (>=>))
65+import Control.Monad
66+import Control.Monad.IO.Class
6167import Data.Maybe (fromMaybe, isNothing, isJust)
6268import Data.Foldable (foldrM)
6369import Network.URI (parseURI, isURI, URI(..))
6470import qualified Data.ByteString.Lazy as B
71+import qualified Data.ByteString as BS
72+import qualified Data.Map as M
6573import Data.Aeson (eitherDecode', encode)
6674import Data.Yaml (decode)
6775import qualified Data.Yaml as Yaml
6876import qualified Data.Text as T
77+import System.Console.GetOpt
78+import Text.Pandoc.Class (withMediaBag, PandocIO, getLog)
79+import Paths_pandoc (getDataDir)
6980#ifndef _WINDOWS
7081import System.Posix.Terminal (queryTerminal)
7182import System.Posix.IO (stdOutput)
7283#endif
73−import Control.Monad.Trans
74−import Text.Pandoc.Class (withMediaBag, PandocIO, getLog)
84+
85+parseOptions :: [OptDescr (Opt -> IO Opt)] -> Opt -> IO (Opt, [FilePath])
86+parseOptions options' defaults = do
87+ rawArgs <- map UTF8.decodeArg <$> getArgs
88+ prg <- getProgName
89+
90+ let (actions, args, unrecognizedOpts, errors) =
91+ getOpt' Permute options' rawArgs
92+
93+ let unknownOptionErrors = foldr handelUnrecognizedOption [] unrecognizedOpts
94+
95+ unless (null errors && null unknownOptionErrors) $
96+ err 2 $ concat errors ++ unlines unknownOptionErrors ++
97+ ("Try " ++ prg ++ " --help for more information.")
98+
99+ -- thread option data structure through all supplied option actions
100+ opts <- foldl (>>=) (return defaults) actions
101+ return (opts, args)
75102
76103convertWithOpts :: Opt -> [FilePath] -> IO ()
77104convertWithOpts opts args = do
@@ -718,3 +745,692 @@ lookupHighlightStyle (Just s) =
718745 case lookup (map toLower s) highlightingStyles of
719746 Just sty -> return (Just sty)
720747 Nothing -> err 68 $ "Unknown highlight-style " ++ s
748+
749+-- | A list of functions, each transforming the options data structure
750+-- in response to a command-line option.
751+options :: [OptDescr (Opt -> IO Opt)]
752+options =
753+ [ Option "fr" ["from","read"]
754+ (ReqArg
755+ (\arg opt -> return opt { optReader = Just arg })
756+ "FORMAT")
757+ ""
758+
759+ , Option "tw" ["to","write"]
760+ (ReqArg
761+ (\arg opt -> return opt { optWriter = Just arg })
762+ "FORMAT")
763+ ""
764+
765+ , Option "o" ["output"]
766+ (ReqArg
767+ (\arg opt -> return opt { optOutputFile = arg })
768+ "FILENAME")
769+ "" -- "Name of output file"
770+
771+ , Option "" ["data-dir"]
772+ (ReqArg
773+ (\arg opt -> return opt { optDataDir = Just arg })
774+ "DIRECTORY") -- "Directory containing pandoc data files."
775+ ""
776+
777+ , Option "R" ["parse-raw"]
778+ (NoArg
779+ (\opt -> return opt { optParseRaw = True }))
780+ "" -- "Parse untranslatable HTML codes and LaTeX environments as raw"
781+
782+ , Option "" ["base-header-level"]
783+ (ReqArg
784+ (\arg opt ->
785+ case safeRead arg of
786+ Just t | t > 0 && t < 6 -> do
787+ return opt{ optBaseHeaderLevel = t }
788+ _ -> err 19
789+ "base-header-level must be 1-5")
790+ "NUMBER")
791+ "" -- "Headers base level"
792+
793+ , Option "" ["indented-code-classes"]
794+ (ReqArg
795+ (\arg opt -> return opt { optIndentedCodeClasses = words $
796+ map (\c -> if c == ',' then ' ' else c) arg })
797+ "STRING")
798+ "" -- "Classes (whitespace- or comma-separated) to use for indented code-blocks"
799+
800+ , Option "F" ["filter"]
801+ (ReqArg
802+ (\arg opt -> return opt { optFilters = arg : optFilters opt })
803+ "PROGRAM")
804+ "" -- "External JSON filter"
805+
806+ , Option "p" ["preserve-tabs"]
807+ (NoArg
808+ (\opt -> return opt { optPreserveTabs = True }))
809+ "" -- "Preserve tabs instead of converting to spaces"
810+
811+ , Option "" ["tab-stop"]
812+ (ReqArg
813+ (\arg opt ->
814+ case safeRead arg of
815+ Just t | t > 0 -> return opt { optTabStop = t }
816+ _ -> err 31
817+ "tab-stop must be a number greater than 0")
818+ "NUMBER")
819+ "" -- "Tab stop (default 4)"
820+
821+ , Option "" ["track-changes"]
822+ (ReqArg
823+ (\arg opt -> do
824+ action <- case arg of
825+ "accept" -> return AcceptChanges
826+ "reject" -> return RejectChanges
827+ "all" -> return AllChanges
828+ _ -> err 6
829+ ("Unknown option for track-changes: " ++ arg)
830+ return opt { optTrackChanges = action })
831+ "accept|reject|all")
832+ "" -- "Accepting or reject MS Word track-changes.""
833+
834+ , Option "" ["file-scope"]
835+ (NoArg
836+ (\opt -> return opt { optFileScope = True }))
837+ "" -- "Parse input files before combining"
838+
839+ , Option "" ["extract-media"]
840+ (ReqArg
841+ (\arg opt ->
842+ return opt { optExtractMedia = Just arg })
843+ "PATH")
844+ "" -- "Directory to which to extract embedded media"
845+
846+ , Option "s" ["standalone"]
847+ (NoArg
848+ (\opt -> return opt { optStandalone = True }))
849+ "" -- "Include needed header and footer on output"
850+
851+ , Option "" ["template"]
852+ (ReqArg
853+ (\arg opt ->
854+ return opt{ optTemplate = Just arg,
855+ optStandalone = True })
856+ "FILENAME")
857+ "" -- "Use custom template"
858+
859+ , Option "M" ["metadata"]
860+ (ReqArg
861+ (\arg opt -> do
862+ let (key, val) = splitField arg
863+ return opt{ optMetadata = (key, val) : optMetadata opt })
864+ "KEY[:VALUE]")
865+ ""
866+
867+ , Option "V" ["variable"]
868+ (ReqArg
869+ (\arg opt -> do
870+ let (key, val) = splitField arg
871+ return opt{ optVariables = (key, val) : optVariables opt })
872+ "KEY[:VALUE]")
873+ ""
874+
875+ , Option "D" ["print-default-template"]
876+ (ReqArg
877+ (\arg _ -> do
878+ templ <- getDefaultTemplate Nothing arg
879+ case templ of
880+ Right t -> UTF8.hPutStr stdout t
881+ Left e -> error $ show e
882+ exitSuccess)
883+ "FORMAT")
884+ "" -- "Print default template for FORMAT"
885+
886+ , Option "" ["print-default-data-file"]
887+ (ReqArg
888+ (\arg _ -> do
889+ readDataFile Nothing arg >>= BS.hPutStr stdout
890+ exitSuccess)
891+ "FILE")
892+ "" -- "Print default data file"
893+
894+ , Option "" ["dpi"]
895+ (ReqArg
896+ (\arg opt ->
897+ case safeRead arg of
898+ Just t | t > 0 -> return opt { optDpi = t }
899+ _ -> err 31
900+ "dpi must be a number greater than 0")
901+ "NUMBER")
902+ "" -- "Dpi (default 96)"
903+
904+ , Option "" ["wrap"]
905+ (ReqArg
906+ (\arg opt ->
907+ case safeRead ("Wrap" ++ uppercaseFirstLetter arg) of
908+ Just o -> return opt { optWrapText = o }
909+ Nothing -> err 77 "--wrap must be auto, none, or preserve")
910+ "auto|none|preserve")
911+ "" -- "Option for wrapping text in output"
912+
913+ , Option "" ["columns"]
914+ (ReqArg
915+ (\arg opt ->
916+ case safeRead arg of
917+ Just t | t > 0 -> return opt { optColumns = t }
918+ _ -> err 33
919+ "columns must be a number greater than 0")
920+ "NUMBER")
921+ "" -- "Length of line in characters"
922+
923+ , Option "" ["toc", "table-of-contents"]
924+ (NoArg
925+ (\opt -> return opt { optTableOfContents = True }))
926+ "" -- "Include table of contents"
927+
928+ , Option "" ["toc-depth"]
929+ (ReqArg
930+ (\arg opt ->
931+ case safeRead arg of
932+ Just t | t >= 1 && t <= 6 ->
933+ return opt { optTOCDepth = t }
934+ _ -> err 57
935+ "TOC level must be a number between 1 and 6")
936+ "NUMBER")
937+ "" -- "Number of levels to include in TOC"
938+
939+ , Option "" ["no-highlight"]
940+ (NoArg
941+ (\opt -> return opt { optHighlightStyle = Nothing }))
942+ "" -- "Don't highlight source code"
943+
944+ , Option "" ["highlight-style"]
945+ (ReqArg
946+ (\arg opt -> return opt{ optHighlightStyle = Just arg })
947+ "STYLE")
948+ "" -- "Style for highlighted code"
949+
950+ , Option "H" ["include-in-header"]
951+ (ReqArg
952+ (\arg opt -> return opt{ optIncludeInHeader =
953+ arg : optIncludeInHeader opt,
954+ optStandalone = True })
955+ "FILENAME")
956+ "" -- "File to include at end of header (implies -s)"
957+
958+ , Option "B" ["include-before-body"]
959+ (ReqArg
960+ (\arg opt -> return opt{ optIncludeBeforeBody =
961+ arg : optIncludeBeforeBody opt,
962+ optStandalone = True })
963+ "FILENAME")
964+ "" -- "File to include before document body"
965+
966+ , Option "A" ["include-after-body"]
967+ (ReqArg
968+ (\arg opt -> return opt{ optIncludeAfterBody =
969+ arg : optIncludeAfterBody opt,
970+ optStandalone = True })
971+ "FILENAME")
972+ "" -- "File to include after document body"
973+
974+ , Option "" ["self-contained"]
975+ (NoArg
976+ (\opt -> return opt { optSelfContained = True,
977+ optStandalone = True }))
978+ "" -- "Make slide shows include all the needed js and css"
979+
980+ , Option "" ["html-q-tags"]
981+ (NoArg
982+ (\opt ->
983+ return opt { optHtmlQTags = True }))
984+ "" -- "Use <q> tags for quotes in HTML"
985+
986+ , Option "" ["ascii"]
987+ (NoArg
988+ (\opt -> return opt { optAscii = True }))
989+ "" -- "Use ascii characters only in HTML output"
990+
991+ , Option "" ["reference-links"]
992+ (NoArg
993+ (\opt -> return opt { optReferenceLinks = True } ))
994+ "" -- "Use reference links in parsing HTML"
995+
996+ , Option "" ["reference-location"]
997+ (ReqArg
998+ (\arg opt -> do
999+ action <- case arg of
1000+ "block" -> return EndOfBlock
1001+ "section" -> return EndOfSection
1002+ "document" -> return EndOfDocument
1003+ _ -> err 6
1004+ ("Unknown option for reference-location: " ++ arg)
1005+ return opt { optReferenceLocation = action })
1006+ "block|section|document")
1007+ "" -- "Accepting or reject MS Word track-changes.""
1008+
1009+ , Option "" ["atx-headers"]
1010+ (NoArg
1011+ (\opt -> return opt { optSetextHeaders = False } ))
1012+ "" -- "Use atx-style headers for markdown"
1013+
1014+ , Option "" ["top-level-division"]
1015+ (ReqArg
1016+ (\arg opt -> do
1017+ let tldName = "TopLevel" ++ uppercaseFirstLetter arg
1018+ case safeRead tldName of
1019+ Just tlDiv -> return opt { optTopLevelDivision = tlDiv }
1020+ _ -> err 76 ("Top-level division must be " ++
1021+ "section, chapter, part, or default"))
1022+ "section|chapter|part")
1023+ "" -- "Use top-level division type in LaTeX, ConTeXt, DocBook"
1024+
1025+ , Option "N" ["number-sections"]
1026+ (NoArg
1027+ (\opt -> return opt { optNumberSections = True }))
1028+ "" -- "Number sections in LaTeX"
1029+
1030+ , Option "" ["number-offset"]
1031+ (ReqArg
1032+ (\arg opt ->
1033+ case safeRead ('[':arg ++ "]") of
1034+ Just ns -> return opt { optNumberOffset = ns,
1035+ optNumberSections = True }
1036+ _ -> err 57 "could not parse number-offset")
1037+ "NUMBERS")
1038+ "" -- "Starting number for sections, subsections, etc."
1039+
1040+ , Option "" ["listings"]
1041+ (NoArg
1042+ (\opt -> return opt { optListings = True }))
1043+ "" -- "Use listings package for LaTeX code blocks"
1044+
1045+ , Option "i" ["incremental"]
1046+ (NoArg
1047+ (\opt -> return opt { optIncremental = True }))
1048+ "" -- "Make list items display incrementally in Slidy/Slideous/S5"
1049+
1050+ , Option "" ["slide-level"]
1051+ (ReqArg
1052+ (\arg opt ->
1053+ case safeRead arg of
1054+ Just t | t >= 1 && t <= 6 ->
1055+ return opt { optSlideLevel = Just t }
1056+ _ -> err 39
1057+ "slide level must be a number between 1 and 6")
1058+ "NUMBER")
1059+ "" -- "Force header level for slides"
1060+
1061+ , Option "" ["section-divs"]
1062+ (NoArg
1063+ (\opt -> return opt { optSectionDivs = True }))
1064+ "" -- "Put sections in div tags in HTML"
1065+
1066+ , Option "" ["default-image-extension"]
1067+ (ReqArg
1068+ (\arg opt -> return opt { optDefaultImageExtension = arg })
1069+ "extension")
1070+ "" -- "Default extension for extensionless images"
1071+
1072+ , Option "" ["email-obfuscation"]
1073+ (ReqArg
1074+ (\arg opt -> do
1075+ method <- case arg of
1076+ "references" -> return ReferenceObfuscation
1077+ "javascript" -> return JavascriptObfuscation
1078+ "none" -> return NoObfuscation
1079+ _ -> err 6
1080+ ("Unknown obfuscation method: " ++ arg)
1081+ return opt { optEmailObfuscation = method })
1082+ "none|javascript|references")
1083+ "" -- "Method for obfuscating email in HTML"
1084+
1085+ , Option "" ["id-prefix"]
1086+ (ReqArg
1087+ (\arg opt -> return opt { optIdentifierPrefix = arg })
1088+ "STRING")
1089+ "" -- "Prefix to add to automatically generated HTML identifiers"
1090+
1091+ , Option "T" ["title-prefix"]
1092+ (ReqArg
1093+ (\arg opt -> do
1094+ let newvars = ("title-prefix", arg) : optVariables opt
1095+ return opt { optVariables = newvars,
1096+ optStandalone = True })
1097+ "STRING")
1098+ "" -- "String to prefix to HTML window title"
1099+
1100+ , Option "c" ["css"]
1101+ (ReqArg
1102+ (\arg opt -> return opt{ optCss = arg : optCss opt })
1103+ -- add new link to end, so it is included in proper order
1104+ "URL")
1105+ "" -- "Link to CSS style sheet"
1106+
1107+ , Option "" ["reference-doc"]
1108+ (ReqArg
1109+ (\arg opt ->
1110+ return opt { optReferenceDoc = Just arg })
1111+ "FILENAME")
1112+ "" -- "Path of custom reference doc"
1113+
1114+ , Option "" ["epub-stylesheet"]
1115+ (ReqArg
1116+ (\arg opt -> return opt { optEpubStylesheet = Just arg })
1117+ "FILENAME")
1118+ "" -- "Path of epub.css"
1119+
1120+ , Option "" ["epub-cover-image"]
1121+ (ReqArg
1122+ (\arg opt ->
1123+ return opt { optVariables =
1124+ ("epub-cover-image", arg) : optVariables opt })
1125+ "FILENAME")
1126+ "" -- "Path of epub cover image"
1127+
1128+ , Option "" ["epub-metadata"]
1129+ (ReqArg
1130+ (\arg opt -> return opt { optEpubMetadata = Just arg })
1131+ "FILENAME")
1132+ "" -- "Path of epub metadata file"
1133+
1134+ , Option "" ["epub-embed-font"]
1135+ (ReqArg
1136+ (\arg opt ->
1137+ return opt{ optEpubFonts = arg : optEpubFonts opt })
1138+ "FILE")
1139+ "" -- "Directory of fonts to embed"
1140+
1141+ , Option "" ["epub-chapter-level"]
1142+ (ReqArg
1143+ (\arg opt ->
1144+ case safeRead arg of
1145+ Just t | t >= 1 && t <= 6 ->
1146+ return opt { optEpubChapterLevel = t }
1147+ _ -> err 59
1148+ "chapter level must be a number between 1 and 6")
1149+ "NUMBER")
1150+ "" -- "Header level at which to split chapters in EPUB"
1151+
1152+ , Option "" ["latex-engine"]
1153+ (ReqArg
1154+ (\arg opt -> do
1155+ let b = takeBaseName arg
1156+ if b `elem` ["pdflatex", "lualatex", "xelatex"]
1157+ then return opt { optLaTeXEngine = arg }
1158+ else err 45 "latex-engine must be pdflatex, lualatex, or xelatex.")
1159+ "PROGRAM")
1160+ "" -- "Name of latex program to use in generating PDF"
1161+
1162+ , Option "" ["latex-engine-opt"]
1163+ (ReqArg
1164+ (\arg opt -> do
1165+ let oldArgs = optLaTeXEngineArgs opt
1166+ return opt { optLaTeXEngineArgs = arg : oldArgs })
1167+ "STRING")
1168+ "" -- "Flags to pass to the LaTeX engine, all instances of this option are accumulated and used"
1169+
1170+ , Option "" ["bibliography"]
1171+ (ReqArg
1172+ (\arg opt -> return opt{ optMetadata =
1173+ ("bibliography", arg) : optMetadata opt })
1174+ "FILE")
1175+ ""
1176+
1177+ , Option "" ["csl"]
1178+ (ReqArg
1179+ (\arg opt ->
1180+ return opt{ optMetadata =
1181+ ("csl", arg) : optMetadata opt })
1182+ "FILE")
1183+ ""
1184+
1185+ , Option "" ["citation-abbreviations"]
1186+ (ReqArg
1187+ (\arg opt ->
1188+ return opt{ optMetadata =
1189+ ("citation-abbreviations", arg): optMetadata opt })
1190+ "FILE")
1191+ ""
1192+
1193+ , Option "" ["natbib"]
1194+ (NoArg
1195+ (\opt -> return opt { optCiteMethod = Natbib }))
1196+ "" -- "Use natbib cite commands in LaTeX output"
1197+
1198+ , Option "" ["biblatex"]
1199+ (NoArg
1200+ (\opt -> return opt { optCiteMethod = Biblatex }))
1201+ "" -- "Use biblatex cite commands in LaTeX output"
1202+
1203+ , Option "m" ["latexmathml", "asciimathml"]
1204+ (OptArg
1205+ (\arg opt ->
1206+ return opt { optHTMLMathMethod = LaTeXMathML arg })
1207+ "URL")
1208+ "" -- "Use LaTeXMathML script in html output"
1209+
1210+ , Option "" ["mathml"]
1211+ (NoArg
1212+ (\opt ->
1213+ return opt { optHTMLMathMethod = MathML }))
1214+ "" -- "Use mathml for HTML math"
1215+
1216+ , Option "" ["mimetex"]
1217+ (OptArg
1218+ (\arg opt -> do
1219+ let url' = case arg of
1220+ Just u -> u ++ "?"
1221+ Nothing -> "/cgi-bin/mimetex.cgi?"
1222+ return opt { optHTMLMathMethod = WebTeX url' })
1223+ "URL")
1224+ "" -- "Use mimetex for HTML math"
1225+
1226+ , Option "" ["webtex"]
1227+ (OptArg
1228+ (\arg opt -> do
1229+ let url' = fromMaybe "https://latex.codecogs.com/png.latex?" arg
1230+ return opt { optHTMLMathMethod = WebTeX url' })
1231+ "URL")
1232+ "" -- "Use web service for HTML math"
1233+
1234+ , Option "" ["jsmath"]
1235+ (OptArg
1236+ (\arg opt -> return opt { optHTMLMathMethod = JsMath arg})
1237+ "URL")
1238+ "" -- "Use jsMath for HTML math"
1239+
1240+ , Option "" ["mathjax"]
1241+ (OptArg
1242+ (\arg opt -> do
1243+ let url' = fromMaybe "https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_CHTML-full" arg
1244+ return opt { optHTMLMathMethod = MathJax url'})
1245+ "URL")
1246+ "" -- "Use MathJax for HTML math"
1247+ , Option "" ["katex"]
1248+ (OptArg
1249+ (\arg opt ->
1250+ return opt
1251+ { optKaTeXJS =
1252+ arg <|> Just "https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.6.0/katex.min.js"})
1253+ "URL")
1254+ "" -- Use KaTeX for HTML Math
1255+
1256+ , Option "" ["katex-stylesheet"]
1257+ (ReqArg
1258+ (\arg opt ->
1259+ return opt { optKaTeXStylesheet = Just arg })
1260+ "URL")
1261+ "" -- Set the KaTeX Stylesheet location
1262+
1263+ , Option "" ["gladtex"]
1264+ (NoArg
1265+ (\opt -> return opt { optHTMLMathMethod = GladTeX }))
1266+ "" -- "Use gladtex for HTML math"
1267+
1268+ , Option "" ["trace"]
1269+ (NoArg
1270+ (\opt -> return opt { optVerbosity = DEBUG }))
1271+ "" -- "Turn on diagnostic tracing in readers."
1272+
1273+ , Option "" ["dump-args"]
1274+ (NoArg
1275+ (\opt -> return opt { optDumpArgs = True }))
1276+ "" -- "Print output filename and arguments to stdout."
1277+
1278+ , Option "" ["ignore-args"]
1279+ (NoArg
1280+ (\opt -> return opt { optIgnoreArgs = True }))
1281+ "" -- "Ignore command-line arguments."
1282+
1283+ , Option "" ["verbose"]
1284+ (NoArg
1285+ (\opt -> return opt { optVerbosity = INFO }))
1286+ "" -- "Verbose diagnostic output."
1287+
1288+ , Option "" ["quiet"]
1289+ (NoArg
1290+ (\opt -> return opt { optVerbosity = ERROR }))
1291+ "" -- "Suppress warnings."
1292+
1293+ , Option "" ["fail-if-warnings"]
1294+ (NoArg
1295+ (\opt -> return opt { optFailIfWarnings = True }))
1296+ "" -- "Exit with error status if there were warnings."
1297+
1298+ , Option "" ["bash-completion"]
1299+ (NoArg
1300+ (\_ -> do
1301+ ddir <- getDataDir
1302+ tpl <- readDataFileUTF8 Nothing "bash_completion.tpl"
1303+ let optnames (Option shorts longs _ _) =
1304+ map (\c -> ['-',c]) shorts ++
1305+ map ("--" ++) longs
1306+ let allopts = unwords (concatMap optnames options)
1307+ UTF8.hPutStrLn stdout $ printf tpl allopts
1308+ (unwords readers'names)
1309+ (unwords writers'names)
1310+ (unwords $ map fst highlightingStyles)
1311+ ddir
1312+ exitSuccess ))
1313+ "" -- "Print bash completion script"
1314+
1315+ , Option "" ["list-input-formats"]
1316+ (NoArg
1317+ (\_ -> do
1318+ mapM_ (UTF8.hPutStrLn stdout) readers'names
1319+ exitSuccess ))
1320+ ""
1321+
1322+ , Option "" ["list-output-formats"]
1323+ (NoArg
1324+ (\_ -> do
1325+ mapM_ (UTF8.hPutStrLn stdout) writers'names
1326+ exitSuccess ))
1327+ ""
1328+
1329+ , Option "" ["list-extensions"]
1330+ (NoArg
1331+ (\_ -> do
1332+ let showExt x = drop 4 (show x) ++
1333+ if extensionEnabled x pandocExtensions
1334+ then " +"
1335+ else " -"
1336+ mapM_ (UTF8.hPutStrLn stdout . showExt)
1337+ ([minBound..maxBound] :: [Extension])
1338+ exitSuccess ))
1339+ ""
1340+
1341+ , Option "" ["list-highlight-languages"]
1342+ (NoArg
1343+ (\_ -> do
1344+ let langs = [ T.unpack (T.toLower (sShortname s))
1345+ | s <- M.elems defaultSyntaxMap
1346+ , sShortname s `notElem`
1347+ [T.pack "Alert", T.pack "Alert_indent"]
1348+ ]
1349+ mapM_ (UTF8.hPutStrLn stdout) langs
1350+ exitSuccess ))
1351+ ""
1352+
1353+ , Option "" ["list-highlight-styles"]
1354+ (NoArg
1355+ (\_ -> do
1356+ mapM_ (UTF8.hPutStrLn stdout) $
1357+ map fst highlightingStyles
1358+ exitSuccess ))
1359+ ""
1360+
1361+ , Option "v" ["version"]
1362+ (NoArg
1363+ (\_ -> do
1364+ prg <- getProgName
1365+ defaultDatadir <- E.catch
1366+ (getAppUserDataDirectory "pandoc")
1367+ (\e -> let _ = (e :: E.SomeException)
1368+ in return "")
1369+ UTF8.hPutStrLn stdout (prg ++ " " ++ pandocVersion ++
1370+ compileInfo ++ "\nDefault user data directory: " ++
1371+ defaultDatadir ++ copyrightMessage)
1372+ exitSuccess ))
1373+ "" -- "Print version"
1374+
1375+ , Option "h" ["help"]
1376+ (NoArg
1377+ (\_ -> do
1378+ prg <- getProgName
1379+ UTF8.hPutStr stdout (usageMessage prg options)
1380+ exitSuccess ))
1381+ "" -- "Show help"
1382+
1383+ ]
1384+
1385+-- Returns usage message
1386+usageMessage :: String -> [OptDescr (Opt -> IO Opt)] -> String
1387+usageMessage programName = usageInfo (programName ++ " [OPTIONS] [FILES]")
1388+
1389+copyrightMessage :: String
1390+copyrightMessage = intercalate "\n" [
1391+ "",
1392+ "Copyright (C) 2006-2016 John MacFarlane",
1393+ "Web: http://pandoc.org",
1394+ "This is free software; see the source for copying conditions.",
1395+ "There is no warranty, not even for merchantability or fitness",
1396+ "for a particular purpose." ]
1397+
1398+compileInfo :: String
1399+compileInfo =
1400+ "\nCompiled with pandoc-types " ++ VERSION_pandoc_types ++ ", texmath " ++
1401+ VERSION_texmath ++ ", skylighting " ++ VERSION_skylighting
1402+
1403+handelUnrecognizedOption :: String -> [String] -> [String]
1404+handelUnrecognizedOption "--smart" =
1405+ (("--smart has been removed. Use +smart or -smart extension instead.\n" ++
1406+ "For example: pandoc -f markdown+smart -t markdown-smart.") :)
1407+handelUnrecognizedOption "-S" = handelUnrecognizedOption "--smart"
1408+handelUnrecognizedOption "--old-dashes" =
1409+ ("--old-dashes has been removed. Use +old_dashes extension instead." :)
1410+handelUnrecognizedOption "--no-wrap" =
1411+ ("--no-wrap has been removed. Use --wrap=none instead." :)
1412+handelUnrecognizedOption "--chapters" =
1413+ ("--chapters has been removed. Use --top-level-division=chapter instead." :)
1414+handelUnrecognizedOption "--reference-docx" =
1415+ ("--reference-docx has been removed. Use --reference-doc instead." :)
1416+handelUnrecognizedOption "--reference-odt" =
1417+ ("--reference-odt has been removed. Use --reference-doc instead." :)
1418+handelUnrecognizedOption x =
1419+ (("Unknown option " ++ x ++ ".") :)
1420+
1421+uppercaseFirstLetter :: String -> String
1422+uppercaseFirstLetter (c:cs) = toUpper c : cs
1423+uppercaseFirstLetter [] = []
1424+
1425+readers'names :: [String]
1426+readers'names = sort (map fst (readers :: [(String, Reader PandocIO)]))
1427+
1428+writers'names :: [String]
1429+writers'names = sort (map fst (writers :: [(String, Writer PandocIO)]))
1430+
1431+splitField :: String -> (String, String)
1432+splitField s =
1433+ case break (`elem` ":=") s of
1434+ (k,_:v) -> (k,v)
1435+ (k,[]) -> (k,"true")
1436+