<commit_before>{-# 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
, traverseExitCodes
  -- * 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.<commit_msg>hlint<commit_after>{-# 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
, traverseExitCodes
  -- * 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 Control.Monad
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
     when (isSuccess a') (void b) -- 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.
{'fraction_non_alphanumeric': 0.11295748802120502, 'fraction_numerical': 0.0016311550616780507, 'mean_word_length': 3.156779661016949, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 91, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6500660', 'n_tokens_mistral': 3086, 'n_tokens_neox': 3003, 'n_words': 1206}