From 8381ac3b02e2dd818bc44dc31707efe222ec40c9 Mon Sep 17 00:00:00 2001
From: Matthew Pickering <matthewtpickering@gmail.com>
Date: Wed, 18 Feb 2015 12:55:04 +0000
Subject: [PATCH] Add Text.Pandoc.Error module with PandocError type

---
 pandoc.cabal               |  1 +
 src/Text/Pandoc/Error.hs   | 39 ++++++++++++++++++++++++++++++++++++++
 src/Text/Pandoc/Parsing.hs | 19 ++++++-------------
 3 files changed, 46 insertions(+), 13 deletions(-)
 create mode 100644 src/Text/Pandoc/Error.hs

diff --git a/pandoc.cabal b/pandoc.cabal
index 16106f896..dd31927c7 100644
--- a/pandoc.cabal
+++ b/pandoc.cabal
@@ -289,6 +289,7 @@ Library
                    Text.Pandoc.Pretty,
                    Text.Pandoc.Shared,
                    Text.Pandoc.MediaBag,
+                   Text.Pandoc.Error,
                    Text.Pandoc.Readers.HTML,
                    Text.Pandoc.Readers.LaTeX,
                    Text.Pandoc.Readers.Markdown,
diff --git a/src/Text/Pandoc/Error.hs b/src/Text/Pandoc/Error.hs
new file mode 100644
index 000000000..d4172f7ca
--- /dev/null
+++ b/src/Text/Pandoc/Error.hs
@@ -0,0 +1,39 @@
+module Text.Pandoc.Error (PandocError(..), handleError,hush, mapLeft) where
+
+import Text.Parsec.Error
+import Text.Parsec.Pos hiding (Line)
+import Text.Pandoc.Compat.Except
+
+type Input = String
+
+data PandocError = ParseFailure String
+                 | ParsecError Input ParseError
+                 deriving (Show)
+
+
+instance Error PandocError where
+  strMsg = ParseFailure
+
+
+mapLeft :: (a -> b) -> Either a c -> Either b c
+mapLeft f (Left x) = Left (f x)
+mapLeft _ (Right x) = Right x
+
+hush :: Either a b -> Maybe b
+hush (Left _) = Nothing
+hush (Right x) = Just x
+
+handleError :: Either PandocError a -> a
+handleError (Right r) = r
+handleError (Left err) =
+  case err of
+    ParseFailure string -> error string
+    ParsecError input err' ->
+        let errPos = errorPos err'
+            errLine = sourceLine errPos
+            errColumn = sourceColumn errPos
+            theline = (lines input ++ [""]) !! (errLine - 1)
+        in  error $ "\nError at " ++ show  err' ++ "\n" ++
+                theline ++ "\n" ++ replicate (errColumn - 1) ' ' ++
+                "^"
+
diff --git a/src/Text/Pandoc/Parsing.hs b/src/Text/Pandoc/Parsing.hs
index aebdcae4c..c18aa331f 100644
--- a/src/Text/Pandoc/Parsing.hs
+++ b/src/Text/Pandoc/Parsing.hs
@@ -190,6 +190,8 @@ import Control.Applicative ((<$>), (<*>), (*>), (<*), (<$))
 import Data.Monoid
 import Data.Maybe (catMaybes)
 
+import Text.Pandoc.Error
+
 type Parser t s = Parsec t s
 
 type ParserT = ParsecT
@@ -845,25 +847,16 @@ readWithM :: (Monad m, Functor m)
           => ParserT [Char] st m a       -- ^ parser
           -> st                       -- ^ initial state
           -> String                   -- ^ input
-          -> m a
+          -> m (Either PandocError a)
 readWithM parser state input =
-    handleError <$> (runParserT parser state "source" input)
-    where
-      handleError (Left err') =
-        let errPos = errorPos err'
-            errLine = sourceLine errPos
-            errColumn = sourceColumn errPos
-            theline = (lines input ++ [""]) !! (errLine - 1)
-        in  error $ "\nError at " ++ show  err' ++ "\n" ++
-                theline ++ "\n" ++ replicate (errColumn - 1) ' ' ++
-                "^"
-      handleError (Right result) = result
+    mapLeft (ParsecError input) <$> runParserT parser state "source" input
+
 
 -- | Parse a string with a given parser and state
 readWith :: Parser [Char] st a
          -> st
          -> String
-         -> a
+         -> Either PandocError a
 readWith p t inp = runIdentity $ readWithM p t inp
 
 returnWarnings :: (Stream s m c)