module Bcc.CLI.TopHandler
  ( toplevelExceptionHandler
  ) where
import           Prelude
import           Control.Exception
import           System.Environment
import           System.Exit
import           System.IO
toplevelExceptionHandler :: IO a -> IO a
toplevelExceptionHandler :: IO a -> IO a
toplevelExceptionHandler IO a
prog = do
    
    
    Handle -> BufferMode -> IO ()
hSetBuffering Handle
stderr BufferMode
LineBuffering
    IO a -> [Handler a] -> IO a
forall a. IO a -> [Handler a] -> IO a
catches IO a
prog [
        (SomeAsyncException -> IO a) -> Handler a
forall a e. Exception e => (e -> IO a) -> Handler a
Handler SomeAsyncException -> IO a
forall a. SomeAsyncException -> IO a
rethrowAsyncExceptions
      , (ExitCode -> IO a) -> Handler a
forall a e. Exception e => (e -> IO a) -> Handler a
Handler ExitCode -> IO a
forall a. ExitCode -> IO a
rethrowExitCode
      , (SomeException -> IO a) -> Handler a
forall a e. Exception e => (e -> IO a) -> Handler a
Handler SomeException -> IO a
forall a. SomeException -> IO a
handleSomeException
      ]
  where
    
    
    rethrowAsyncExceptions :: SomeAsyncException -> IO a
    rethrowAsyncExceptions :: SomeAsyncException -> IO a
rethrowAsyncExceptions = SomeAsyncException -> IO a
forall e a. Exception e => e -> IO a
throwIO
    
    
    rethrowExitCode :: ExitCode -> IO a
    rethrowExitCode :: ExitCode -> IO a
rethrowExitCode = ExitCode -> IO a
forall e a. Exception e => e -> IO a
throwIO
    
    handleSomeException :: SomeException -> IO a
    handleSomeException :: SomeException -> IO a
handleSomeException SomeException
e = do
      Handle -> IO ()
hFlush Handle
stdout
      String
progname <- IO String
getProgName
      Handle -> String -> IO ()
hPutStr Handle
stderr (String -> SomeException -> String
renderSomeException String
progname SomeException
e)
      ExitCode -> IO a
forall e a. Exception e => e -> IO a
throwIO (Int -> ExitCode
ExitFailure Int
1)
    
    
    
    renderSomeException :: String -> SomeException -> String
    renderSomeException :: String -> SomeException -> String
renderSomeException String
progname SomeException
e
      | String
showOutput String -> String -> Bool
forall a. Eq a => a -> a -> Bool
/= String
displayOutput
      = String
showOutput String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\n\n" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
progname String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
": " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
displayOutput
      | Bool
otherwise
      = String
"\n" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
progname String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
": " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
showOutput
      where
        showOutput :: String
showOutput    = SomeException -> String
forall a. Show a => a -> String
show SomeException
e
        displayOutput :: String
displayOutput = SomeException -> String
forall e. Exception e => e -> String
displayException SomeException
e