74      Safe-Inferred-24=K%rEnvironment built up by the shell script monad, so it knows which environment variables and functions are in use.Shell script monad.A shell expression.(Piping the first Expr to the second Exprexpressions run in a sub-shellthe body of a here-doc a comment a command A shell function.&A piece of text that is safely quoted.A shell variable.%Expand a shell variable to its value.?Quotes the value to allow it to be safely exposed to the shell.The method used is to replace ' with '"'"' and wrap the value inside single quotes. This works for POSIX shells, as well as other shells like csh.Indents an Expr!/Evaluate the monad and generates a list of Expr"NEvaluates the monad, and returns a list of Expr and the modified environment.#bRuns the passed Script, using the current environment, and returns the list of Expr it generates.PGenerates a shell script, including hashbang, suitable to be written to a file.&Generates a single line of shell code. #Adds a shell command to the script. Variadic argument version of  .The command can be passed any number of arguments. As well as passing Text and Q arguments, it also accepts Var arguments, which passes the value of a shell variable to the command.Convenient usage of   requires the following: {-# LANGUAGE OverloadedStrings, ExtendedDefaultRules #-} {-# OPTIONS_GHC -fno-warn-type-defaults #-} import Control.Monad.Shell import qualified Data.Text.Lazy as L default (L.Text)!This allows writing, for example: odemo = script $ do cmd "echo" "hello, world" name <- newVar "name" readVar name cmd "echo" "hello" name Adds an Expr to the script. >Adds a comment that is embedded in the generated shell script. Defines a new shell variable.The name of the variable that appears in the shell script will be based on provided name, but each call to newVar will generate a new, unique variable name.4Creates a new shell variable, with an initial value.9Gets a Var that refers to a global variable, such as PATHVDefines a shell function, and returns an action that can be run to call the function.&TODO parameter passing to the functionPipes together two Scripts.FRuns the command, and separates its output into parts (using the IFS)BThe action is run for each part, passed a Var containing the part.BAs long as the first Script exits nonzero, runs the second script.if with a monadic conditionalEIf the conditional exits 0, the first action is run, else the second.when with a monadic conditional!unless with a monadic conditional$BCreates a block such as "do : ; cmd ; cmd" or "else : ; cmd ; cmd"The use of : ensures that the block is not empty, and allows for more regular indetnetion, as well as making the single line formatting work.3Generates shell code to read a variable from stdin.By default, shell scripts continue running past commands that exit nonzero. Use "stopOnFailure True" to make the script stop on the first such command.'Makes a nonzero exit status be ignored.=%&'()*+, -./012!"#3 base of variable namebase of variable namevalue4$56789:;<  .%&'()*+, -./012!"#3 4$56789:;<=      !"#$%&'()*+,"-./0123456789:shell-monad-0.0.2Control.Monad.ShellScriptExprQVarvalquoteindentscript linearScriptruncmdaddcommentnewVarnewVarContaining globalVarfunc-|-forCmdwhileCmdifCmdwhenCmd unlessCmdreadVar stopOnFailure ignoreFailureEnvPipeSubshell HereDocBodyCommentCmdFuncgenevalrunMblockShellCmdcmdAllCmdArg toTextArgenvVarsenvFuncsgetQ modifyEnvVarsmodifyEnvFuncstoLinearScriptifCmd'$fShellCmdScript$fShellCmd(->) $fCmdArgQ $fCmdArgVar $fCmdArgText $fMonoidEnv $fMonadScript $fMonoidQ