{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
module System.Texrunner.Online
( OnlineTex
, runOnlineTex
, runOnlineTex'
, hbox
, hsize
, showthe
, onlineTexParser
, texPutStrLn
, TexStreams
, getInStream
, getOutStream
, clearUnblocking
) where
import Control.Applicative
import Control.Monad (void)
import Control.Monad.Reader
import qualified Data.Attoparsec.ByteString as A
import Data.ByteString.Char8 (ByteString)
import qualified Data.ByteString.Char8 as C8
import qualified Data.ByteString.Lazy.Char8 as LC8
import Data.List (find)
import Data.Maybe
import Data.Monoid
import qualified Data.Traversable as T
import System.Directory
import System.FilePath
import System.IO
import System.IO.Streams as Streams
import System.IO.Streams.Attoparsec
import System.IO.Temp
import System.Process as P (runInteractiveProcess)
import System.Texrunner.Parse
newtype OnlineTex a = OnlineTex {forall a.
OnlineTex a
-> ReaderT (OutputStream ByteString, InputStream ByteString) IO a
runOnlineTexT :: ReaderT TexStreams IO a}
deriving ((forall a b. (a -> b) -> OnlineTex a -> OnlineTex b)
-> (forall a b. a -> OnlineTex b -> OnlineTex a)
-> Functor OnlineTex
forall a b. a -> OnlineTex b -> OnlineTex a
forall a b. (a -> b) -> OnlineTex a -> OnlineTex b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall a b. (a -> b) -> OnlineTex a -> OnlineTex b
fmap :: forall a b. (a -> b) -> OnlineTex a -> OnlineTex b
$c<$ :: forall a b. a -> OnlineTex b -> OnlineTex a
<$ :: forall a b. a -> OnlineTex b -> OnlineTex a
Functor, Functor OnlineTex
Functor OnlineTex =>
(forall a. a -> OnlineTex a)
-> (forall a b. OnlineTex (a -> b) -> OnlineTex a -> OnlineTex b)
-> (forall a b c.
(a -> b -> c) -> OnlineTex a -> OnlineTex b -> OnlineTex c)
-> (forall a b. OnlineTex a -> OnlineTex b -> OnlineTex b)
-> (forall a b. OnlineTex a -> OnlineTex b -> OnlineTex a)
-> Applicative OnlineTex
forall a. a -> OnlineTex a
forall a b. OnlineTex a -> OnlineTex b -> OnlineTex a
forall a b. OnlineTex a -> OnlineTex b -> OnlineTex b
forall a b. OnlineTex (a -> b) -> OnlineTex a -> OnlineTex b
forall a b c.
(a -> b -> c) -> OnlineTex a -> OnlineTex b -> OnlineTex c
forall (f :: * -> *).
Functor f =>
(forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
$cpure :: forall a. a -> OnlineTex a
pure :: forall a. a -> OnlineTex a
$c<*> :: forall a b. OnlineTex (a -> b) -> OnlineTex a -> OnlineTex b
<*> :: forall a b. OnlineTex (a -> b) -> OnlineTex a -> OnlineTex b
$cliftA2 :: forall a b c.
(a -> b -> c) -> OnlineTex a -> OnlineTex b -> OnlineTex c
liftA2 :: forall a b c.
(a -> b -> c) -> OnlineTex a -> OnlineTex b -> OnlineTex c
$c*> :: forall a b. OnlineTex a -> OnlineTex b -> OnlineTex b
*> :: forall a b. OnlineTex a -> OnlineTex b -> OnlineTex b
$c<* :: forall a b. OnlineTex a -> OnlineTex b -> OnlineTex a
<* :: forall a b. OnlineTex a -> OnlineTex b -> OnlineTex a
Applicative, Applicative OnlineTex
Applicative OnlineTex =>
(forall a b. OnlineTex a -> (a -> OnlineTex b) -> OnlineTex b)
-> (forall a b. OnlineTex a -> OnlineTex b -> OnlineTex b)
-> (forall a. a -> OnlineTex a)
-> Monad OnlineTex
forall a. a -> OnlineTex a
forall a b. OnlineTex a -> OnlineTex b -> OnlineTex b
forall a b. OnlineTex a -> (a -> OnlineTex b) -> OnlineTex b
forall (m :: * -> *).
Applicative m =>
(forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
$c>>= :: forall a b. OnlineTex a -> (a -> OnlineTex b) -> OnlineTex b
>>= :: forall a b. OnlineTex a -> (a -> OnlineTex b) -> OnlineTex b
$c>> :: forall a b. OnlineTex a -> OnlineTex b -> OnlineTex b
>> :: forall a b. OnlineTex a -> OnlineTex b -> OnlineTex b
$creturn :: forall a. a -> OnlineTex a
return :: forall a. a -> OnlineTex a
Monad, Monad OnlineTex
Monad OnlineTex =>
(forall a. IO a -> OnlineTex a) -> MonadIO OnlineTex
forall a. IO a -> OnlineTex a
forall (m :: * -> *).
Monad m =>
(forall a. IO a -> m a) -> MonadIO m
$cliftIO :: forall a. IO a -> OnlineTex a
liftIO :: forall a. IO a -> OnlineTex a
MonadIO, MonadReader TexStreams)
runOnlineTex :: String
-> [String]
-> ByteString
-> OnlineTex a
-> IO a
runOnlineTex :: forall a. String -> [String] -> ByteString -> OnlineTex a -> IO a
runOnlineTex String
command [String]
args ByteString
preamble OnlineTex a
process =
(\(a
a,TexLog
_,Maybe ByteString
_) -> a
a) ((a, TexLog, Maybe ByteString) -> a)
-> IO (a, TexLog, Maybe ByteString) -> IO a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String
-> [String]
-> ByteString
-> OnlineTex a
-> IO (a, TexLog, Maybe ByteString)
forall a.
String
-> [String]
-> ByteString
-> OnlineTex a
-> IO (a, TexLog, Maybe ByteString)
runOnlineTex' String
command [String]
args ByteString
preamble OnlineTex a
process
runOnlineTex' :: String
-> [String]
-> ByteString
-> OnlineTex a
-> IO (a, TexLog, Maybe LC8.ByteString)
runOnlineTex' :: forall a.
String
-> [String]
-> ByteString
-> OnlineTex a
-> IO (a, TexLog, Maybe ByteString)
runOnlineTex' String
command [String]
args ByteString
preamble OnlineTex a
process =
String
-> (String -> IO (a, TexLog, Maybe ByteString))
-> IO (a, TexLog, Maybe ByteString)
forall (m :: * -> *) a.
(MonadIO m, MonadMask m) =>
String -> (String -> m a) -> m a
withSystemTempDirectory String
"onlinetex." ((String -> IO (a, TexLog, Maybe ByteString))
-> IO (a, TexLog, Maybe ByteString))
-> (String -> IO (a, TexLog, Maybe ByteString))
-> IO (a, TexLog, Maybe ByteString)
forall a b. (a -> b) -> a -> b
$ \String
path -> do
(OutputStream ByteString
outS, InputStream ByteString
inS, ProcessHandle
h) <- String
-> Maybe [(String, String)]
-> String
-> [String]
-> ByteString
-> IO
(OutputStream ByteString, InputStream ByteString, ProcessHandle)
mkTexHandles String
path Maybe [(String, String)]
forall a. Maybe a
Nothing String
command [String]
args ByteString
preamble
a
a <- (ReaderT (OutputStream ByteString, InputStream ByteString) IO a
-> (OutputStream ByteString, InputStream ByteString) -> IO a)
-> (OutputStream ByteString, InputStream ByteString)
-> ReaderT (OutputStream ByteString, InputStream ByteString) IO a
-> IO a
forall a b c. (a -> b -> c) -> b -> a -> c
flip ReaderT (OutputStream ByteString, InputStream ByteString) IO a
-> (OutputStream ByteString, InputStream ByteString) -> IO a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (OutputStream ByteString
outS, InputStream ByteString
inS) (ReaderT (OutputStream ByteString, InputStream ByteString) IO a
-> IO a)
-> (OnlineTex a
-> ReaderT (OutputStream ByteString, InputStream ByteString) IO a)
-> OnlineTex a
-> IO a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OnlineTex a
-> ReaderT (OutputStream ByteString, InputStream ByteString) IO a
forall a.
OnlineTex a
-> ReaderT (OutputStream ByteString, InputStream ByteString) IO a
runOnlineTexT (OnlineTex a -> IO a) -> OnlineTex a -> IO a
forall a b. (a -> b) -> a -> b
$ OnlineTex a
process
Maybe ByteString -> OutputStream ByteString -> IO ()
forall a. Maybe a -> OutputStream a -> IO ()
write Maybe ByteString
forall a. Maybe a
Nothing OutputStream ByteString
outS
ExitCode
_ <- ProcessHandle -> IO ExitCode
waitForProcess ProcessHandle
h
Maybe String
pdfPath <- (String -> Bool) -> [String] -> Maybe String
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find ((String -> String -> Bool
forall a. Eq a => a -> a -> Bool
==String
".pdf") (String -> Bool) -> (String -> String) -> String -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
takeExtension) ([String] -> Maybe String) -> IO [String] -> IO (Maybe String)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IO [String]
getDirectoryContents String
path
Maybe ByteString
pdfFile <- (String -> IO ByteString) -> Maybe String -> IO (Maybe ByteString)
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> Maybe a -> m (Maybe b)
T.mapM (String -> IO ByteString
LC8.readFile (String -> IO ByteString)
-> (String -> String) -> String -> IO ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
path String -> String -> String
</>)) Maybe String
pdfPath
Maybe String
logPath <- (String -> Bool) -> [String] -> Maybe String
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find ((String -> String -> Bool
forall a. Eq a => a -> a -> Bool
==String
".log") (String -> Bool) -> (String -> String) -> String -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
takeExtension) ([String] -> Maybe String) -> IO [String] -> IO (Maybe String)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IO [String]
getDirectoryContents String
path
Maybe ByteString
logFile <- (String -> IO ByteString) -> Maybe String -> IO (Maybe ByteString)
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> Maybe a -> m (Maybe b)
T.mapM (String -> IO ByteString
C8.readFile (String -> IO ByteString)
-> (String -> String) -> String -> IO ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
path String -> String -> String
</>)) Maybe String
logPath
(a, TexLog, Maybe ByteString) -> IO (a, TexLog, Maybe ByteString)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (a
a, ByteString -> TexLog
parseLog (ByteString -> TexLog) -> ByteString -> TexLog
forall a b. (a -> b) -> a -> b
$ ByteString -> Maybe ByteString -> ByteString
forall a. a -> Maybe a -> a
fromMaybe ByteString
"" Maybe ByteString
logFile, Maybe ByteString
pdfFile)
hbox :: Fractional n => ByteString -> OnlineTex (Box n)
hbox :: forall n. Fractional n => ByteString -> OnlineTex (Box n)
hbox ByteString
str = do
OnlineTex ()
clearUnblocking
ByteString -> OnlineTex ()
texPutStrLn (ByteString -> OnlineTex ()) -> ByteString -> OnlineTex ()
forall a b. (a -> b) -> a -> b
$ ByteString
"\\setbox0=\\hbox{" ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
str ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
"}\n\\showbox0\n"
Parser (Box n) -> OnlineTex (Box n)
forall a. Parser a -> OnlineTex a
onlineTexParser Parser (Box n)
forall n. Fractional n => Parser (Box n)
parseBox
showthe :: Fractional n => ByteString -> OnlineTex n
showthe :: forall n. Fractional n => ByteString -> OnlineTex n
showthe ByteString
str = do
OnlineTex ()
clearUnblocking
ByteString -> OnlineTex ()
texPutStrLn (ByteString -> OnlineTex ()) -> ByteString -> OnlineTex ()
forall a b. (a -> b) -> a -> b
$ ByteString
"\\showthe" ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
str
Parser n -> OnlineTex n
forall a. Parser a -> OnlineTex a
onlineTexParser Parser n
forall n. Fractional n => Parser n
parseUnit
hsize :: Fractional n => OnlineTex n
hsize :: forall n. Fractional n => OnlineTex n
hsize = Box n -> n
forall n. Box n -> n
boxWidth (Box n -> n) -> OnlineTex (Box n) -> OnlineTex n
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ByteString -> OnlineTex (Box n)
forall n. Fractional n => ByteString -> OnlineTex (Box n)
hbox ByteString
"\\line{\\hfill}"
onlineTexParser :: A.Parser a -> OnlineTex a
onlineTexParser :: forall a. Parser a -> OnlineTex a
onlineTexParser Parser a
p = OnlineTex (InputStream ByteString)
getInStream OnlineTex (InputStream ByteString)
-> (InputStream ByteString -> OnlineTex a) -> OnlineTex a
forall a b. OnlineTex a -> (a -> OnlineTex b) -> OnlineTex b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= IO a -> OnlineTex a
forall a. IO a -> OnlineTex a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO a -> OnlineTex a)
-> (InputStream ByteString -> IO a)
-> InputStream ByteString
-> OnlineTex a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Parser a -> InputStream ByteString -> IO a
forall r. Parser r -> InputStream ByteString -> IO r
parseFromStream Parser a
p
texPutStrLn :: ByteString -> OnlineTex ()
texPutStrLn :: ByteString -> OnlineTex ()
texPutStrLn ByteString
a = OnlineTex (OutputStream ByteString)
getOutStream OnlineTex (OutputStream ByteString)
-> (OutputStream ByteString -> OnlineTex ()) -> OnlineTex ()
forall a b. OnlineTex a -> (a -> OnlineTex b) -> OnlineTex b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= IO () -> OnlineTex ()
forall a. IO a -> OnlineTex a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> OnlineTex ())
-> (OutputStream ByteString -> IO ())
-> OutputStream ByteString
-> OnlineTex ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe ByteString -> OutputStream ByteString -> IO ()
forall a. Maybe a -> OutputStream a -> IO ()
write (ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just (ByteString -> Maybe ByteString) -> ByteString -> Maybe ByteString
forall a b. (a -> b) -> a -> b
$ ByteString -> ByteString -> ByteString
C8.append ByteString
a ByteString
"\n")
type TexStreams = (OutputStream ByteString, InputStream ByteString)
getOutStream :: OnlineTex (OutputStream ByteString)
getOutStream :: OnlineTex (OutputStream ByteString)
getOutStream = ((OutputStream ByteString, InputStream ByteString)
-> OutputStream ByteString)
-> OnlineTex (OutputStream ByteString)
forall a.
((OutputStream ByteString, InputStream ByteString) -> a)
-> OnlineTex a
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
reader (OutputStream ByteString, InputStream ByteString)
-> OutputStream ByteString
forall a b. (a, b) -> a
fst
getInStream :: OnlineTex (InputStream ByteString)
getInStream :: OnlineTex (InputStream ByteString)
getInStream = ((OutputStream ByteString, InputStream ByteString)
-> InputStream ByteString)
-> OnlineTex (InputStream ByteString)
forall a.
((OutputStream ByteString, InputStream ByteString) -> a)
-> OnlineTex a
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
reader (OutputStream ByteString, InputStream ByteString)
-> InputStream ByteString
forall a b. (a, b) -> b
snd
clearUnblocking :: OnlineTex ()
clearUnblocking :: OnlineTex ()
clearUnblocking = OnlineTex (InputStream ByteString)
getInStream OnlineTex (InputStream ByteString)
-> (InputStream ByteString -> OnlineTex ()) -> OnlineTex ()
forall a b. OnlineTex a -> (a -> OnlineTex b) -> OnlineTex b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= OnlineTex (Maybe ByteString) -> OnlineTex ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (OnlineTex (Maybe ByteString) -> OnlineTex ())
-> (InputStream ByteString -> OnlineTex (Maybe ByteString))
-> InputStream ByteString
-> OnlineTex ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO (Maybe ByteString) -> OnlineTex (Maybe ByteString)
forall a. IO a -> OnlineTex a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Maybe ByteString) -> OnlineTex (Maybe ByteString))
-> (InputStream ByteString -> IO (Maybe ByteString))
-> InputStream ByteString
-> OnlineTex (Maybe ByteString)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. InputStream ByteString -> IO (Maybe ByteString)
forall a. InputStream a -> IO (Maybe a)
Streams.read
mkTexHandles :: FilePath
-> Maybe [(String, String)]
-> String
-> [String]
-> ByteString
-> IO (OutputStream ByteString,
InputStream ByteString,
ProcessHandle)
mkTexHandles :: String
-> Maybe [(String, String)]
-> String
-> [String]
-> ByteString
-> IO
(OutputStream ByteString, InputStream ByteString, ProcessHandle)
mkTexHandles String
dir Maybe [(String, String)]
env String
command [String]
args ByteString
preamble = do
(OutputStream ByteString
outStream, InputStream ByteString
inStream, InputStream ByteString
_, ProcessHandle
h) <- String
-> [String]
-> Maybe String
-> Maybe [(String, String)]
-> IO
(OutputStream ByteString, InputStream ByteString,
InputStream ByteString, ProcessHandle)
runInteractiveProcess'
String
command
[String]
args
(String -> Maybe String
forall a. a -> Maybe a
Just String
dir)
Maybe [(String, String)]
env
Maybe ByteString -> OutputStream ByteString -> IO ()
forall a. Maybe a -> OutputStream a -> IO ()
write (ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just (ByteString -> Maybe ByteString) -> ByteString -> Maybe ByteString
forall a b. (a -> b) -> a -> b
$ ByteString
"\\tracingonline=1"
ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
"\\showboxdepth=1"
ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
"\\showboxbreadth=1"
ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
"\\scrollmode\n"
) OutputStream ByteString
outStream
Maybe ByteString -> OutputStream ByteString -> IO ()
forall a. Maybe a -> OutputStream a -> IO ()
write (ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just ByteString
preamble) OutputStream ByteString
outStream
(OutputStream ByteString, InputStream ByteString, ProcessHandle)
-> IO
(OutputStream ByteString, InputStream ByteString, ProcessHandle)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (OutputStream ByteString
outStream, InputStream ByteString
inStream, ProcessHandle
h)
runInteractiveProcess'
:: FilePath
-> [String]
-> Maybe FilePath
-> Maybe [(String,String)]
-> IO (OutputStream ByteString,
InputStream ByteString,
InputStream ByteString,
ProcessHandle)
runInteractiveProcess' :: String
-> [String]
-> Maybe String
-> Maybe [(String, String)]
-> IO
(OutputStream ByteString, InputStream ByteString,
InputStream ByteString, ProcessHandle)
runInteractiveProcess' String
cmd [String]
args Maybe String
wd Maybe [(String, String)]
env = do
(Handle
hin, Handle
hout, Handle
herr, ProcessHandle
ph) <- String
-> [String]
-> Maybe String
-> Maybe [(String, String)]
-> IO (Handle, Handle, Handle, ProcessHandle)
P.runInteractiveProcess String
cmd [String]
args Maybe String
wd Maybe [(String, String)]
env
Handle -> BufferMode -> IO ()
hSetBuffering Handle
hin BufferMode
LineBuffering
OutputStream ByteString
sIn <- Handle -> IO (OutputStream ByteString)
Streams.handleToOutputStream Handle
hin IO (OutputStream ByteString)
-> (OutputStream ByteString -> IO (OutputStream ByteString))
-> IO (OutputStream ByteString)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=
IO () -> OutputStream ByteString -> IO (OutputStream ByteString)
forall b a. IO b -> OutputStream a -> IO (OutputStream a)
Streams.atEndOfOutput (Handle -> IO ()
hClose Handle
hin) IO (OutputStream ByteString)
-> (OutputStream ByteString -> IO (OutputStream ByteString))
-> IO (OutputStream ByteString)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=
OutputStream ByteString -> IO (OutputStream ByteString)
forall a. OutputStream a -> IO (OutputStream a)
Streams.lockingOutputStream
InputStream ByteString
sOut <- Handle -> IO (InputStream ByteString)
Streams.handleToInputStream Handle
hout IO (InputStream ByteString)
-> (InputStream ByteString -> IO (InputStream ByteString))
-> IO (InputStream ByteString)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=
IO () -> InputStream ByteString -> IO (InputStream ByteString)
forall b a. IO b -> InputStream a -> IO (InputStream a)
Streams.atEndOfInput (Handle -> IO ()
hClose Handle
hout) IO (InputStream ByteString)
-> (InputStream ByteString -> IO (InputStream ByteString))
-> IO (InputStream ByteString)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=
InputStream ByteString -> IO (InputStream ByteString)
forall a. InputStream a -> IO (InputStream a)
Streams.lockingInputStream
InputStream ByteString
sErr <- Handle -> IO (InputStream ByteString)
Streams.handleToInputStream Handle
herr IO (InputStream ByteString)
-> (InputStream ByteString -> IO (InputStream ByteString))
-> IO (InputStream ByteString)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=
IO () -> InputStream ByteString -> IO (InputStream ByteString)
forall b a. IO b -> InputStream a -> IO (InputStream a)
Streams.atEndOfInput (Handle -> IO ()
hClose Handle
herr) IO (InputStream ByteString)
-> (InputStream ByteString -> IO (InputStream ByteString))
-> IO (InputStream ByteString)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=
InputStream ByteString -> IO (InputStream ByteString)
forall a. InputStream a -> IO (InputStream a)
Streams.lockingInputStream
(OutputStream ByteString, InputStream ByteString,
InputStream ByteString, ProcessHandle)
-> IO
(OutputStream ByteString, InputStream ByteString,
InputStream ByteString, ProcessHandle)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (OutputStream ByteString
sIn, InputStream ByteString
sOut, InputStream ByteString
sErr, ProcessHandle
ph)