@@ -39,7 +39,6 @@ module Text.Pandoc.App (
3939 ) where
4040import Control.Applicative ((<|>))
4141import qualified Control.Exception as E
42−import Control.Exception.Extensible (throwIO)
4342import Control.Monad
4443import Control.Monad.Trans
4544import Data.Aeson (eitherDecode', encode)
@@ -68,6 +67,7 @@ import System.FilePath
6867import System.IO (stderr, stdout)
6968import System.IO.Error (isDoesNotExistError)
7069import Text.Pandoc
70+import Text.Pandoc.Error (PandocError(..))
7171import Text.Pandoc.Builder (setMeta)
7272import Text.Pandoc.Class (PandocIO, getLog, withMediaBag)
7373import Text.Pandoc.Highlighting (highlightingStyles)
@@ -76,7 +76,7 @@ import Text.Pandoc.MediaBag (MediaBag, extractMediaBag, mediaDirectory)
7676import Text.Pandoc.PDF (makePDF)
7777import Text.Pandoc.Process (pipeProcess)
7878import Text.Pandoc.SelfContained (makeSelfContained, makeDataURI)
79−import Text.Pandoc.Shared (err, headerShift, openURL, readDataFile,
79+import Text.Pandoc.Shared (headerShift, openURL, readDataFile,
8080 readDataFileUTF8, safeRead, tabFilter)
8181import qualified Text.Pandoc.UTF8 as UTF8
8282import Text.Pandoc.Walk (walk)
@@ -98,7 +98,8 @@ parseOptions options' defaults = do
9898 let unknownOptionErrors = foldr handleUnrecognizedOption [] unrecognizedOpts
9999
100100 unless (null errors && null unknownOptionErrors) $
101− err 2 $ concat errors ++ unlines unknownOptionErrors ++
101+ E.throwIO $ PandocAppError 2 $
102+ concat errors ++ unlines unknownOptionErrors ++
102103 ("Try " ++ prg ++ " --help for more information.")
103104
104105 -- thread option data structure through all supplied option actions
@@ -175,7 +176,7 @@ convertWithOpts opts = do
175176 (\o d -> liftIO $ writeCustom writerName o d)
176177 :: Writer PandocIO)
177178 else case getWriter writerName of
178− Left e -> err 9 $
179+ Left e -> E.throwIO $ PandocAppError 9 $
179180 if format == "pdf"
180181 then e ++
181182 "\nTo create a pdf with pandoc, use " ++
@@ -189,7 +190,7 @@ convertWithOpts opts = do
189190 -- the sake of the text2tags reader.
190191 reader <- case getReader readerName of
191192 Right r -> return (r :: Reader PandocIO)
192− Left e -> err 7 e'
193+ Left e -> E.throwIO $ PandocAppError 7 e'
193194 where e' = case readerName of
194195 "pdf" -> e ++
195196 "\nPandoc can convert to PDF, but not from PDF."
@@ -204,7 +205,7 @@ convertWithOpts opts = do
204205 Nothing -> do
205206 deftemp <- getDefaultTemplate datadir format
206207 case deftemp of
207− Left e -> throwIO e
208+ Left e -> E.throwIO e
208209 Right t -> return (Just t)
209210 Just tp -> do
210211 -- strip off extensions
@@ -217,8 +218,8 @@ convertWithOpts opts = do
217218 (readDataFileUTF8 datadir
218219 ("templates" </> tp'))
219220 (\e' -> let _ = (e' :: E.SomeException)
220− in throwIO e')
221− else throwIO e)
221+ in E.throwIO e')
222+ else E.throwIO e)
222223
223224 let addStringAsVariable varname s vars = return $ (varname, s) : vars
224225
@@ -304,7 +305,7 @@ convertWithOpts opts = do
304305 let addSyntaxMap existingmap f = do
305306 res <- parseSyntaxDefinition f
306307 case res of
307− Left errstr -> err 67 errstr
308+ Left errstr -> E.throwIO $ PandocAppError 67 errstr
308309 Right syn -> return $ addSyntaxDefinition syn existingmap
309310
310311 syntaxMap <- foldM addSyntaxMap defaultSyntaxMap
@@ -312,7 +313,8 @@ convertWithOpts opts = do
312313
313314 case missingIncludes (M.elems syntaxMap) of
314315 [] -> return ()
315− xs -> err 73 $ "Missing syntax definitions:\n" ++
316+ xs -> E.throwIO $ PandocAppError 73 $
317+ "Missing syntax definitions:\n" ++
316318 unlines (map
317319 (\(syn,dep) -> (T.unpack syn ++ " requires " ++
318320 T.unpack dep ++ " through IncludeRules.")) xs)
@@ -358,7 +360,8 @@ convertWithOpts opts = do
358360 istty <- queryTerminal stdOutput
359361#endif
360362 when (istty && not (isTextFormat format) && outputFile == "-") $
361− err 5 $ "Cannot write " ++ format ++ " output to stdout.\n" ++
363+ E.throwIO $ PandocAppError 5 $
364+ "Cannot write " ++ format ++ " output to stdout.\n" ++
362365 "Specify an output file using the -o option."
363366
364367
@@ -386,7 +389,8 @@ convertWithOpts opts = do
386389 Just logfile -> B.writeFile logfile (encodeLogMessages reports)
387390 let isWarning msg = messageVerbosity msg == WARNING
388391 when (optFailIfWarnings opts && any isWarning reports) $
389− err 3 "Failing because there were warnings."
392+ E.throwIO $
393+ PandocAppError 3 "Failing because there were warnings."
390394 return res
391395
392396 let sourceToDoc :: [FilePath] -> PandocIO (Pandoc, MediaBag)
@@ -429,8 +433,8 @@ convertWithOpts opts = do
429433 -- make sure writer is latex, beamer, context, html5 or ms
430434 unless (laTeXOutput || conTeXtOutput || html5Output ||
431435 msOutput) $
432− err 47 $ "cannot produce pdf output with " ++ format ++
433− " writer"
436+ liftIO $ E.throwIO $ PandocAppError 47 $
437+ "cannot produce pdf output with " ++ format ++ " writer"
434438
435439 let pdfprog = case () of
436440 _ | conTeXtOutput -> "context"
@@ -441,7 +445,8 @@ convertWithOpts opts = do
441445 -- check for pdf creating program
442446 mbPdfProg <- liftIO $ findExecutable pdfprog
443447 when (isNothing mbPdfProg) $
444− err 41 $ pdfprog ++ " not found. " ++
448+ liftIO $ E.throwIO $ PandocAppError 41 $
449+ pdfprog ++ " not found. " ++
445450 pdfprog ++ " is needed for pdf output."
446451
447452 res <- makePDF pdfprog f writerOptions verbosity media doc'
@@ -450,7 +455,7 @@ convertWithOpts opts = do
450455 Left err' -> liftIO $ do
451456 B.hPutStr stderr err'
452457 B.hPut stderr $ B.pack [10]
453− err 43 "Error producing PDF"
458+ E.throwIO $ PandocAppError 43 "Error producing PDF"
454459 | otherwise -> do
455460 let htmlFormat = format `elem`
456461 ["html","html4","html5","s5","slidy","slideous","dzslides","revealjs"]
@@ -492,19 +497,21 @@ externalFilter f args' d = liftIO $ do
492497 unless (exists && isExecutable) $ do
493498 mbExe <- findExecutable f'
494499 when (isNothing mbExe) $
495− err 83 $ "Error running filter " ++ f ++ ":\n" ++
496− "Could not find executable '" ++ f' ++ "'."
500+ E.throwIO $ PandocAppError 83 $
501+ "Error running filter " ++ f ++ ":\n" ++
502+ "Could not find executable '" ++ f' ++ "'."
497503 env <- getEnvironment
498504 let env' = Just $ ("PANDOC_VERSION", pandocVersion) : env
499505 (exitcode, outbs) <- E.handle filterException $
500506 pipeProcess env' f' args'' $ encode d
501507 case exitcode of
502508 ExitSuccess -> return $ either error id $ eitherDecode' outbs
503− ExitFailure ec -> err 83 $ "Error running filter " ++ f ++ "\n" ++
504− "Filter returned error status " ++ show ec
509+ ExitFailure ec -> E.throwIO $ PandocAppError 83 $
510+ "Error running filter " ++ f ++ "\n" ++
511+ "Filter returned error status " ++ show ec
505512 where filterException :: E.SomeException -> IO a
506− filterException e = err 83 $ "Error running filter " ++ f ++ "\n" ++
507− show e
513+ filterException e = E.throwIO $ PandocAppError 83 $
514+ "Error running filter " ++ f ++ "\n" ++ show e
508515
509516-- | Data structure for command line options.
510517data Opt = Opt
@@ -806,12 +813,14 @@ lookupHighlightStyle (Just s)
806813 | takeExtension s == ".theme" = -- attempt to load KDE theme
807814 do contents <- B.readFile s
808815 case parseTheme contents of
809− Left _ -> err 69 $ "Could not read highlighting theme " ++ s
816+ Left _ -> E.throwIO $ PandocAppError 69 $
817+ "Could not read highlighting theme " ++ s
810818 Right sty -> return (Just sty)
811819 | otherwise =
812820 case lookup (map toLower s) highlightingStyles of
813821 Just sty -> return (Just sty)
814− Nothing -> err 68 $ "Unknown highlight-style " ++ s
822+ Nothing -> E.throwIO $ PandocAppError 68 $
823+ "Unknown highlight-style " ++ s
815824
816825-- | A list of functions, each transforming the options data structure
817826-- in response to a command-line option.
@@ -847,8 +856,8 @@ options =
847856 case safeRead arg of
848857 Just t | t > 0 && t < 6 ->
849858 return opt{ optBaseHeaderLevel = t }
850− _ -> err 19
851− "base-header-level must be 1-5")
859+ _ -> E.throwIO $ PandocAppError 19
860+ "base-header-level must be 1-5")
852861 "NUMBER")
853862 "" -- "Headers base level"
854863
@@ -881,8 +890,8 @@ options =
881890 (\arg opt ->
882891 case safeRead arg of
883892 Just t | t > 0 -> return opt { optTabStop = t }
884− _ -> err 31
885− "tab-stop must be a number greater than 0")
893+ _ -> E.throwIO $ PandocAppError 31
894+ "tab-stop must be a number greater than 0")
886895 "NUMBER")
887896 "" -- "Tab stop (default 4)"
888897
@@ -893,7 +902,7 @@ options =
893902 "accept" -> return AcceptChanges
894903 "reject" -> return RejectChanges
895904 "all" -> return AllChanges
896− _ -> err 6
905+ _ -> E.throwIO $ PandocAppError 6
897906 ("Unknown option for track-changes: " ++ arg)
898907 return opt { optTrackChanges = action })
899908 "accept|reject|all")
@@ -964,7 +973,7 @@ options =
964973 (\arg opt ->
965974 case safeRead arg of
966975 Just t | t > 0 -> return opt { optDpi = t }
967− _ -> err 31
976+ _ -> E.throwIO $ PandocAppError 31
968977 "dpi must be a number greater than 0")
969978 "NUMBER")
970979 "" -- "Dpi (default 96)"
@@ -974,7 +983,8 @@ options =
974983 (\arg opt ->
975984 case safeRead ("Wrap" ++ uppercaseFirstLetter arg) of
976985 Just o -> return opt { optWrapText = o }
977− Nothing -> err 77 "--wrap must be auto, none, or preserve")
986+ Nothing -> E.throwIO $ PandocAppError 77
987+ "--wrap must be auto, none, or preserve")
978988 "auto|none|preserve")
979989 "" -- "Option for wrapping text in output"
980990
@@ -983,7 +993,7 @@ options =
983993 (\arg opt ->
984994 case safeRead arg of
985995 Just t | t > 0 -> return opt { optColumns = t }
986− _ -> err 33
996+ _ -> E.throwIO $ PandocAppError 33
987997 "columns must be a number greater than 0")
988998 "NUMBER")
989999 "" -- "Length of line in characters"
@@ -999,7 +1009,7 @@ options =
9991009 case safeRead arg of
10001010 Just t | t >= 1 && t <= 6 ->
10011011 return opt { optTOCDepth = t }
1002− _ -> err 57
1012+ _ -> E.throwIO $ PandocAppError 57
10031013 "TOC level must be a number between 1 and 6")
10041014 "NUMBER")
10051015 "" -- "Number of levels to include in TOC"
@@ -1075,7 +1085,7 @@ options =
10751085 "block" -> return EndOfBlock
10761086 "section" -> return EndOfSection
10771087 "document" -> return EndOfDocument
1078− _ -> err 6
1088+ _ -> E.throwIO $ PandocAppError 6
10791089 ("Unknown option for reference-location: " ++ arg)
10801090 return opt { optReferenceLocation = action })
10811091 "block|section|document")
@@ -1092,8 +1102,9 @@ options =
10921102 let tldName = "TopLevel" ++ uppercaseFirstLetter arg
10931103 case safeRead tldName of
10941104 Just tlDiv -> return opt { optTopLevelDivision = tlDiv }
1095− _ -> err 76 ("Top-level division must be " ++
1096− "section, chapter, part, or default"))
1105+ _ -> E.throwIO $ PandocAppError 76
1106+ ("Top-level division must be " ++
1107+ "section, chapter, part, or default"))
10971108 "section|chapter|part")
10981109 "" -- "Use top-level division type in LaTeX, ConTeXt, DocBook"
10991110
@@ -1108,7 +1119,8 @@ options =
11081119 case safeRead ('[':arg ++ "]") of
11091120 Just ns -> return opt { optNumberOffset = ns,
11101121 optNumberSections = True }
1111− _ -> err 57 "could not parse number-offset")
1122+ _ -> E.throwIO $ PandocAppError 57
1123+ "could not parse number-offset")
11121124 "NUMBERS")
11131125 "" -- "Starting number for sections, subsections, etc."
11141126
@@ -1128,7 +1140,7 @@ options =
11281140 case safeRead arg of
11291141 Just t | t >= 1 && t <= 6 ->
11301142 return opt { optSlideLevel = Just t }
1131− _ -> err 39
1143+ _ -> E.throwIO $ PandocAppError 39
11321144 "slide level must be a number between 1 and 6")
11331145 "NUMBER")
11341146 "" -- "Force header level for slides"
@@ -1151,7 +1163,7 @@ options =
11511163 "references" -> return ReferenceObfuscation
11521164 "javascript" -> return JavascriptObfuscation
11531165 "none" -> return NoObfuscation
1154− _ -> err 6
1166+ _ -> E.throwIO $ PandocAppError 6
11551167 ("Unknown obfuscation method: " ++ arg)
11561168 return opt { optEmailObfuscation = method })
11571169 "none|javascript|references")
@@ -1213,7 +1225,7 @@ options =
12131225 case safeRead arg of
12141226 Just t | t >= 1 && t <= 6 ->
12151227 return opt { optEpubChapterLevel = t }
1216− _ -> err 59
1228+ _ -> E.throwIO $ PandocAppError 59
12171229 "chapter level must be a number between 1 and 6")
12181230 "NUMBER")
12191231 "" -- "Header level at which to split chapters in EPUB"
@@ -1224,7 +1236,7 @@ options =
12241236 let b = takeBaseName arg
12251237 if b `elem` ["pdflatex", "lualatex", "xelatex"]
12261238 then return opt { optLaTeXEngine = arg }
1227− else err 45 "latex-engine must be pdflatex, lualatex, or xelatex.")
1239+ else E.throwIO $ PandocAppError 45 "latex-engine must be pdflatex, lualatex, or xelatex.")
12281240 "PROGRAM")
12291241 "" -- "Name of latex program to use in generating PDF"
12301242