{-# LANGUAGE CPP #-} -- | -- Module : Streamly.System.Process -- Copyright : (c) 2020 Composewell Technologies -- License : Apache-2.0 -- Maintainer : streamly@composewell.com -- Stability : experimental -- Portability : GHC -- -- This module provides functions to run operating system processes as stream -- producers, consumers or stream 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 binary executables into your Haskell program. -- -- However, we recommend native Haskell functions with Streamly threads over -- using system processes whenever possible. This approach offers a simpler -- programming model compared to system processes, which also have a larger -- performance overhead. -- -- Prefer "Streamly.System.Command" module as a higher level wrapper over this -- module. -- -- = Executables as functions -- -- Processes can be composed in a streaming pipeline just like a Posix shell -- command pipeline. Moreover, we can mix processes and Haskell functions -- seamlessly in a processing pipeline. For example: -- -- >>> :{ -- Process.toBytes "echo" ["hello world"] -- & Process.pipeBytes "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 & fmap toUpper & Unicode.encodeLatin1 -- & Stream.fold Stdio.write -- :} -- HELLO WORLD -- -- = Shell commands as functions -- -- Using a shell as the command interpreter we can use shell commands in a data -- processing pipeline: -- -- >>> :{ -- Process.toBytes "sh" ["-c", "echo hello | tr [a-z] [A-Z]"] -- & Stream.fold Stdio.write -- :} -- HELLO -- -- = Running Commands Concurrently -- -- We can run executables or commands concurrently as we would run any other -- functions in Streamly. For example, the following program greps the word -- "to" in all the files in the current directory concurrently: -- -- >>> :{ -- grep file = -- Process.toBytes "grep" ["-H", "pattern", file] -- & Stream.handle (\(_ :: Process.ProcessFailure) -> Stream.nil) -- & Stream.foldMany (Fold.takeEndBy (== 10) Array.write) -- :} -- -- >>> :{ -- pgrep = -- Dir.readFiles "." -- & Stream.parConcatMap id grep -- & Stream.fold Stdio.writeChunks -- :} -- -- = Experimental APIs -- -- See "Streamly.Internal.System.Process" for unreleased functions. -- module Streamly.System.Process ( -- * Setup -- | To execute the code examples provided in this module in ghci, please -- run the following commands first. -- -- $setup -- * Exceptions -- | Since we are composing using Streamly's streaming pipeline there is -- nothing special about exception handling, it works the same as in -- Streamly. Like the @pipefail@ option in shells, exceptions are -- propagated if any of the stages fail. ProcessFailure (..) -- * Process Configuration -- | Use the config modifiers to modify the default config. , Config -- ** Common Modifiers -- | These options apply to both POSIX and Windows. , setCwd , setEnv , closeFiles , newProcessGroup , Session (..) , setSession -- ** Posix Only Modifiers -- | These options have no effect on Windows. , interruptChildOnly , setUserId , setGroupId -- ** Windows Only Modifiers -- | These options have no effect on Posix. , waitForDescendants -- * Generation , toChunks , toChunksWith , toBytes , toChars , toLines -- * Effects , toString , toStdout , toNull -- * Transformation , pipeChunks , pipeChunksWith , pipeBytes -- * Including Stderr Stream -- | Like other "Generation" routines but along with stdout, stderr is also -- included in the output stream. stdout is converted to 'Right' values in -- the output stream and stderr is converted to 'Left' values. , toBytesEither , toChunksEither , toChunksEitherWith , pipeBytesEither , pipeChunksEither , pipeChunksEitherWith -- * Non-streaming Processes -- | These processes do not attach the IO streams with other processes. , foreground , daemon , standalone -- * Deprecated , processChunks , processBytes ) where import Streamly.Internal.System.Process #include "DocTestProcess.hs"