module Hix.Data.Error where

import Control.Monad.Trans.Except (ExceptT, throwE)
import qualified Data.Text.IO as Text
import Exon (exon)
import Path (Path, toFilePath)
import System.IO (stderr)
import System.IO.Error (tryIOError)

data Error =
  PreprocError Text
  |
  EnvError Text
  |
  GhciError Text
  |
  NewError Text
  |
  BootstrapError Text
  |
  NoMatch Text
  |
  Fatal Text
  deriving stock (Error -> Error -> Bool
(Error -> Error -> Bool) -> (Error -> Error -> Bool) -> Eq Error
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Error -> Error -> Bool
== :: Error -> Error -> Bool
$c/= :: Error -> Error -> Bool
/= :: Error -> Error -> Bool
Eq, Int -> Error -> ShowS
[Error] -> ShowS
Error -> String
(Int -> Error -> ShowS)
-> (Error -> String) -> ([Error] -> ShowS) -> Show Error
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Error -> ShowS
showsPrec :: Int -> Error -> ShowS
$cshow :: Error -> String
show :: Error -> String
$cshowList :: [Error] -> ShowS
showList :: [Error] -> ShowS
Show, (forall x. Error -> Rep Error x)
-> (forall x. Rep Error x -> Error) -> Generic Error
forall x. Rep Error x -> Error
forall x. Error -> Rep Error x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Error -> Rep Error x
from :: forall x. Error -> Rep Error x
$cto :: forall x. Rep Error x -> Error
to :: forall x. Rep Error x -> Error
Generic)

pathText :: Path b t -> Text
pathText :: forall b t. Path b t -> Text
pathText =
  String -> Text
forall a. ToText a => a -> Text
toText (String -> Text) -> (Path b t -> String) -> Path b t -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Path b t -> String
forall b t. Path b t -> String
toFilePath

printPreprocError ::
  MonadIO m =>
  Text ->
  m ()
printPreprocError :: forall (m :: * -> *). MonadIO m => Text -> m ()
printPreprocError Text
msg =
  IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Handle -> Text -> IO ()
Text.hPutStrLn Handle
stderr [exon|>>> Preprocessor generator failed: #{msg}|])

printEnvError ::
  MonadIO m =>
  Text ->
  m ()
printEnvError :: forall (m :: * -> *). MonadIO m => Text -> m ()
printEnvError Text
msg =
  IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Handle -> Text -> IO ()
Text.hPutStrLn Handle
stderr [exon|>>> Invalid env config: #{msg}|])

printGhciError ::
  MonadIO m =>
  Text ->
  m ()
printGhciError :: forall (m :: * -> *). MonadIO m => Text -> m ()
printGhciError Text
msg =
  IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Handle -> Text -> IO ()
Text.hPutStrLn Handle
stderr [exon|>>> Invalid ghci config: #{msg}|])

printNewError ::
  MonadIO m =>
  Text ->
  m ()
printNewError :: forall (m :: * -> *). MonadIO m => Text -> m ()
printNewError Text
msg =
  IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Handle -> Text -> IO ()
Text.hPutStrLn Handle
stderr [exon|>>> Can't create new project: #{msg}|])

printBootstrapError ::
  MonadIO m =>
  Text ->
  m ()
printBootstrapError :: forall (m :: * -> *). MonadIO m => Text -> m ()
printBootstrapError Text
msg =
  IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Handle -> Text -> IO ()
Text.hPutStrLn Handle
stderr [exon|>>> Can't bootstrap project: #{msg}|])

printFatalError ::
  MonadIO m =>
  Text ->
  m ()
printFatalError :: forall (m :: * -> *). MonadIO m => Text -> m ()
printFatalError Text
msg =
  IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Handle -> Text -> IO ()
Text.hPutStrLn Handle
stderr [exon|>>> Fatal error: #{msg}|])

sourceError :: Text -> Path b t -> Text
sourceError :: forall b t. Text -> Path b t -> Text
sourceError Text
reason Path b t
source =
  [exon|#{reason} the source file '#{pathText source}'|]

tryIO ::
  IO a ->
  ExceptT Error IO a
tryIO :: forall a. IO a -> ExceptT Error IO a
tryIO IO a
ma =
  IO (Either IOError a) -> ExceptT Error IO (Either IOError a)
forall a. IO a -> ExceptT Error IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO a -> IO (Either IOError a)
forall a. IO a -> IO (Either IOError a)
tryIOError IO a
ma) ExceptT Error IO (Either IOError a)
-> (Either IOError a -> ExceptT Error IO a) -> ExceptT Error IO a
forall a b.
ExceptT Error IO a
-> (a -> ExceptT Error IO b) -> ExceptT Error IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
    Right a
a -> a -> ExceptT Error IO a
forall a. a -> ExceptT Error IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
a
    Left IOError
err -> Error -> ExceptT Error IO a
forall (m :: * -> *) e a. Monad m => e -> ExceptT e m a
throwE (Text -> Error
Fatal (IOError -> Text
forall b a. (Show a, IsString b) => a -> b
show IOError
err))

note :: Text -> Maybe a -> ExceptT Error IO a
note :: forall a. Text -> Maybe a -> ExceptT Error IO a
note Text
err =
  ExceptT Error IO a
-> (a -> ExceptT Error IO a) -> Maybe a -> ExceptT Error IO a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Error -> ExceptT Error IO a
forall (m :: * -> *) e a. Monad m => e -> ExceptT e m a
throwE (Text -> Error
GhciError Text
err)) a -> ExceptT Error IO a
forall a. a -> ExceptT Error IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure