diff options
author | John MacFarlane <jgm@berkeley.edu> | 2017-04-02 23:02:55 +0200 |
---|---|---|
committer | John MacFarlane <jgm@berkeley.edu> | 2017-04-02 23:04:48 +0200 |
commit | 913db947a9cb43b6f449db2cd4c85fd74aa1ac8f (patch) | |
tree | 48af245903a81e6d80f1e8b7f4c8f519d1e7571b /src/Text/Pandoc/App.hs | |
parent | 9e78a9d26b73fa603025789a942f70306aaaad22 (diff) | |
download | pandoc-913db947a9cb43b6f449db2cd4c85fd74aa1ac8f.tar.gz |
Text.Pandoc.App: Throw errors rather than exiting.
These are caught (and lead to exit) in pandoc.hs, but
other uses of Text.Pandoc.App may want to recover in another
way.
Added PandocAppError to PandocError (API change).
This is a stopgap: later we should have a separate constructor
for each type of error.
Also fixed uses of 'exit' in Shared.readDataFile, and
removed 'err' from Shared (API change).
Finally, removed the dependency on extensible-exceptions.
See #3548.
Diffstat (limited to 'src/Text/Pandoc/App.hs')
-rw-r--r-- | src/Text/Pandoc/App.hs | 94 |
1 files changed, 53 insertions, 41 deletions
diff --git a/src/Text/Pandoc/App.hs b/src/Text/Pandoc/App.hs index 8f0410f12..b7ac4fd75 100644 --- a/src/Text/Pandoc/App.hs +++ b/src/Text/Pandoc/App.hs @@ -39,7 +39,6 @@ module Text.Pandoc.App ( ) where import Control.Applicative ((<|>)) import qualified Control.Exception as E -import Control.Exception.Extensible (throwIO) import Control.Monad import Control.Monad.Trans import Data.Aeson (eitherDecode', encode) @@ -68,6 +67,7 @@ import System.FilePath import System.IO (stderr, stdout) import System.IO.Error (isDoesNotExistError) import Text.Pandoc +import Text.Pandoc.Error (PandocError(..)) import Text.Pandoc.Builder (setMeta) import Text.Pandoc.Class (PandocIO, getLog, withMediaBag) import Text.Pandoc.Highlighting (highlightingStyles) @@ -76,7 +76,7 @@ import Text.Pandoc.MediaBag (MediaBag, extractMediaBag, mediaDirectory) import Text.Pandoc.PDF (makePDF) import Text.Pandoc.Process (pipeProcess) import Text.Pandoc.SelfContained (makeSelfContained, makeDataURI) -import Text.Pandoc.Shared (err, headerShift, openURL, readDataFile, +import Text.Pandoc.Shared (headerShift, openURL, readDataFile, readDataFileUTF8, safeRead, tabFilter) import qualified Text.Pandoc.UTF8 as UTF8 import Text.Pandoc.Walk (walk) @@ -98,7 +98,8 @@ parseOptions options' defaults = do let unknownOptionErrors = foldr handleUnrecognizedOption [] unrecognizedOpts unless (null errors && null unknownOptionErrors) $ - err 2 $ concat errors ++ unlines unknownOptionErrors ++ + E.throwIO $ PandocAppError 2 $ + concat errors ++ unlines unknownOptionErrors ++ ("Try " ++ prg ++ " --help for more information.") -- thread option data structure through all supplied option actions @@ -175,7 +176,7 @@ convertWithOpts opts = do (\o d -> liftIO $ writeCustom writerName o d) :: Writer PandocIO) else case getWriter writerName of - Left e -> err 9 $ + Left e -> E.throwIO $ PandocAppError 9 $ if format == "pdf" then e ++ "\nTo create a pdf with pandoc, use " ++ @@ -189,7 +190,7 @@ convertWithOpts opts = do -- the sake of the text2tags reader. reader <- case getReader readerName of Right r -> return (r :: Reader PandocIO) - Left e -> err 7 e' + Left e -> E.throwIO $ PandocAppError 7 e' where e' = case readerName of "pdf" -> e ++ "\nPandoc can convert to PDF, but not from PDF." @@ -204,7 +205,7 @@ convertWithOpts opts = do Nothing -> do deftemp <- getDefaultTemplate datadir format case deftemp of - Left e -> throwIO e + Left e -> E.throwIO e Right t -> return (Just t) Just tp -> do -- strip off extensions @@ -217,8 +218,8 @@ convertWithOpts opts = do (readDataFileUTF8 datadir ("templates" </> tp')) (\e' -> let _ = (e' :: E.SomeException) - in throwIO e') - else throwIO e) + in E.throwIO e') + else E.throwIO e) let addStringAsVariable varname s vars = return $ (varname, s) : vars @@ -304,7 +305,7 @@ convertWithOpts opts = do let addSyntaxMap existingmap f = do res <- parseSyntaxDefinition f case res of - Left errstr -> err 67 errstr + Left errstr -> E.throwIO $ PandocAppError 67 errstr Right syn -> return $ addSyntaxDefinition syn existingmap syntaxMap <- foldM addSyntaxMap defaultSyntaxMap @@ -312,7 +313,8 @@ convertWithOpts opts = do case missingIncludes (M.elems syntaxMap) of [] -> return () - xs -> err 73 $ "Missing syntax definitions:\n" ++ + xs -> E.throwIO $ PandocAppError 73 $ + "Missing syntax definitions:\n" ++ unlines (map (\(syn,dep) -> (T.unpack syn ++ " requires " ++ T.unpack dep ++ " through IncludeRules.")) xs) @@ -358,7 +360,8 @@ convertWithOpts opts = do istty <- queryTerminal stdOutput #endif when (istty && not (isTextFormat format) && outputFile == "-") $ - err 5 $ "Cannot write " ++ format ++ " output to stdout.\n" ++ + E.throwIO $ PandocAppError 5 $ + "Cannot write " ++ format ++ " output to stdout.\n" ++ "Specify an output file using the -o option." @@ -386,7 +389,8 @@ convertWithOpts opts = do Just logfile -> B.writeFile logfile (encodeLogMessages reports) let isWarning msg = messageVerbosity msg == WARNING when (optFailIfWarnings opts && any isWarning reports) $ - err 3 "Failing because there were warnings." + E.throwIO $ + PandocAppError 3 "Failing because there were warnings." return res let sourceToDoc :: [FilePath] -> PandocIO (Pandoc, MediaBag) @@ -429,8 +433,8 @@ convertWithOpts opts = do -- make sure writer is latex, beamer, context, html5 or ms unless (laTeXOutput || conTeXtOutput || html5Output || msOutput) $ - err 47 $ "cannot produce pdf output with " ++ format ++ - " writer" + liftIO $ E.throwIO $ PandocAppError 47 $ + "cannot produce pdf output with " ++ format ++ " writer" let pdfprog = case () of _ | conTeXtOutput -> "context" @@ -441,7 +445,8 @@ convertWithOpts opts = do -- check for pdf creating program mbPdfProg <- liftIO $ findExecutable pdfprog when (isNothing mbPdfProg) $ - err 41 $ pdfprog ++ " not found. " ++ + liftIO $ E.throwIO $ PandocAppError 41 $ + pdfprog ++ " not found. " ++ pdfprog ++ " is needed for pdf output." res <- makePDF pdfprog f writerOptions verbosity media doc' @@ -450,7 +455,7 @@ convertWithOpts opts = do Left err' -> liftIO $ do B.hPutStr stderr err' B.hPut stderr $ B.pack [10] - err 43 "Error producing PDF" + E.throwIO $ PandocAppError 43 "Error producing PDF" | otherwise -> do let htmlFormat = format `elem` ["html","html4","html5","s5","slidy","slideous","dzslides","revealjs"] @@ -492,19 +497,21 @@ externalFilter f args' d = liftIO $ do unless (exists && isExecutable) $ do mbExe <- findExecutable f' when (isNothing mbExe) $ - err 83 $ "Error running filter " ++ f ++ ":\n" ++ - "Could not find executable '" ++ f' ++ "'." + E.throwIO $ PandocAppError 83 $ + "Error running filter " ++ f ++ ":\n" ++ + "Could not find executable '" ++ f' ++ "'." env <- getEnvironment let env' = Just $ ("PANDOC_VERSION", pandocVersion) : env (exitcode, outbs) <- E.handle filterException $ pipeProcess env' f' args'' $ encode d case exitcode of ExitSuccess -> return $ either error id $ eitherDecode' outbs - ExitFailure ec -> err 83 $ "Error running filter " ++ f ++ "\n" ++ - "Filter returned error status " ++ show ec + ExitFailure ec -> E.throwIO $ PandocAppError 83 $ + "Error running filter " ++ f ++ "\n" ++ + "Filter returned error status " ++ show ec where filterException :: E.SomeException -> IO a - filterException e = err 83 $ "Error running filter " ++ f ++ "\n" ++ - show e + filterException e = E.throwIO $ PandocAppError 83 $ + "Error running filter " ++ f ++ "\n" ++ show e -- | Data structure for command line options. data Opt = Opt @@ -806,12 +813,14 @@ lookupHighlightStyle (Just s) | takeExtension s == ".theme" = -- attempt to load KDE theme do contents <- B.readFile s case parseTheme contents of - Left _ -> err 69 $ "Could not read highlighting theme " ++ s + Left _ -> E.throwIO $ PandocAppError 69 $ + "Could not read highlighting theme " ++ s Right sty -> return (Just sty) | otherwise = case lookup (map toLower s) highlightingStyles of Just sty -> return (Just sty) - Nothing -> err 68 $ "Unknown highlight-style " ++ s + Nothing -> E.throwIO $ PandocAppError 68 $ + "Unknown highlight-style " ++ s -- | A list of functions, each transforming the options data structure -- in response to a command-line option. @@ -847,8 +856,8 @@ options = case safeRead arg of Just t | t > 0 && t < 6 -> return opt{ optBaseHeaderLevel = t } - _ -> err 19 - "base-header-level must be 1-5") + _ -> E.throwIO $ PandocAppError 19 + "base-header-level must be 1-5") "NUMBER") "" -- "Headers base level" @@ -881,8 +890,8 @@ options = (\arg opt -> case safeRead arg of Just t | t > 0 -> return opt { optTabStop = t } - _ -> err 31 - "tab-stop must be a number greater than 0") + _ -> E.throwIO $ PandocAppError 31 + "tab-stop must be a number greater than 0") "NUMBER") "" -- "Tab stop (default 4)" @@ -893,7 +902,7 @@ options = "accept" -> return AcceptChanges "reject" -> return RejectChanges "all" -> return AllChanges - _ -> err 6 + _ -> E.throwIO $ PandocAppError 6 ("Unknown option for track-changes: " ++ arg) return opt { optTrackChanges = action }) "accept|reject|all") @@ -964,7 +973,7 @@ options = (\arg opt -> case safeRead arg of Just t | t > 0 -> return opt { optDpi = t } - _ -> err 31 + _ -> E.throwIO $ PandocAppError 31 "dpi must be a number greater than 0") "NUMBER") "" -- "Dpi (default 96)" @@ -974,7 +983,8 @@ options = (\arg opt -> case safeRead ("Wrap" ++ uppercaseFirstLetter arg) of Just o -> return opt { optWrapText = o } - Nothing -> err 77 "--wrap must be auto, none, or preserve") + Nothing -> E.throwIO $ PandocAppError 77 + "--wrap must be auto, none, or preserve") "auto|none|preserve") "" -- "Option for wrapping text in output" @@ -983,7 +993,7 @@ options = (\arg opt -> case safeRead arg of Just t | t > 0 -> return opt { optColumns = t } - _ -> err 33 + _ -> E.throwIO $ PandocAppError 33 "columns must be a number greater than 0") "NUMBER") "" -- "Length of line in characters" @@ -999,7 +1009,7 @@ options = case safeRead arg of Just t | t >= 1 && t <= 6 -> return opt { optTOCDepth = t } - _ -> err 57 + _ -> E.throwIO $ PandocAppError 57 "TOC level must be a number between 1 and 6") "NUMBER") "" -- "Number of levels to include in TOC" @@ -1075,7 +1085,7 @@ options = "block" -> return EndOfBlock "section" -> return EndOfSection "document" -> return EndOfDocument - _ -> err 6 + _ -> E.throwIO $ PandocAppError 6 ("Unknown option for reference-location: " ++ arg) return opt { optReferenceLocation = action }) "block|section|document") @@ -1092,8 +1102,9 @@ options = let tldName = "TopLevel" ++ uppercaseFirstLetter arg case safeRead tldName of Just tlDiv -> return opt { optTopLevelDivision = tlDiv } - _ -> err 76 ("Top-level division must be " ++ - "section, chapter, part, or default")) + _ -> E.throwIO $ PandocAppError 76 + ("Top-level division must be " ++ + "section, chapter, part, or default")) "section|chapter|part") "" -- "Use top-level division type in LaTeX, ConTeXt, DocBook" @@ -1108,7 +1119,8 @@ options = case safeRead ('[':arg ++ "]") of Just ns -> return opt { optNumberOffset = ns, optNumberSections = True } - _ -> err 57 "could not parse number-offset") + _ -> E.throwIO $ PandocAppError 57 + "could not parse number-offset") "NUMBERS") "" -- "Starting number for sections, subsections, etc." @@ -1128,7 +1140,7 @@ options = case safeRead arg of Just t | t >= 1 && t <= 6 -> return opt { optSlideLevel = Just t } - _ -> err 39 + _ -> E.throwIO $ PandocAppError 39 "slide level must be a number between 1 and 6") "NUMBER") "" -- "Force header level for slides" @@ -1151,7 +1163,7 @@ options = "references" -> return ReferenceObfuscation "javascript" -> return JavascriptObfuscation "none" -> return NoObfuscation - _ -> err 6 + _ -> E.throwIO $ PandocAppError 6 ("Unknown obfuscation method: " ++ arg) return opt { optEmailObfuscation = method }) "none|javascript|references") @@ -1213,7 +1225,7 @@ options = case safeRead arg of Just t | t >= 1 && t <= 6 -> return opt { optEpubChapterLevel = t } - _ -> err 59 + _ -> E.throwIO $ PandocAppError 59 "chapter level must be a number between 1 and 6") "NUMBER") "" -- "Header level at which to split chapters in EPUB" @@ -1224,7 +1236,7 @@ options = let b = takeBaseName arg if b `elem` ["pdflatex", "lualatex", "xelatex"] then return opt { optLaTeXEngine = arg } - else err 45 "latex-engine must be pdflatex, lualatex, or xelatex.") + else E.throwIO $ PandocAppError 45 "latex-engine must be pdflatex, lualatex, or xelatex.") "PROGRAM") "" -- "Name of latex program to use in generating PDF" |