-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Use OS processes as stream transformation functions -- -- Use operating system (OS) commands in Haskell programs as if they were -- native Haskell functions, by treating their inputs and outputs as -- Haskell streams. This allows you to write high-level Haskell scripts -- that can perform tasks similar to shell scripts, but with C-like -- performance, and with strong safety guarantees, refactorability, and -- modularity. @package streamly-process @version 0.3.1 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: -- --
-- >>> :{
-- Process.toBytes "echo" ["hello world"]
-- & Stream.fold Stdio.write
-- :}
-- hello world
--
toBytes :: (MonadAsync m, MonadCatch m) => FilePath -> [String] -> Stream m Word8
-- | The following code is equivalent to the shell command echo "hello
-- world":
--
--
-- >>> :{
-- Process.toChunks "echo" ["hello world"]
-- & Stream.fold Stdio.writeChunks
-- :}
-- hello world
--
--
-- -- >>> toChunks = toChunksWith id --toChunks :: (MonadAsync m, MonadCatch m) => FilePath -> [String] -> Stream m (Array Word8) -- | Like toChunks but use the specified configuration to run the -- process. toChunksWith :: (MonadCatch m, MonadAsync m) => (Config -> Config) -> FilePath -> [String] -> Stream m (Array Word8) -- |
-- >>> toChars path args = toBytes path args & Unicode.decodeUtf8 --toChars :: (MonadAsync m, MonadCatch m) => FilePath -> [String] -> Stream m Char -- |
-- >>> toLines path args f = toChars path args & Unicode.lines f --toLines :: (MonadAsync m, MonadCatch m) => Fold m Char a -> FilePath -> [String] -> Stream m a -- |
-- >>> toString path args = toChars path args & Stream.fold Fold.toList --toString :: (MonadAsync m, MonadCatch m) => FilePath -> [String] -> m String -- |
-- >>> toStdout path args = toChunks path args & Stdio.putChunks --toStdout :: (MonadAsync m, MonadCatch m) => FilePath -> [String] -> m () -- |
-- >>> toNull path args = toChunks path args & Stream.fold Fold.drain --toNull :: (MonadAsync m, MonadCatch m) => FilePath -> [String] -> m () -- | Like pipeChunks except that it works on a stream of bytes -- instead of a stream of chunks. -- -- We can write the example in pipeChunks as follows. -- --
-- >>> :{
-- Process.toBytes "echo" ["hello world"]
-- & Process.pipeBytes "tr" ["[a-z]", "[A-Z]"]
-- & Stream.fold Stdio.write
-- :}
-- HELLO WORLD
--
--
-- pre-release
pipeBytes :: (MonadCatch m, MonadAsync m) => FilePath -> [String] -> Stream m Word8 -> Stream m Word8
-- | pipeChunks 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.pipeChunks "tr" ["[a-z]", "[A-Z]"]
-- & Stream.fold Stdio.writeChunks
-- :}
-- HELLO WORLD
--
--
-- pre-release
pipeChunks :: (MonadCatch m, MonadAsync m) => FilePath -> [String] -> Stream m (Array Word8) -> Stream m (Array Word8)
-- | Like pipeChunks but use the specified configuration to run the
-- process.
pipeChunksWith :: (MonadCatch m, MonadAsync m) => (Config -> Config) -> FilePath -> [String] -> Stream m (Array Word8) -> Stream m (Array Word8)
-- | Like pipeChunks except that it works on a stream of chars
-- instead of a stream of chunks.
--
--
-- >>> :{
-- Process.toChars "echo" ["hello world"]
-- & Process.pipeChars "tr" ["[a-z]", "[A-Z]"]
-- & Stdio.putChars
-- :}
-- HELLO WORLD
--
--
-- We can seamlessly replace the tr process with the Haskell
-- toUpper function:
--
--
-- >>> :{
-- Process.toChars "echo" ["hello world"]
-- & fmap toUpper
-- & Stdio.putChars
-- :}
-- HELLO WORLD
--
--
-- pre-release
pipeChars :: (MonadCatch m, MonadAsync m) => FilePath -> [String] -> Stream m Char -> Stream m Char
-- | toBytesEither 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.toBytesEither "/bin/bash" ["-c", "echo 'hello'; echo 'world' 1>&2"]
-- & Stream.fold (Fold.partition Stdio.writeErr Stdio.write)
-- :}
-- world
-- hello
-- ((),())
--
toBytesEither :: (MonadAsync m, MonadCatch m) => FilePath -> [String] -> Stream m (Either Word8 Word8)
-- | Like toBytesEither but generates a stream of Array
-- Word8 instead of a stream of Word8.
--
--
-- >>> :{
-- toChunksEither "bash" ["-c", "echo 'hello'; echo 'world' 1>&2"]
-- & Stream.fold (Fold.partition Stdio.writeErrChunks Stdio.writeChunks)
-- :}
-- world
-- hello
-- ((),())
--
--
-- -- >>> toChunksEither = toChunksEitherWith id ---- -- Prefer toChunksEither over toBytesEither when -- performance matters. -- -- Pre-release toChunksEither :: (MonadAsync m, MonadCatch m) => FilePath -> [String] -> Stream m (Either (Array Word8) (Array Word8)) -- | Like toChunksEither but use the specified configuration to run -- the process. toChunksEitherWith :: (MonadCatch m, MonadAsync m) => (Config -> Config) -> FilePath -> [String] -> Stream m (Either (Array Word8) (Array Word8)) -- | pipeBytesEither 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:]: -- --
-- >>> :{
-- pipeBytesEither "echo" ["hello world"] Stream.nil
-- & Stream.catRights
-- & pipeBytesEither "tr" ["[:lower:]", "[:upper:]"]
-- & Stream.catRights
-- & Stream.fold Stdio.write
-- :}
-- HELLO WORLD
--
pipeBytesEither :: (MonadCatch m, MonadAsync m) => FilePath -> [String] -> Stream m Word8 -> Stream m (Either Word8 Word8)
-- | Like pipeChunks but also includes stderr as Left stream
-- in the Either output.
pipeChunksEither :: (MonadCatch m, MonadAsync m) => FilePath -> [String] -> Stream m (Array Word8) -> Stream m (Either (Array Word8) (Array Word8))
-- | Like pipeChunksEither but use the specified configuration to
-- run the process.
pipeChunksEitherWith :: (MonadCatch m, MonadAsync m) => (Config -> Config) -> FilePath -> [String] -> Stream m (Array Word8) -> Stream m (Either (Array Word8) (Array Word8))
-- | Launch a process interfacing with the user. User interrupts are sent
-- to the launched process and ignored by the parent process. The
-- launched process inherits stdin, stdout, and stderr from the parent,
-- so that the user can interact with the process. The parent waits for
-- the child process to exit, an ExitCode is returned when the
-- process finishes.
--
-- This is the same as the common system function found in other
-- libraries used to execute commands.
--
-- On Windows you can pass setSession NewConsole to create a new
-- console.
foreground :: (Config -> Config) -> FilePath -> [String] -> IO ExitCode
-- | Launch a daemon process. Closes stdin, stdout and stderr, creates a
-- new session, detached from the terminal, the parent does not wait for
-- the process to finish.
--
-- The ProcessHandle returned can be used to terminate the daemon
-- or send signals to it.
daemon :: (Config -> Config) -> FilePath -> [String] -> IO ProcessHandle
-- | Launch a standalone process i.e. the process does not have a way to
-- attach the IO streams with other processes. The IO streams stdin,
-- stdout, stderr can either be inherited from the parent or closed.
--
-- This API is more powerful than interactive and daemon
-- and can be used to implement both of these. However, it should be used
-- carefully e.g. if you inherit the IO streams and parent is not waiting
-- for the child process to finish then both parent and child may use the
-- IO streams resulting in garbled IO if both are reading/writing
-- simultaneously.
--
-- If the parent chooses to wait for the process an ExitCode is
-- returned otherwise a ProcessHandle is returned which can be
-- used to terminate the process, send signals to it or wait for it to
-- finish.
standalone :: Bool -> (Bool, Bool, Bool) -> (Config -> Config) -> FilePath -> [String] -> IO (Either ExitCode ProcessHandle)
-- | Deprecated: Use interruptChildOnly instead.
parentIgnoresInterrupt :: Bool -> Config -> Config
-- | Deprecated: Use waitForDescendants instead.
waitForChildTree :: Bool -> Config -> Config
-- | Deprecated: Use foreground instead.
interactive :: (Config -> Config) -> FilePath -> [String] -> IO ExitCode
-- | Deprecated: Please use pipeBytes instead.
processBytes :: (MonadCatch m, MonadAsync m) => FilePath -> [String] -> Stream m Word8 -> Stream m Word8
-- | Deprecated: Please use pipeChunks instead.
processChunks :: (MonadCatch m, MonadAsync m) => FilePath -> [String] -> Stream m (Array Word8) -> Stream m (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.Command
-- | -- >>> toBytes "echo hello world" & Stdio.putBytes -- hello world -- -- >>> toBytes "echo hello\\ world" & Stdio.putBytes -- hello world -- -- >>> toBytes "echo 'hello world'" & Stdio.putBytes -- hello world -- -- >>> toBytes "echo \"hello world\"" & Stdio.putBytes -- hello world ---- -- Pre-release toBytes :: (MonadAsync m, MonadCatch m) => String -> Stream m Word8 -- |
-- >>> toChunks "echo hello world" & Stdio.putChunks -- hello world ---- -- Pre-release toChunks :: (MonadAsync m, MonadCatch m) => String -> Stream m (Array Word8) -- | Like toChunks but use the specified configuration to run the -- process. toChunksWith :: (MonadCatch m, MonadAsync m) => (Config -> Config) -> String -> Stream m (Array Word8) -- |
-- >>> toChars "echo hello world" & Stdio.putChars -- hello world ---- -- Pre-release toChars :: (MonadAsync m, MonadCatch m) => String -> Stream m Char -- |
-- >>> toLines Fold.toList "echo -e hello\\\\nworld" & Stream.fold Fold.toList -- ["hello","world"] ---- -- Pre-release toLines :: (MonadAsync m, MonadCatch m) => Fold m Char a -> String -> Stream m a -- |
-- >>> toString "echo hello world" -- "hello world\n" ---- -- Pre-release toString :: (MonadAsync m, MonadCatch m) => String -> m String -- |
-- >>> toStdout "echo hello world" -- hello world ---- -- Pre-release toStdout :: (MonadAsync m, MonadCatch m) => String -> m () -- |
-- >>> toNull "echo hello world" ---- -- Pre-release toNull :: (MonadAsync m, MonadCatch m) => String -> m () -- | Like pipeChunks except that it works on a stream of bytes -- instead of a stream of chunks. -- --
-- >>> :{
-- toBytes "echo hello world"
-- & pipeBytes "tr [a-z] [A-Z]"
-- & Stdio.putBytes
-- :}
-- HELLO WORLD
--
--
-- Pre-release
pipeBytes :: (MonadAsync m, MonadCatch m) => String -> Stream m Word8 -> Stream m Word8
-- | Like pipeChunks except that it works on a stream of chars
-- instead of a stream of chunks.
--
--
-- >>> :{
-- toChars "echo hello world"
-- & pipeChars "tr [a-z] [A-Z]"
-- & Stdio.putChars
-- :}
-- HELLO WORLD
--
--
-- Pre-release
pipeChars :: (MonadAsync m, MonadCatch m) => String -> Stream m Char -> Stream m Char
-- | pipeChunks command input runs the executable with arguments
-- specified by command and supplying input stream as
-- its standard input. Returns the standard output of the executable as a
-- stream of byte arrays.
--
-- 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]:
--
--
-- >>> :{
-- toChunks "echo hello world"
-- & pipeChunks "tr [a-z] [A-Z]"
-- & Stdio.putChunks
-- :}
-- HELLO WORLD
--
--
-- Pre-release
pipeChunks :: (MonadAsync m, MonadCatch m) => String -> Stream m (Array Word8) -> Stream m (Array Word8)
-- | Like pipeChunks but use the specified configuration to run the
-- process.
pipeChunksWith :: (MonadCatch m, MonadAsync m) => (Config -> Config) -> String -> Stream m (Array Word8) -> Stream m (Array Word8)
-- | Launch a standlone process i.e. the process does not have a way to
-- attach the IO streams with other processes. The IO streams stdin,
-- stdout, stderr can either be inherited from the parent or closed.
--
-- This API is more powerful than interactive and daemon
-- and can be used to implement both of these. However, it should be used
-- carefully e.g. if you inherit the IO streams and parent is not waiting
-- for the child process to finish then both parent and child may use the
-- IO streams resulting in garbled IO if both are reading/writing
-- simultaneously.
--
-- If the parent chooses to wait for the process an ExitCode is
-- returned otherwise a ProcessHandle is returned which can be
-- used to terminate the process, send signals to it or wait for it to
-- finish.
standalone :: Bool -> (Bool, Bool, Bool) -> (Config -> Config) -> String -> IO (Either ExitCode ProcessHandle)
-- | Launch a process interfacing with the user. User interrupts are sent
-- to the launched process and ignored by the parent process. The
-- launched process inherits stdin, stdout, and stderr from the parent,
-- so that the user can interact with the process. The parent waits for
-- the child process to exit, an ExitCode is returned when the
-- process finishes.
--
-- This is the same as the common system function found in other
-- libraries used to execute commands.
--
-- On Windows you can pass setSession NewConsole to create a new
-- console.
foreground :: (Config -> Config) -> String -> IO ExitCode
-- | Launch a daemon process. Closes stdin, stdout and stderr, creates a
-- new session, detached from the terminal, the parent does not wait for
-- the process to finish.
--
-- The ProcessHandle returned can be used to terminate the daemon
-- or send signals to it.
daemon :: (Config -> Config) -> String -> IO ProcessHandle
quotedWord :: MonadCatch m => Parser Char m String
-- | A modifier for process running APIs in Streamly.System.Process
-- to run command strings.
--
-- For example:
--
-- -- >>> runWith Process.toString "echo hello" -- "hello\n" -- -- >>> runWith Process.toStdout "echo hello" -- hello ---- -- Internal runWith :: MonadCatch m => (FilePath -> [String] -> m a) -> String -> m a -- | A modifier for stream generation APIs in -- Streamly.System.Process to generate streams from command -- strings. -- -- For example: -- --
-- >>> streamWith Process.toBytes "echo hello" & Stdio.putBytes -- hello -- -- >>> streamWith Process.toChunks "echo hello" & Stdio.putChunks -- hello ---- -- Internal streamWith :: MonadCatch m => (FilePath -> [String] -> Stream m a) -> String -> Stream m a -- | A modifier for process piping APIs in Streamly.System.Process -- to pipe data through processes specified by command strings. -- -- For example: -- --
-- >>> :{
-- toChunks "echo hello"
-- & pipeWith Process.pipeChunks "tr [a-z] [A-Z]"
-- & Stdio.putChunks
-- :}
-- HELLO
--
--
-- Internal
pipeWith :: MonadCatch m => (FilePath -> [String] -> Stream m a -> Stream m b) -> String -> Stream m a -> Stream m b
-- | This module provides a way to invoke external executables and use them
-- seamlessly in a Haskell program, in a streaming fashion. This enables
-- you to write high-level Haskell scripts to perform tasks similar to
-- shell scripts without requiring the shell. Moreover, Haskell scripts
-- provide C-like performance.
--
-- Please see the Streamly.System.Process for basics. This module
-- is a wrapper over that module. Streamly.System.Process requires
-- specifying a command executable name and its arguments separately
-- (e.g. "ls" "-al") whereas using this module we can specify the
-- executable and its arguments more conveniently as a single command
-- string e.g. we can execute "ls -al".
--
-- A command string is parsed in the same way as a posix shell would
-- parse it. A command string consists of whitespace separated tokens
-- with the first token treated as the executable name and the rest as
-- arguments. Whitespace can be escaped using \. Alternatively,
-- double quotes or single quotes can be used to enclose tokens with
-- whitespaces. Quotes can be escaped using \. Single quotes
-- inside double quotes or vice-versa are treated as normal characters.
--
-- You can use the string quasiquoter str to write commands
-- conveniently, it allows Haskell variable expansion as well e.g.:
--
--
-- >>> f = "file name"
--
-- >>> [str|ls -al "#{f} with spaces"|]
-- "ls -al \"file name with spaces\""
--
--
-- With the Streamly.System.Command module you can write the
-- examples in the Streamly.System.Process module more
-- conveniently.
--
--
-- >>> :{
-- Command.toBytes [str|echo "hello world"|]
-- & Command.pipeBytes [str|tr [a-z] [A-Z]|]
-- & Stream.fold Stdio.write
-- :}
-- HELLO WORLD
--
--
--
-- >>> :{
-- Command.toBytes [str|sh "-c" "echo 'hello world' | tr [a-z] [A-Z]"|]
-- & Stream.fold Stdio.write
-- :}
-- HELLO WORLD
--
--
--
-- >>> :{
-- grep file =
-- Command.toBytes [str|grep -H "pattern" #{file}|]
-- & Stream.handle (\(_ :: Command.ProcessFailure) -> Stream.nil)
-- & Stream.foldMany (Fold.takeEndBy (== 10) Array.write)
-- :}
--
--
--
-- >>> :{
-- pgrep =
-- Dir.readFiles "."
-- & Stream.parConcatMap id grep
-- & Stream.fold Stdio.writeChunks
-- :}
--
--
-- -- >>> toBytes "echo hello world" & Stdio.putBytes -- hello world -- -- >>> toBytes "echo hello\\ world" & Stdio.putBytes -- hello world -- -- >>> toBytes "echo 'hello world'" & Stdio.putBytes -- hello world -- -- >>> toBytes "echo \"hello world\"" & Stdio.putBytes -- hello world ---- -- Pre-release toBytes :: (MonadAsync m, MonadCatch m) => String -> Stream m Word8 -- |
-- >>> toChunks "echo hello world" & Stdio.putChunks -- hello world ---- -- Pre-release toChunks :: (MonadAsync m, MonadCatch m) => String -> Stream m (Array Word8) -- | Like toChunks but use the specified configuration to run the -- process. toChunksWith :: (MonadCatch m, MonadAsync m) => (Config -> Config) -> String -> Stream m (Array Word8) -- |
-- >>> toChars "echo hello world" & Stdio.putChars -- hello world ---- -- Pre-release toChars :: (MonadAsync m, MonadCatch m) => String -> Stream m Char -- |
-- >>> toLines Fold.toList "echo -e hello\\\\nworld" & Stream.fold Fold.toList -- ["hello","world"] ---- -- Pre-release toLines :: (MonadAsync m, MonadCatch m) => Fold m Char a -> String -> Stream m a -- |
-- >>> toString "echo hello world" -- "hello world\n" ---- -- Pre-release toString :: (MonadAsync m, MonadCatch m) => String -> m String -- |
-- >>> toStdout "echo hello world" -- hello world ---- -- Pre-release toStdout :: (MonadAsync m, MonadCatch m) => String -> m () -- |
-- >>> toNull "echo hello world" ---- -- Pre-release toNull :: (MonadAsync m, MonadCatch m) => String -> m () -- | pipeChunks command input runs the executable with arguments -- specified by command and supplying input stream as -- its standard input. Returns the standard output of the executable as a -- stream of byte arrays. -- -- 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]: -- --
-- >>> :{
-- toChunks "echo hello world"
-- & pipeChunks "tr [a-z] [A-Z]"
-- & Stdio.putChunks
-- :}
-- HELLO WORLD
--
--
-- Pre-release
pipeChunks :: (MonadAsync m, MonadCatch m) => String -> Stream m (Array Word8) -> Stream m (Array Word8)
-- | Like pipeChunks but use the specified configuration to run the
-- process.
pipeChunksWith :: (MonadCatch m, MonadAsync m) => (Config -> Config) -> String -> Stream m (Array Word8) -> Stream m (Array Word8)
-- | Like pipeChunks except that it works on a stream of bytes
-- instead of a stream of chunks.
--
--
-- >>> :{
-- toBytes "echo hello world"
-- & pipeBytes "tr [a-z] [A-Z]"
-- & Stdio.putBytes
-- :}
-- HELLO WORLD
--
--
-- Pre-release
pipeBytes :: (MonadAsync m, MonadCatch m) => String -> Stream m Word8 -> Stream m Word8
-- | Like pipeChunks except that it works on a stream of chars
-- instead of a stream of chunks.
--
--
-- >>> :{
-- toChars "echo hello world"
-- & pipeChars "tr [a-z] [A-Z]"
-- & Stdio.putChars
-- :}
-- HELLO WORLD
--
--
-- Pre-release
pipeChars :: (MonadAsync m, MonadCatch m) => String -> Stream m Char -> Stream m Char
-- | Launch a process interfacing with the user. User interrupts are sent
-- to the launched process and ignored by the parent process. The
-- launched process inherits stdin, stdout, and stderr from the parent,
-- so that the user can interact with the process. The parent waits for
-- the child process to exit, an ExitCode is returned when the
-- process finishes.
--
-- This is the same as the common system function found in other
-- libraries used to execute commands.
--
-- On Windows you can pass setSession NewConsole to create a new
-- console.
foreground :: (Config -> Config) -> String -> IO ExitCode
-- | Launch a daemon process. Closes stdin, stdout and stderr, creates a
-- new session, detached from the terminal, the parent does not wait for
-- the process to finish.
--
-- The ProcessHandle returned can be used to terminate the daemon
-- or send signals to it.
daemon :: (Config -> Config) -> String -> IO ProcessHandle
-- | Launch a standlone process i.e. the process does not have a way to
-- attach the IO streams with other processes. The IO streams stdin,
-- stdout, stderr can either be inherited from the parent or closed.
--
-- This API is more powerful than interactive and daemon
-- and can be used to implement both of these. However, it should be used
-- carefully e.g. if you inherit the IO streams and parent is not waiting
-- for the child process to finish then both parent and child may use the
-- IO streams resulting in garbled IO if both are reading/writing
-- simultaneously.
--
-- If the parent chooses to wait for the process an ExitCode is
-- returned otherwise a ProcessHandle is returned which can be
-- used to terminate the process, send signals to it or wait for it to
-- finish.
standalone :: Bool -> (Bool, Bool, Bool) -> (Config -> Config) -> String -> IO (Either ExitCode ProcessHandle)
-- | 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.
--
--
-- >>> :{
-- 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
--
--
--
-- >>> :{
-- Process.toBytes "sh" ["-c", "echo hello | tr [a-z] [A-Z]"]
-- & Stream.fold Stdio.write
-- :}
-- HELLO
--
--
--
-- >>> :{
-- 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
-- :}
--
--
--
-- >>> :{
-- Process.toChunks "echo" ["hello world"]
-- & Stream.fold Stdio.writeChunks
-- :}
-- hello world
--
--
-- -- >>> toChunks = toChunksWith id --toChunks :: (MonadAsync m, MonadCatch m) => FilePath -> [String] -> Stream m (Array Word8) -- | Like toChunks but use the specified configuration to run the -- process. toChunksWith :: (MonadCatch m, MonadAsync m) => (Config -> Config) -> FilePath -> [String] -> Stream m (Array Word8) -- | The following code is equivalent to the shell command echo "hello -- world": -- --
-- >>> :{
-- Process.toBytes "echo" ["hello world"]
-- & Stream.fold Stdio.write
-- :}
-- hello world
--
toBytes :: (MonadAsync m, MonadCatch m) => FilePath -> [String] -> Stream m Word8
-- | -- >>> toChars path args = toBytes path args & Unicode.decodeUtf8 --toChars :: (MonadAsync m, MonadCatch m) => FilePath -> [String] -> Stream m Char -- |
-- >>> toLines path args f = toChars path args & Unicode.lines f --toLines :: (MonadAsync m, MonadCatch m) => Fold m Char a -> FilePath -> [String] -> Stream m a -- |
-- >>> toString path args = toChars path args & Stream.fold Fold.toList --toString :: (MonadAsync m, MonadCatch m) => FilePath -> [String] -> m String -- |
-- >>> toStdout path args = toChunks path args & Stdio.putChunks --toStdout :: (MonadAsync m, MonadCatch m) => FilePath -> [String] -> m () -- |
-- >>> toNull path args = toChunks path args & Stream.fold Fold.drain --toNull :: (MonadAsync m, MonadCatch m) => FilePath -> [String] -> m () -- | pipeChunks 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.pipeChunks "tr" ["[a-z]", "[A-Z]"]
-- & Stream.fold Stdio.writeChunks
-- :}
-- HELLO WORLD
--
--
-- pre-release
pipeChunks :: (MonadCatch m, MonadAsync m) => FilePath -> [String] -> Stream m (Array Word8) -> Stream m (Array Word8)
-- | Like pipeChunks but use the specified configuration to run the
-- process.
pipeChunksWith :: (MonadCatch m, MonadAsync m) => (Config -> Config) -> FilePath -> [String] -> Stream m (Array Word8) -> Stream m (Array Word8)
-- | Like pipeChunks except that it works on a stream of bytes
-- instead of a stream of chunks.
--
-- We can write the example in pipeChunks as follows.
--
--
-- >>> :{
-- Process.toBytes "echo" ["hello world"]
-- & Process.pipeBytes "tr" ["[a-z]", "[A-Z]"]
-- & Stream.fold Stdio.write
-- :}
-- HELLO WORLD
--
--
-- pre-release
pipeBytes :: (MonadCatch m, MonadAsync m) => FilePath -> [String] -> Stream m Word8 -> Stream m Word8
-- | toBytesEither 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.toBytesEither "/bin/bash" ["-c", "echo 'hello'; echo 'world' 1>&2"]
-- & Stream.fold (Fold.partition Stdio.writeErr Stdio.write)
-- :}
-- world
-- hello
-- ((),())
--
toBytesEither :: (MonadAsync m, MonadCatch m) => FilePath -> [String] -> Stream m (Either Word8 Word8)
-- | Like toBytesEither but generates a stream of Array
-- Word8 instead of a stream of Word8.
--
--
-- >>> :{
-- toChunksEither "bash" ["-c", "echo 'hello'; echo 'world' 1>&2"]
-- & Stream.fold (Fold.partition Stdio.writeErrChunks Stdio.writeChunks)
-- :}
-- world
-- hello
-- ((),())
--
--
-- -- >>> toChunksEither = toChunksEitherWith id ---- -- Prefer toChunksEither over toBytesEither when -- performance matters. -- -- Pre-release toChunksEither :: (MonadAsync m, MonadCatch m) => FilePath -> [String] -> Stream m (Either (Array Word8) (Array Word8)) -- | Like toChunksEither but use the specified configuration to run -- the process. toChunksEitherWith :: (MonadCatch m, MonadAsync m) => (Config -> Config) -> FilePath -> [String] -> Stream m (Either (Array Word8) (Array Word8)) -- | pipeBytesEither 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:]: -- --
-- >>> :{
-- pipeBytesEither "echo" ["hello world"] Stream.nil
-- & Stream.catRights
-- & pipeBytesEither "tr" ["[:lower:]", "[:upper:]"]
-- & Stream.catRights
-- & Stream.fold Stdio.write
-- :}
-- HELLO WORLD
--
pipeBytesEither :: (MonadCatch m, MonadAsync m) => FilePath -> [String] -> Stream m Word8 -> Stream m (Either Word8 Word8)
-- | Like pipeChunks but also includes stderr as Left stream
-- in the Either output.
pipeChunksEither :: (MonadCatch m, MonadAsync m) => FilePath -> [String] -> Stream m (Array Word8) -> Stream m (Either (Array Word8) (Array Word8))
-- | Like pipeChunksEither but use the specified configuration to
-- run the process.
pipeChunksEitherWith :: (MonadCatch m, MonadAsync m) => (Config -> Config) -> FilePath -> [String] -> Stream m (Array Word8) -> Stream m (Either (Array Word8) (Array Word8))
-- | Launch a process interfacing with the user. User interrupts are sent
-- to the launched process and ignored by the parent process. The
-- launched process inherits stdin, stdout, and stderr from the parent,
-- so that the user can interact with the process. The parent waits for
-- the child process to exit, an ExitCode is returned when the
-- process finishes.
--
-- This is the same as the common system function found in other
-- libraries used to execute commands.
--
-- On Windows you can pass setSession NewConsole to create a new
-- console.
foreground :: (Config -> Config) -> FilePath -> [String] -> IO ExitCode
-- | Launch a daemon process. Closes stdin, stdout and stderr, creates a
-- new session, detached from the terminal, the parent does not wait for
-- the process to finish.
--
-- The ProcessHandle returned can be used to terminate the daemon
-- or send signals to it.
daemon :: (Config -> Config) -> FilePath -> [String] -> IO ProcessHandle
-- | Launch a standalone process i.e. the process does not have a way to
-- attach the IO streams with other processes. The IO streams stdin,
-- stdout, stderr can either be inherited from the parent or closed.
--
-- This API is more powerful than interactive and daemon
-- and can be used to implement both of these. However, it should be used
-- carefully e.g. if you inherit the IO streams and parent is not waiting
-- for the child process to finish then both parent and child may use the
-- IO streams resulting in garbled IO if both are reading/writing
-- simultaneously.
--
-- If the parent chooses to wait for the process an ExitCode is
-- returned otherwise a ProcessHandle is returned which can be
-- used to terminate the process, send signals to it or wait for it to
-- finish.
standalone :: Bool -> (Bool, Bool, Bool) -> (Config -> Config) -> FilePath -> [String] -> IO (Either ExitCode ProcessHandle)
-- | Deprecated: Please use pipeChunks instead.
processChunks :: (MonadCatch m, MonadAsync m) => FilePath -> [String] -> Stream m (Array Word8) -> Stream m (Array Word8)
-- | Deprecated: Please use pipeBytes instead.
processBytes :: (MonadCatch m, MonadAsync m) => FilePath -> [String] -> Stream m Word8 -> Stream m Word8