module Ecluse.Runtime.Server.Halt (
InteractiveHalt (..),
defaultInteractiveHalt,
withInteractiveHalt,
) where
import System.Exit (ExitCode (ExitFailure))
import System.IO (hIsTerminalDevice, isEOF)
import System.Posix.Process (exitImmediately)
import UnliftIO.Async (withAsync)
data InteractiveHalt = InteractiveHalt
{ InteractiveHalt -> IO Bool
haltOnInteractive :: IO Bool
, InteractiveHalt -> IO ()
awaitHaltSignal :: IO ()
, InteractiveHalt -> IO ()
halt :: IO ()
}
defaultInteractiveHalt :: InteractiveHalt
defaultInteractiveHalt :: InteractiveHalt
defaultInteractiveHalt =
InteractiveHalt
{ haltOnInteractive :: IO Bool
haltOnInteractive = Handle -> IO Bool
hIsTerminalDevice Handle
stdin
, awaitHaltSignal :: IO ()
awaitHaltSignal = IO ()
awaitStdinEof
, halt :: IO ()
halt = ExitCode -> IO ()
forall a. ExitCode -> IO a
exitImmediately (Int -> ExitCode
ExitFailure Int
130)
}
awaitStdinEof :: IO ()
awaitStdinEof :: IO ()
awaitStdinEof =
IO Bool
isEOF IO Bool -> (Bool -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Bool
True -> IO ()
forall (f :: * -> *). Applicative f => f ()
pass
Bool
False -> IO Text -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void IO Text
forall (m :: * -> *). MonadIO m => m Text
getLine IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> IO ()
awaitStdinEof
withInteractiveHalt :: InteractiveHalt -> IO a -> IO a
withInteractiveHalt :: forall a. InteractiveHalt -> IO a -> IO a
withInteractiveHalt InteractiveHalt
ih IO a
action =
InteractiveHalt -> IO Bool
haltOnInteractive InteractiveHalt
ih IO Bool -> (Bool -> IO a) -> IO a
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Bool
False -> IO a
action
Bool
True -> IO () -> (Async () -> IO a) -> IO a
forall (m :: * -> *) a b.
MonadUnliftIO m =>
m a -> (Async a -> m b) -> m b
withAsync (InteractiveHalt -> IO ()
awaitHaltSignal InteractiveHalt
ih IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> InteractiveHalt -> IO ()
halt InteractiveHalt
ih) (IO a -> Async () -> IO a
forall a b. a -> b -> a
const IO a
action)