Command 0.0.2 → 0.0.4
raw patch · 3 files changed
+337/−302 lines, 3 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
+ System.Command: (->->) :: Monad m => m ExitCode -> m a -> m ExitCode
+ System.Command: (<-<-) :: Monad m => m a -> m ExitCode -> m ExitCode
+ System.Command: create_group :: CreateProcess -> Bool
- System.Command: CreateProcess :: CmdSpec -> Maybe FilePath -> Maybe [(String, String)] -> StdStream -> StdStream -> StdStream -> Bool -> CreateProcess
+ System.Command: CreateProcess :: CmdSpec -> Maybe FilePath -> Maybe [(String, String)] -> StdStream -> StdStream -> StdStream -> Bool -> Bool -> CreateProcess
Files
- Command.cabal +14/−4
- System/Command.hs +0/−298
- src/System/Command.hs +323/−0
Command.cabal view
@@ -1,16 +1,21 @@ Name: Command-Version: 0.0.2+Version: 0.0.4 License: BSD3 License-File: LICENSE Author: Tony Morris <ʇǝu˙sıɹɹoɯʇ@ןןǝʞsɐɥ> Maintainer: Tony Morris Synopsis: A replacement for System.Exit and System.Process Category: System+Homepage: https://github.com/tonymorris/command Description: Specifically, this library replaces @System.Exit.ExitCode@ with an abstract data type.-Cabal-version: >= 1.2+Cabal-Version: >= 1.6 Build-Type: Simple +Source-Repository head+ Type: git+ Location: git@github.com:tonymorris/command.git+ Flag small_base Description: Choose the new, split-up base package. @@ -19,8 +24,13 @@ base < 5 && >= 4 , process - GHC-Options: -Wall+ GHC-Options: + -Wall - Exposed-Modules: System.Command+ Hs-Source-Dirs:+ src++ Exposed-Modules: + System.Command
− System/Command.hs
@@ -1,298 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}--module System.Command-(- -- * Running sub-processes- P.createProcess-, P.shell-, P.proc-, P.CreateProcess(..)-, P.CmdSpec(..)-, P.StdStream(..)-, P.ProcessHandle- -- * Specific variants of createProcess-, readProcessWithExitCode-, P.runCommand-, P.runProcess-, P.runInteractiveCommand-, P.runInteractiveProcess-, P.readProcess-, system-, rawSystem- -- * Data Type-, ExitCode- -- * ExitCode combinators-, exitCode-, success-, isSuccess-, isFailure-, exitValue-, exitWith-, exitFailure-, exitSuccess-, (->>)-, (->>>)-, (<<-)-, (<<<-)-, runExitCodes- -- * Process completion-, waitForProcess-, getProcessExitCode-, P.terminateProcess-) where--import qualified System.Exit as E-import qualified System.Process as P-import Data.Data-import Data.Monoid-import Control.Arrow-import Control.Exception-import Prelude hiding (foldr)-import Data.Foldable---- | The result of running a process-newtype ExitCode =- ExitCode Int- deriving (Eq, Ord, Data, Typeable)--instance Read ExitCode where- readsPrec n s =- first exitCode `map` readsPrec n s--instance Show ExitCode where- show (ExitCode n) =- if n == 0 then "ExitSuccess" else "ExitFailure " ++ show n--instance Exception ExitCode where- toException =- toException . toExitCode- fromException =- fmap fromExitCode . fromException--instance Monoid ExitCode where- mempty =- success- a `mappend` b =- if isSuccess a then b else a---- | Construct a process result.--- A value of @0@ denotes success, otherwise, failure.-exitCode ::- Int- -> ExitCode-exitCode =- ExitCode---- | Construct a process result with the value @0@.-success ::- ExitCode-success =- exitCode 0---- | Returns true if the given process result was constructed with the value @0@, otherwise false.-isSuccess ::- ExitCode- -> Bool-isSuccess (ExitCode n) =- n == 0---- | Returns false if the given process result was constructed with the value @0@, otherwise true.-isFailure ::- ExitCode- -> Bool-isFailure =- not . isSuccess---- | Returns the value that the given process result was constructed with.-exitValue ::- ExitCode- -> Int-exitValue (ExitCode n) =- n---- | Computation 'exitWith' @code@ throws 'ExitCode' @code@.--- Normally this terminates the program, returning @code@ to the--- program's caller. Before the program terminates, any open or--- semi-closed handles are first closed.------ A program that fails in any other way is treated as if it had--- called 'exitFailure'.--- A program that terminates successfully without calling 'exitWith'--- explicitly is treated as it it had called 'exitWith' 'ExitSuccess'.------ As an 'ExitCode' is not an 'IOError', 'exitWith' bypasses--- the error handling in the 'IO' monad and cannot be intercepted by--- 'catch' from the "Prelude". However it is a 'SomeException', and can--- be caught using the functions of "Control.Exception". This means--- that cleanup computations added with 'Control.Exception.bracket'--- (from "Control.Exception") are also executed properly on 'exitWith'.------ Note: in GHC, 'exitWith' should be called from the main program--- thread in order to exit the process. When called from another--- thread, 'exitWith' will throw an 'ExitException' as normal, but the--- exception will not cause the process itself to exit.-exitWith ::- ExitCode- -> IO a-exitWith =- E.exitWith . toExitCode---- | The computation 'exitFailure' is equivalent to--- 'exitWith' @(@'exitCode exitfail'@)@,--- where /exitfail/ is implementation-dependent.-exitFailure ::- IO a-exitFailure =- exitWith (exitCode 1)---- | The computation 'exitSuccess' is equivalent to--- 'exitWith' 'success', It terminates the program--- sucessfully.-exitSuccess ::- IO a-exitSuccess =- exitWith success---- | Runs the first action.------ Only if the result is successful, run the second action returning its result.-(->>) ::- Monad m =>- m ExitCode- -> m ExitCode- -> m ExitCode-a ->> b =- do a' <- a- if isSuccess a' then b else return a'---- | Runs the first action.------ Only if the result is successful, run the second action returning no result.-(->>>) ::- Monad m =>- m ExitCode- -> m a- -> m ()-a ->>> b =- do a' <- a- if isSuccess a' then b >> return () else return ()---- | Runs the second action.------ Only if the result is successful, run the first action returning its result.-(<<-) ::- Monad m =>- m ExitCode- -> m ExitCode- -> m ExitCode-(<<-) =- flip (->>)---- | Runs the second action.------ Only if the result is successful, run the first action returning no result.-(<<<-) ::- Monad m =>- m a- -> m ExitCode- -> m ()-(<<<-) =- flip (->>>)---- | Run the structure of actions stopping at the first failure.-runExitCodes ::- (Monad m, Foldable f) =>- f (m ExitCode)- -> m ExitCode-runExitCodes =- foldr (->>) (return success)---- | readProcessWithExitCode creates an external process, reads its--- standard output and standard error strictly, waits until the process--- terminates, and then returns the 'ExitCode' of the process,--- the standard output, and the standard error.------ 'readProcess' and 'readProcessWithExitCode' are fairly simple wrappers--- around 'createProcess'. Constructing variants of these functions is--- quite easy: follow the link to the source code to see how--- 'readProcess' is implemented.-readProcessWithExitCode ::- FilePath- -> [String]- -> String- -> IO (ExitCode, String, String)-readProcessWithExitCode p args i =- fmap (\(e, t, u) -> (fromExitCode e, t, u)) (P.readProcessWithExitCode p args i)---- | Computation @system cmd@ returns the exit code produced when the--- operating system runs the shell command @cmd@.------ This computation may fail with------ * @PermissionDenied@: The process has insufficient privileges to--- perform the operation.------ * @ResourceExhausted@: Insufficient resources are available to--- perform the operation.------ * @UnsupportedOperation@: The implementation does not support--- system calls.------ On Windows, 'system' passes the command to the Windows command--- interpreter (@CMD.EXE@ or @COMMAND.COM@), hence Unixy shell tricks--- will not work.-system ::- String- -> IO ExitCode-system =- fmap fromExitCode . P.system---- | The computation @'rawSystem' cmd args@ runs the operating system command--- @cmd@ in such a way that it receives as arguments the @args@ strings--- exactly as given, with no funny escaping or shell meta-syntax expansion.--- It will therefore behave more portably between operating systems than 'system'.------ The return codes and possible failures are the same as for 'system'.-rawSystem ::- String- -> [String]- -> IO ExitCode-rawSystem z =- fmap fromExitCode . P.rawSystem z---- | Waits for the specified process to terminate, and returns its exit code.---- GHC Note: in order to call @waitForProcess@ without blocking all the--- other threads in the system, you must compile the program with--- @-threaded@.-waitForProcess ::- P.ProcessHandle- -> IO ExitCode-waitForProcess =- fmap fromExitCode . P.waitForProcess----- | This is a non-blocking version of 'waitForProcess'. If the process is--- still running, 'Nothing' is returned. If the process has exited, then--- @'Just' e@ is returned where @e@ is the exit code of the process.-getProcessExitCode ::- P.ProcessHandle- -> IO (Maybe ExitCode)-getProcessExitCode =- (fmap . fmap) fromExitCode . P.getProcessExitCode---- not exported--toExitCode ::- ExitCode- -> E.ExitCode-toExitCode (ExitCode n) =- if n == 0 then E.ExitSuccess else E.ExitFailure n--fromExitCode ::- E.ExitCode- -> ExitCode-fromExitCode E.ExitSuccess =- success-fromExitCode (E.ExitFailure n) =- exitCode n
+ src/System/Command.hs view
@@ -0,0 +1,323 @@+{-# LANGUAGE DeriveDataTypeable #-}++module System.Command+(+ -- * Running sub-processes+ P.createProcess+, P.shell+, P.proc+, P.CreateProcess(..)+, P.CmdSpec(..)+, P.StdStream(..)+, P.ProcessHandle+ -- * Specific variants of createProcess+, readProcessWithExitCode+, P.runCommand+, P.runProcess+, P.runInteractiveCommand+, P.runInteractiveProcess+, P.readProcess+, system+, rawSystem+ -- * Data Type+, ExitCode+ -- * ExitCode combinators+, exitCode+, success+, isSuccess+, isFailure+, exitValue+, exitWith+, exitFailure+, exitSuccess+, (->>)+, (->>>)+, (->->)+, (<<-)+, (<<<-)+, (<-<-)+, runExitCodes+ -- * Process completion+, waitForProcess+, getProcessExitCode+, P.terminateProcess+) where++import qualified System.Exit as E+import qualified System.Process as P+import Data.Data+import Data.Monoid+import Control.Arrow+import Control.Exception+import Prelude hiding (foldr)+import Data.Foldable++-- | The result of running a process+newtype ExitCode =+ ExitCode Int+ deriving (Eq, Ord, Data, Typeable)++instance Read ExitCode where+ readsPrec n s =+ first exitCode `map` readsPrec n s++instance Show ExitCode where+ show (ExitCode n) =+ if n == 0 then "ExitSuccess" else "ExitFailure " ++ show n++instance Exception ExitCode where+ toException =+ toException . toExitCode+ fromException =+ fmap fromExitCode . fromException++instance Monoid ExitCode where+ mempty =+ success+ a `mappend` b =+ if isSuccess a then b else a++-- | Construct a process result.+-- A value of @0@ denotes success, otherwise, failure.+exitCode ::+ Int+ -> ExitCode+exitCode =+ ExitCode++-- | Construct a process result with the value @0@.+success ::+ ExitCode+success =+ exitCode 0++-- | Returns true if the given process result was constructed with the value @0@, otherwise false.+isSuccess ::+ ExitCode+ -> Bool+isSuccess (ExitCode n) =+ n == 0++-- | Returns false if the given process result was constructed with the value @0@, otherwise true.+isFailure ::+ ExitCode+ -> Bool+isFailure =+ not . isSuccess++-- | Returns the value that the given process result was constructed with.+exitValue ::+ ExitCode+ -> Int+exitValue (ExitCode n) =+ n++-- | Computation 'exitWith' @code@ throws 'ExitCode' @code@.+-- Normally this terminates the program, returning @code@ to the+-- program's caller. Before the program terminates, any open or+-- semi-closed handles are first closed.+--+-- A program that fails in any other way is treated as if it had+-- called 'exitFailure'.+-- A program that terminates successfully without calling 'exitWith'+-- explicitly is treated as it it had called 'exitWith' 'ExitSuccess'.+--+-- As an 'ExitCode' is not an 'IOError', 'exitWith' bypasses+-- the error handling in the 'IO' monad and cannot be intercepted by+-- 'catch' from the "Prelude". However it is a 'SomeException', and can+-- be caught using the functions of "Control.Exception". This means+-- that cleanup computations added with 'Control.Exception.bracket'+-- (from "Control.Exception") are also executed properly on 'exitWith'.+--+-- Note: in GHC, 'exitWith' should be called from the main program+-- thread in order to exit the process. When called from another+-- thread, 'exitWith' will throw an 'ExitException' as normal, but the+-- exception will not cause the process itself to exit.+exitWith ::+ ExitCode+ -> IO a+exitWith =+ E.exitWith . toExitCode++-- | The computation 'exitFailure' is equivalent to+-- 'exitWith' @(@'exitCode exitfail'@)@,+-- where /exitfail/ is implementation-dependent.+exitFailure ::+ IO a+exitFailure =+ exitWith (exitCode 1)++-- | The computation 'exitSuccess' is equivalent to+-- 'exitWith' 'success', It terminates the program+-- sucessfully.+exitSuccess ::+ IO a+exitSuccess =+ exitWith success++-- | Runs the first action.+--+-- Only if the result is successful, run the second action returning its result.+(->>) ::+ Monad m =>+ m ExitCode+ -> m ExitCode+ -> m ExitCode+a ->> b =+ do a' <- a+ if isSuccess a' then b else return a'++-- | Runs the first action.+--+-- Only if the result is successful, run the second action returning no result.+(->>>) ::+ Monad m =>+ m ExitCode+ -> m a+ -> m ()+a ->>> b =+ do a' <- a+ if isSuccess a' then b >> return () else return ()++-- | Runs the first action.+--+-- Only if the result is successful, run the second action returning the first action's result.+(->->) ::+ Monad m =>+ m ExitCode+ -> m a+ -> m ExitCode+a ->-> b =+ do a' <- a+ if isSuccess a' then b >> return a' else return a'++-- | Runs the second action.+--+-- Only if the result is successful, run the first action returning its result.+(<<-) ::+ Monad m =>+ m ExitCode+ -> m ExitCode+ -> m ExitCode+(<<-) =+ flip (->>)++-- | Runs the second action.+--+-- Only if the result is successful, run the first action returning no result.+(<<<-) ::+ Monad m =>+ m a+ -> m ExitCode+ -> m ()+(<<<-) =+ flip (->>>)++-- | Runs the second action.+--+-- Only if the result is successful, run the first action returning the second action's result.+(<-<-) ::+ Monad m =>+ m a+ -> m ExitCode+ -> m ExitCode+(<-<-) =+ flip (->->)++-- | Run the structure of actions stopping at the first failure.+runExitCodes ::+ (Monad m, Foldable f) =>+ f (m ExitCode)+ -> m ExitCode+runExitCodes =+ foldr (->>) (return success)++-- | readProcessWithExitCode creates an external process, reads its+-- standard output and standard error strictly, waits until the process+-- terminates, and then returns the 'ExitCode' of the process,+-- the standard output, and the standard error.+--+-- 'readProcess' and 'readProcessWithExitCode' are fairly simple wrappers+-- around 'createProcess'. Constructing variants of these functions is+-- quite easy: follow the link to the source code to see how+-- 'readProcess' is implemented.+readProcessWithExitCode ::+ FilePath+ -> [String]+ -> String+ -> IO (ExitCode, String, String)+readProcessWithExitCode p args i =+ fmap (\(e, t, u) -> (fromExitCode e, t, u)) (P.readProcessWithExitCode p args i)++-- | Computation @system cmd@ returns the exit code produced when the+-- operating system runs the shell command @cmd@.+--+-- This computation may fail with+--+-- * @PermissionDenied@: The process has insufficient privileges to+-- perform the operation.+--+-- * @ResourceExhausted@: Insufficient resources are available to+-- perform the operation.+--+-- * @UnsupportedOperation@: The implementation does not support+-- system calls.+--+-- On Windows, 'system' passes the command to the Windows command+-- interpreter (@CMD.EXE@ or @COMMAND.COM@), hence Unixy shell tricks+-- will not work.+system ::+ String+ -> IO ExitCode+system =+ fmap fromExitCode . P.system++-- | The computation @'rawSystem' cmd args@ runs the operating system command+-- @cmd@ in such a way that it receives as arguments the @args@ strings+-- exactly as given, with no funny escaping or shell meta-syntax expansion.+-- It will therefore behave more portably between operating systems than 'system'.+--+-- The return codes and possible failures are the same as for 'system'.+rawSystem ::+ String+ -> [String]+ -> IO ExitCode+rawSystem z =+ fmap fromExitCode . P.rawSystem z++-- | Waits for the specified process to terminate, and returns its exit code.++-- GHC Note: in order to call @waitForProcess@ without blocking all the+-- other threads in the system, you must compile the program with+-- @-threaded@.+waitForProcess ::+ P.ProcessHandle+ -> IO ExitCode+waitForProcess =+ fmap fromExitCode . P.waitForProcess+++-- | This is a non-blocking version of 'waitForProcess'. If the process is+-- still running, 'Nothing' is returned. If the process has exited, then+-- @'Just' e@ is returned where @e@ is the exit code of the process.+getProcessExitCode ::+ P.ProcessHandle+ -> IO (Maybe ExitCode)+getProcessExitCode =+ (fmap . fmap) fromExitCode . P.getProcessExitCode++-- not exported++toExitCode ::+ ExitCode+ -> E.ExitCode+toExitCode (ExitCode n) =+ if n == 0 then E.ExitSuccess else E.ExitFailure n++fromExitCode ::+ E.ExitCode+ -> ExitCode+fromExitCode E.ExitSuccess =+ success+fromExitCode (E.ExitFailure n) =+ exitCode n