{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
module Text.Pandoc.Error (
PandocError(..),
handleError) where
import Control.Exception (Exception)
import Data.Typeable (Typeable)
import Data.Word (Word8)
import Data.Text (Text)
import qualified Data.Text as T
import GHC.Generics (Generic)
import Network.HTTP.Client (HttpException)
import System.Exit (ExitCode (..), exitWith)
import System.IO (stderr)
import qualified Text.Pandoc.UTF8 as UTF8
import Text.Printf (printf)
import Text.Parsec.Error
import Text.Parsec.Pos hiding (Line)
type Input = Text
data PandocError = PandocIOError Text IOError
| PandocHttpError Text HttpException
| PandocShouldNeverHappenError Text
| PandocSomeError Text
| PandocParseError Text
| PandocParsecError Input ParseError
| PandocMakePDFError Text
| PandocOptionError Text
| PandocSyntaxMapError Text
| PandocFailOnWarningError
| PandocPDFProgramNotFoundError Text
| PandocPDFError Text
| PandocFilterError Text Text
| PandocCouldNotFindDataFileError Text
| PandocResourceNotFound Text
| PandocTemplateError Text
| PandocAppError Text
| PandocEpubSubdirectoryError Text
| PandocMacroLoop Text
| PandocUTF8DecodingError Text Int Word8
| PandocIpynbDecodingError Text
| PandocUnknownReaderError Text
| PandocUnknownWriterError Text
| PandocUnsupportedExtensionError Text Text
deriving (Int -> PandocError -> ShowS
[PandocError] -> ShowS
PandocError -> String
(Int -> PandocError -> ShowS)
-> (PandocError -> String)
-> ([PandocError] -> ShowS)
-> Show PandocError
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PandocError] -> ShowS
$cshowList :: [PandocError] -> ShowS
show :: PandocError -> String
$cshow :: PandocError -> String
showsPrec :: Int -> PandocError -> ShowS
$cshowsPrec :: Int -> PandocError -> ShowS
Show, Typeable, (forall x. PandocError -> Rep PandocError x)
-> (forall x. Rep PandocError x -> PandocError)
-> Generic PandocError
forall x. Rep PandocError x -> PandocError
forall x. PandocError -> Rep PandocError x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep PandocError x -> PandocError
$cfrom :: forall x. PandocError -> Rep PandocError x
Generic)
instance Exception PandocError
handleError :: Either PandocError a -> IO a
handleError :: Either PandocError a -> IO a
handleError (Right r :: a
r) = a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return a
r
handleError (Left e :: PandocError
e) =
case PandocError
e of
PandocIOError _ err' :: IOError
err' -> IOError -> IO a
forall a. IOError -> IO a
ioError IOError
err'
PandocHttpError u :: Text
u err' :: HttpException
err' -> Int -> Text -> IO a
forall a. Int -> Text -> IO a
err 61 (Text -> IO a) -> Text -> IO a
forall a b. (a -> b) -> a -> b
$
"Could not fetch " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
u Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> "\n" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> HttpException -> Text
forall a. Show a => a -> Text
tshow HttpException
err'
PandocShouldNeverHappenError s :: Text
s -> Int -> Text -> IO a
forall a. Int -> Text -> IO a
err 62 (Text -> IO a) -> Text -> IO a
forall a b. (a -> b) -> a -> b
$
"Something we thought was impossible happened!\n" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
"Please report this to pandoc's developers: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
s
PandocSomeError s :: Text
s -> Int -> Text -> IO a
forall a. Int -> Text -> IO a
err 63 Text
s
PandocParseError s :: Text
s -> Int -> Text -> IO a
forall a. Int -> Text -> IO a
err 64 Text
s
PandocParsecError input :: Text
input err' :: ParseError
err' ->
let errPos :: SourcePos
errPos = ParseError -> SourcePos
errorPos ParseError
err'
errLine :: Int
errLine = SourcePos -> Int
sourceLine SourcePos
errPos
errColumn :: Int
errColumn = SourcePos -> Int
sourceColumn SourcePos
errPos
ls :: [Text]
ls = Text -> [Text]
T.lines Text
input [Text] -> [Text] -> [Text]
forall a. Semigroup a => a -> a -> a
<> [""]
errorInFile :: Text
errorInFile = if [Text] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Text]
ls Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
errLine Int -> Int -> Int
forall a. Num a => a -> a -> a
- 1
then [Text] -> Text
T.concat ["\n", [Text]
ls [Text] -> Int -> Text
forall a. [a] -> Int -> a
!! (Int
errLine Int -> Int -> Int
forall a. Num a => a -> a -> a
- 1)
,"\n", Int -> Text -> Text
T.replicate (Int
errColumn Int -> Int -> Int
forall a. Num a => a -> a -> a
- 1) " "
,"^"]
else ""
in Int -> Text -> IO a
forall a. Int -> Text -> IO a
err 65 (Text -> IO a) -> Text -> IO a
forall a b. (a -> b) -> a -> b
$ "\nError at " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> ParseError -> Text
forall a. Show a => a -> Text
tshow ParseError
err' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
if SourcePos -> String
sourceName SourcePos
errPos String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== "source"
then Text
errorInFile
else ""
PandocMakePDFError s :: Text
s -> Int -> Text -> IO a
forall a. Int -> Text -> IO a
err 66 Text
s
PandocOptionError s :: Text
s -> Int -> Text -> IO a
forall a. Int -> Text -> IO a
err 6 Text
s
PandocSyntaxMapError s :: Text
s -> Int -> Text -> IO a
forall a. Int -> Text -> IO a
err 67 Text
s
PandocFailOnWarningError -> Int -> Text -> IO a
forall a. Int -> Text -> IO a
err 3 "Failing because there were warnings."
PandocPDFProgramNotFoundError pdfprog :: Text
pdfprog -> Int -> Text -> IO a
forall a. Int -> Text -> IO a
err 47 (Text -> IO a) -> Text -> IO a
forall a b. (a -> b) -> a -> b
$
Text
pdfprog Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> " not found. Please select a different --pdf-engine or install " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
pdfprog
PandocPDFError logmsg :: Text
logmsg -> Int -> Text -> IO a
forall a. Int -> Text -> IO a
err 43 (Text -> IO a) -> Text -> IO a
forall a b. (a -> b) -> a -> b
$ "Error producing PDF.\n" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
logmsg
PandocFilterError filtername :: Text
filtername msg :: Text
msg -> Int -> Text -> IO a
forall a. Int -> Text -> IO a
err 83 (Text -> IO a) -> Text -> IO a
forall a b. (a -> b) -> a -> b
$ "Error running filter " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
Text
filtername Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> ":\n" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
msg
PandocCouldNotFindDataFileError fn :: Text
fn -> Int -> Text -> IO a
forall a. Int -> Text -> IO a
err 97 (Text -> IO a) -> Text -> IO a
forall a b. (a -> b) -> a -> b
$
"Could not find data file " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
fn
PandocResourceNotFound fn :: Text
fn -> Int -> Text -> IO a
forall a. Int -> Text -> IO a
err 99 (Text -> IO a) -> Text -> IO a
forall a b. (a -> b) -> a -> b
$
"File " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
fn Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> " not found in resource path"
PandocTemplateError s :: Text
s -> Int -> Text -> IO a
forall a. Int -> Text -> IO a
err 5 (Text -> IO a) -> Text -> IO a
forall a b. (a -> b) -> a -> b
$ "Error compiling template " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
s
PandocAppError s :: Text
s -> Int -> Text -> IO a
forall a. Int -> Text -> IO a
err 4 Text
s
PandocEpubSubdirectoryError s :: Text
s -> Int -> Text -> IO a
forall a. Int -> Text -> IO a
err 31 (Text -> IO a) -> Text -> IO a
forall a b. (a -> b) -> a -> b
$
"EPUB subdirectory name '" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
s Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> "' contains illegal characters"
PandocMacroLoop s :: Text
s -> Int -> Text -> IO a
forall a. Int -> Text -> IO a
err 91 (Text -> IO a) -> Text -> IO a
forall a b. (a -> b) -> a -> b
$
"Loop encountered in expanding macro " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
s
PandocUTF8DecodingError f :: Text
f offset :: Int
offset w :: Word8
w -> Int -> Text -> IO a
forall a. Int -> Text -> IO a
err 92 (Text -> IO a) -> Text -> IO a
forall a b. (a -> b) -> a -> b
$
"UTF-8 decoding error in " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
f Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> " at byte offset " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall a. Show a => a -> Text
tshow Int
offset Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
" (" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (String -> Word8 -> String
forall r. PrintfType r => String -> r
printf "%2x" Word8
w) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> ").\n" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
"The input must be a UTF-8 encoded text."
PandocIpynbDecodingError w :: Text
w -> Int -> Text -> IO a
forall a. Int -> Text -> IO a
err 93 (Text -> IO a) -> Text -> IO a
forall a b. (a -> b) -> a -> b
$
"ipynb decoding error: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
w
PandocUnknownReaderError r :: Text
r -> Int -> Text -> IO a
forall a. Int -> Text -> IO a
err 21 (Text -> IO a) -> Text -> IO a
forall a b. (a -> b) -> a -> b
$
"Unknown input format " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
r Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
case Text
r of
"doc" -> "\nPandoc can convert from DOCX, but not from DOC." Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
"\nTry using Word to save your DOC file as DOCX," Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
" and convert that with pandoc."
"pdf" -> "\nPandoc can convert to PDF, but not from PDF."
_ -> ""
PandocUnknownWriterError w :: Text
w -> Int -> Text -> IO a
forall a. Int -> Text -> IO a
err 22 (Text -> IO a) -> Text -> IO a
forall a b. (a -> b) -> a -> b
$
"Unknown output format " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
w Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
case Text
w of
"pdf" -> "To create a pdf using pandoc, use" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
" -t latex|beamer|context|ms|html5" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
"\nand specify an output file with " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
".pdf extension (-o filename.pdf)."
"doc" -> "\nPandoc can convert to DOCX, but not from DOC."
_ -> ""
PandocUnsupportedExtensionError ext :: Text
ext f :: Text
f -> Int -> Text -> IO a
forall a. Int -> Text -> IO a
err 23 (Text -> IO a) -> Text -> IO a
forall a b. (a -> b) -> a -> b
$
"The extension " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
ext Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> " is not supported " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
"for " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
f
err :: Int -> Text -> IO a
err :: Int -> Text -> IO a
err exitCode :: Int
exitCode msg :: Text
msg = do
Handle -> String -> IO ()
UTF8.hPutStrLn Handle
stderr (Text -> String
T.unpack Text
msg)
ExitCode -> IO Any
forall a. ExitCode -> IO a
exitWith (ExitCode -> IO Any) -> ExitCode -> IO Any
forall a b. (a -> b) -> a -> b
$ Int -> ExitCode
ExitFailure Int
exitCode
a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return a
forall a. HasCallStack => a
undefined
tshow :: Show a => a -> Text
tshow :: a -> Text
tshow = String -> Text
T.pack (String -> Text) -> (a -> String) -> a -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> String
forall a. Show a => a -> String
show