Conveniently run child processes:
{-# LANGUAGE ScopedTypeVariables #-}
import Cradle
main :: IO ()
main = do
StdoutTrimmed stdout <- run $ cmd "echo" & addArgs ["Hello, World!"]
print stdout
-- prints "Hello, World!"
-- `run` is polymorphic on the return type. Just by adding it to the pattern
-- match, you can get things like the exit code and stderr:
(exitCode :: ExitCode, StderrRaw stderr) <- run $ cmd "ls" & addArgs ["does-not-exist"]
print exitCode
-- prints ExitFailure 2
print stderr
-- prints "ls: cannot access 'does-not-exist': No such file or directory\n"It does not run the processes through a shell, but rather is meant as a high-level interface to fork & exec.
process:processis substantially lower level thancradle. That is, it allows for more control, and more options, but at the cost of a more complicated interface. (cradleusesprocessunder the hood.)typed-process: A safer version ofprocess. Still lower-level thancradle.turtle:turtleis a more ambitious library, including a number of system-related functionality (such as changing directories, looking up environment variables, etc.), as well as providing convenient functions for running common executables such asdateandrm.cradleby contrast only runs specified processes.shake'scmd. This was the basis forcradle, which indeed started it's life as a factoring-out of thecmdlogic into a separate library. Since then, the API has been cleaned up and generalized. Notable changes are separatingcmdfromrunso functions can be more easily applied to the command; not being variadic in the arguments for better type inference; and removingCmdArgumentsclass altogether in favor of a composition ofProcessConfiguration -> ProcessConfigurationfunctions.
cradlefor Rust: The same ideas from the same people in another good language.