@@ -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+