    {-# LANGUAGE DeriveDataTypeable #-}
    {-# LANGUAGE DeriveGeneric      #-}
    {-# LANGUAGE OverloadedStrings  #-}
    {- |
       Module      : Text.Pandoc.Error
       Copyright   : Copyright (C) 2006-2020 John MacFarlane
       License     : GNU GPL, version 2 or above

       Maintainer  : John MacFarlane <jgm@berkeley.edu>
       Stability   : alpha
       Portability : portable

    This module provides a standard way to deal with possible errors encounted
    during parsing.

    -}
    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

    -- | Handle PandocError by exiting with an error message.
    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 error comes from a chunk or included file,
                         -- then we won't get the right text this way:
                         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 Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> " -- see also /usr/share/doc/pandoc/README.Debian"
        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