-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Use OS processes as stream transformation functions -- -- Run operating system processes as stream source, sink or -- transformation functions. Use them seamlessly in a streaming data -- pipeline in the same way as any other Haskell functions. @package streamly-process @version 0.2.0 module Streamly.Internal.System.Process -- | Process configuration used for creating a new process. -- -- By default the process config is setup to inherit the following -- attributes from the parent process: -- --
-- >>> toBytes path args = processBytes path args Stream.nil ---- -- The following code is equivalent to the shell command echo "hello -- world": -- --
-- >>> :{
-- Process.toBytes "echo" ["hello world"]
-- & Stream.fold Stdio.write
-- :}
-- hello world
--
toBytes :: (IsStream t, MonadAsync m, MonadCatch m) => FilePath -> [String] -> t m Word8
-- | toBytes' path args runs the executable at path using
-- args as arguments and returns a stream of Either
-- bytes. The Left values are from stderr and the
-- Right values are from stdout of the executable.
--
-- Raises ProcessFailure exception in case of failure.
--
-- The following example uses echo to write hello to
-- stdout and world to stderr, then uses folds
-- from Streamly.Console.Stdio to write them back to
-- stdout and stderr respectively:
--
--
-- >>> :{
-- Process.toBytes' "/bin/bash" ["-c", "echo 'hello'; echo 'world' 1>&2"]
-- & Stream.fold (Fold.partition Stdio.writeErr Stdio.write)
-- :}
-- world
-- hello
-- ((),())
--
--
-- -- >>> toBytes' path args = Process.processBytes' path args Stream.nil --toBytes' :: (IsStream t, MonadAsync m, MonadCatch m) => FilePath -> [String] -> t m (Either Word8 Word8) -- | See processChunks. toChunks is defined as: -- --
-- >>> toChunks path args = processChunks path args Stream.nil ---- -- The following code is equivalent to the shell command echo "hello -- world": -- --
-- >>> :{
-- Process.toChunks "echo" ["hello world"]
-- & Stream.fold Stdio.writeChunks
-- :}
-- hello world
--
toChunks :: (IsStream t, MonadAsync m, MonadCatch m) => FilePath -> [String] -> t m (Array Word8)
-- | Like toBytes but generates a stream of Array Word8
-- instead of a stream of Word8.
--
--
-- >>> :{
-- toChunks' "bash" ["-c", "echo 'hello'; echo 'world' 1>&2"]
-- & Stream.fold (Fold.partition Stdio.writeErrChunks Stdio.writeChunks)
-- :}
-- world
-- hello
-- ((),())
--
--
-- -- >>> toChunks' path args = processChunks' path args Stream.nil ---- -- Prefer toChunks over toBytes when performance matters. toChunks' :: (IsStream t, MonadAsync m, MonadCatch m) => FilePath -> [String] -> t m (Either (Array Word8) (Array Word8)) -- | Like processChunks except that it works on a stream of bytes -- instead of a stream of chunks. -- -- We can write the example in processChunks as follows. Notice -- how seamlessly we can replace the tr process with the Haskell -- toUpper function: -- --
-- >>> :{
-- Process.toBytes "echo" ["hello world"]
-- & Unicode.decodeLatin1 & Stream.map toUpper & Unicode.encodeLatin1
-- & Stream.fold Stdio.write
-- :}
-- HELLO WORLD
--
processBytes :: (IsStream t, MonadCatch m, MonadAsync m) => FilePath -> [String] -> t m Word8 -> t m Word8
-- | processBytes' path args input runs the executable at
-- path using args as arguments and input
-- stream as its standard input. The error stream of the executable is
-- presented as Left values in the resulting stream and output
-- stream as Right values.
--
-- Raises ProcessFailure exception in case of failure.
--
-- For example, the following is equivalent to the shell command echo
-- "hello world" | tr [:lower:] [:upper:]:
--
--
-- >>> :{
-- processBytes' "echo" ["hello world"] Stream.nil
-- & Stream.rights
-- & processBytes' "tr" ["[:lower:]", "[:upper:]"]
-- & Stream.rights
-- & Stream.fold Stdio.write
-- :}
-- HELLO WORLD
--
processBytes' :: (IsStream t, MonadCatch m, MonadAsync m) => FilePath -> [String] -> t m Word8 -> t m (Either Word8 Word8)
processChunksWith :: (IsStream t, MonadCatch m, MonadAsync m) => (Config -> Config) -> FilePath -> [String] -> t m (Array Word8) -> t m (Array Word8)
-- | processChunks file args input runs the executable
-- file specified by its name or path using args as
-- arguments and input stream as its standard input. Returns the
-- standard output of the executable as a stream.
--
-- If only the name of an executable file is specified instead of its
-- path then the file name is searched in the directories specified by
-- the PATH environment variable.
--
-- If the input stream throws an exception or if the output stream is
-- garbage collected before it could finish then the process is
-- terminated with SIGTERM.
--
-- If the process terminates with a non-zero exit code then a
-- ProcessFailure exception is raised.
--
-- The following code is equivalent to the shell command echo "hello
-- world" | tr [a-z] [A-Z]:
--
--
-- >>> :{
-- Process.toChunks "echo" ["hello world"]
-- & Process.processChunks "tr" ["[a-z]", "[A-Z]"]
-- & Stream.fold Stdio.writeChunks
-- :}
-- HELLO WORLD
--
processChunks :: (IsStream t, MonadCatch m, MonadAsync m) => FilePath -> [String] -> t m (Array Word8) -> t m (Array Word8)
processChunks'With :: (IsStream t, MonadCatch m, MonadAsync m) => (Config -> Config) -> FilePath -> [String] -> t m (Array Word8) -> t m (Either (Array Word8) (Array Word8))
processChunks' :: (IsStream t, MonadCatch m, MonadAsync m) => FilePath -> [String] -> t m (Array Word8) -> t m (Either (Array Word8) (Array Word8))
instance GHC.Show.Show Streamly.Internal.System.Process.ProcessFailure
instance GHC.Exception.Type.Exception Streamly.Internal.System.Process.ProcessFailure
module Streamly.Internal.System.Process.Posix
-- | Thread safe, mutable process handle. Process status is stored in the
-- handle and is modified by the process inspection operations.
data Process
-- | Creates a new process, executes the specified action in the cloned
-- process and then performs an exec system call using the
-- provided path, arguments and environment. The PATH is searched for the
-- specified binary when the specified path is not absolute?
newProcess :: IO () -> FilePath -> [String] -> Maybe [(String, String)] -> IO Process
-- | Wait until the process exits by itself or gets terminated due to a
-- signal. Returns the ProcessStatus which includes the
-- termination reason or exit code.
--
-- Thread safe.
wait :: Process -> IO ProcessStatus
-- | Get the current status of a process. A Nothing value means the
-- process is still running, a Just value means the process is
-- terminated and provides the status of the process.
--
-- Thread safe.
getStatus :: Process -> IO (Maybe ProcessStatus)
-- | return (parent, child, (parentAction, childAction, failureAction))
mkPipe :: Direction -> IO (Fd, Fd, (IO (), IO (), IO ()))
mkStdioPipes :: Bool -> IO ((Handle, Handle, Maybe Handle, Handle, Handle), IO (), IO (), IO ())
instance GHC.Classes.Eq Streamly.Internal.System.Process.Posix.Direction
instance GHC.Show.Show Streamly.Internal.System.Process.Posix.Direction
instance GHC.Show.Show Streamly.Internal.System.Process.Posix.ProcessDoesNotExist
instance GHC.Exception.Type.Exception Streamly.Internal.System.Process.Posix.ProcessDoesNotExist
-- | Use OS processes as stream transformation functions.
--
-- This module provides functions to run operating system processes as
-- stream source, sink or transformation functions. Thus OS processes can
-- be used in the same way as Haskell functions and all the streaming
-- combinators in streamly can be used to combine them. This allows you
-- to seamlessly integrate external programs into your Haskell program.
--
-- We recommend that you use Streamly threads instead of system processes
-- where possible as they have a simpler programming model and processes
-- have a larger performance overhead.
--
-- -- >>> :set -XFlexibleContexts -- -- >>> :set -XScopedTypeVariables -- -- >>> import Data.Char (toUpper) -- -- >>> import Data.Function ((&)) -- -- >>> import qualified Streamly.Console.Stdio as Stdio -- -- >>> import qualified Streamly.Data.Array.Foreign as Array -- -- >>> import qualified Streamly.Data.Fold as Fold -- -- >>> import qualified Streamly.Prelude as Stream -- -- >>> import qualified Streamly.System.Process as Process -- -- >>> import qualified Streamly.Unicode.Stream as Unicode -- -- >>> import qualified Streamly.Internal.FileSystem.Dir as Dir -- -- >>> import qualified Streamly.Internal.Data.Stream.IsStream as Stream ---- --
-- >>> :{
-- Process.toBytes "echo" ["hello world"]
-- & Process.processBytes "tr" ["[a-z]", "[A-Z]"]
-- & Stream.fold Stdio.write
-- :}
-- HELLO WORLD
--
--
-- Of course, you can use a Haskell function instead of "tr":
--
--
-- >>> :{
-- Process.toBytes "echo" ["hello world"]
-- & Unicode.decodeLatin1 & Stream.map toUpper & Unicode.encodeLatin1
-- & Stream.fold Stdio.write
-- :}
-- HELLO WORLD
--
--
--
-- >>> :{
-- Process.toBytes "sh" ["-c", "echo hello | tr [a-z] [A-Z]"]
-- & Stream.fold Stdio.write
-- :}
-- HELLO
--
--
--
-- >>> :{
-- grep file =
-- Process.toBytes "grep" ["-H", "to", file]
-- & Stream.handle (\(_ :: Process.ProcessFailure) -> Stream.nil)
-- & Stream.splitWithSuffix (== 10) Array.write
-- :}
--
--
--
-- >>> :{
-- pgrep =
-- Dir.toFiles "."
-- & Stream.concatMapWith Stream.async grep
-- & Stream.fold Stdio.writeChunks
-- :}
--
--
-- -- >>> toChunks path args = processChunks path args Stream.nil ---- -- The following code is equivalent to the shell command echo "hello -- world": -- --
-- >>> :{
-- Process.toChunks "echo" ["hello world"]
-- & Stream.fold Stdio.writeChunks
-- :}
-- hello world
--
toChunks :: (IsStream t, MonadAsync m, MonadCatch m) => FilePath -> [String] -> t m (Array Word8)
-- | See processBytes. toBytes is defined as:
--
-- -- >>> toBytes path args = processBytes path args Stream.nil ---- -- The following code is equivalent to the shell command echo "hello -- world": -- --
-- >>> :{
-- Process.toBytes "echo" ["hello world"]
-- & Stream.fold Stdio.write
-- :}
-- hello world
--
toBytes :: (IsStream t, MonadAsync m, MonadCatch m) => FilePath -> [String] -> t m Word8
-- | processChunks file args input runs the executable
-- file specified by its name or path using args as
-- arguments and input stream as its standard input. Returns the
-- standard output of the executable as a stream.
--
-- If only the name of an executable file is specified instead of its
-- path then the file name is searched in the directories specified by
-- the PATH environment variable.
--
-- If the input stream throws an exception or if the output stream is
-- garbage collected before it could finish then the process is
-- terminated with SIGTERM.
--
-- If the process terminates with a non-zero exit code then a
-- ProcessFailure exception is raised.
--
-- The following code is equivalent to the shell command echo "hello
-- world" | tr [a-z] [A-Z]:
--
--
-- >>> :{
-- Process.toChunks "echo" ["hello world"]
-- & Process.processChunks "tr" ["[a-z]", "[A-Z]"]
-- & Stream.fold Stdio.writeChunks
-- :}
-- HELLO WORLD
--
processChunks :: (IsStream t, MonadCatch m, MonadAsync m) => FilePath -> [String] -> t m (Array Word8) -> t m (Array Word8)
-- | Like processChunks except that it works on a stream of bytes
-- instead of a stream of chunks.
--
-- We can write the example in processChunks as follows. Notice
-- how seamlessly we can replace the tr process with the Haskell
-- toUpper function:
--
--
-- >>> :{
-- Process.toBytes "echo" ["hello world"]
-- & Unicode.decodeLatin1 & Stream.map toUpper & Unicode.encodeLatin1
-- & Stream.fold Stdio.write
-- :}
-- HELLO WORLD
--
processBytes :: (IsStream t, MonadCatch m, MonadAsync m) => FilePath -> [String] -> t m Word8 -> t m Word8