packages feed

effectful-zoo-0.0.3.0: components/core/Effectful/Zoo/Process.hs

module Effectful.Zoo.Process
  ( IO.CreateProcess(..),
    IO.CmdSpec(..),
    IO.StdStream(..),
    Handle,
    ProcessHandle,
    ExitCode(..),
    FD,
    Pid,
    createProcess,
    createProcess_,
    IO.shell,
    IO.proc,
    callProcess,
    callCommand,
    spawnProcess,
    spawnCommand,
    readCreateProcess,
    readProcess,
    readCreateProcessWithExitCode,
    readProcessWithExitCode,
    cleanupProcess,
    getPid,
    getCurrentPid,
    interruptProcessGroupOf,
    createPipe,
    createPipeFd,
    runProcess,
    runCommand,
    runInteractiveProcess,
    runInteractiveCommand,
    system,
    rawSystem,

    waitSecondsForProcess,
  ) where

import Control.Exception qualified as CE
import HaskellWorks.Error
import HaskellWorks.Error.Types
import HaskellWorks.IO.Process qualified as IO
import HaskellWorks.Prelude
import Effectful
import Effectful.Zoo.Core
import Effectful.Zoo.Error.Static
import System.Exit (ExitCode (..))
import System.Posix.Internals (FD)
import System.Process (Pid, ProcessHandle)
import System.Process qualified as IO

createProcess :: ()
  => r <: Error IOException
  => r <: IOE
  => IO.CreateProcess
  -> Eff r (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
createProcess cp = do
  r <- liftIO $ CE.try @IOException $ IO.createProcess cp
  fromEither r

createProcess_ :: ()
  => r <: Error IOException
  => r <: IOE
  => String
  -> IO.CreateProcess
  -> Eff r (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
createProcess_ cmd cp = do
  r <- liftIO $ CE.try @IOException $ IO.createProcess_ cmd cp
  fromEither r

callProcess :: ()
  => r <: Error IOException
  => r <: IOE
  => String
  -> [String]
  -> Eff r ()
callProcess cmd args = do
  r <- liftIO $ CE.try @IOException $ IO.callProcess cmd args
  fromEither r

callCommand :: ()
  => r <: Error IOException
  => r <: IOE
  => String
  -> Eff r ()
callCommand cmd = do
  r <- liftIO $ CE.try @IOException $ IO.callCommand cmd
  fromEither r

spawnProcess :: ()
  => r <: Error IOException
  => r <: IOE
  => String
  -> [String]
  -> Eff r ProcessHandle
spawnProcess cmd args = do
  r <- liftIO $ CE.try @IOException $ IO.spawnProcess cmd args
  fromEither r

spawnCommand :: ()
  => r <: Error IOException
  => r <: IOE
  => String
  -> Eff r ProcessHandle
spawnCommand cmd = do
  r <- liftIO $ CE.try @IOException $ IO.spawnCommand cmd
  fromEither r

readCreateProcess :: ()
  => r <: Error IOException
  => r <: IOE
  => IO.CreateProcess
  -> String
  -> Eff r String
readCreateProcess cp input = do
  r <- liftIO $ CE.try @IOException $ IO.readCreateProcess cp input
  fromEither r

readProcess :: ()
  => r <: Error IOException
  => r <: IOE
  => String
  -> [String]
  -> String
  -> Eff r String
readProcess cmd args input = do
  r <- liftIO $ CE.try @IOException $ IO.readProcess cmd args input
  fromEither r

readCreateProcessWithExitCode :: ()
  => r <: Error IOException
  => r <: IOE
  => IO.CreateProcess
  -> String
  -> Eff r (ExitCode, String, String)
readCreateProcessWithExitCode cp input = do
  r <- liftIO $ CE.try @IOException $ IO.readCreateProcessWithExitCode cp input
  fromEither r

readProcessWithExitCode :: ()
  => r <: Error IOException
  => r <: IOE
  => String
  -> [String]
  -> String
  -> Eff r (ExitCode, String, String)
readProcessWithExitCode cmd args input = do
  r <- liftIO $ CE.try @IOException $ IO.readProcessWithExitCode cmd args input
  fromEither r

cleanupProcess :: ()
  => r <: Error IOException
  => r <: IOE
  => (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
  -> Eff r ()
cleanupProcess (mIn, mOut, mErr, ph) = do
  r <- liftIO $ CE.try @IOException $ IO.cleanupProcess (mIn, mOut, mErr, ph)
  fromEither r

getPid :: ()
  => r <: Error IOException
  => r <: IOE
  => ProcessHandle
  -> Eff r (Maybe Pid)
getPid ph = do
  r <- liftIO $ CE.try @IOException $ IO.getPid ph
  fromEither r

getCurrentPid :: ()
  => r <: Error IOException
  => r <: IOE
  => Eff r Pid
getCurrentPid = do
  r <- liftIO $ CE.try @IOException $ IO.getCurrentPid
  fromEither r

interruptProcessGroupOf :: ()
  => r <: Error IOException
  => r <: IOE
  => ProcessHandle
  -> Eff r ()
interruptProcessGroupOf ph = do
  r <- liftIO $ CE.try @IOException $ IO.interruptProcessGroupOf ph
  fromEither r

createPipe :: ()
  => r <: Error IOException
  => r <: IOE
  => Eff r (Handle, Handle)
createPipe = do
  r <- liftIO $ CE.try @IOException $ IO.createPipe
  fromEither r

createPipeFd :: ()
  => r <: Error IOException
  => r <: IOE
  => Eff r (FD, FD)
createPipeFd = do
  r <- liftIO $ CE.try @IOException $ IO.createPipeFd
  fromEither r

runProcess :: ()
  => r <: Error IOException
  => r <: IOE
  => FilePath
  -> [String]
  -> Maybe FilePath
  -> Maybe [(String, String)]
  -> Maybe Handle
  -> Maybe Handle
  -> Maybe Handle
  -> Eff r ProcessHandle
runProcess cmd args mbStdIn mbEnv mbCwd mbStdOut mbStdErr = do
  r <- liftIO $ CE.try @IOException $ IO.runProcess cmd args mbStdIn mbEnv mbCwd mbStdOut mbStdErr
  fromEither r

runCommand :: ()
  => r <: Error IOException
  => r <: IOE
  => String
  -> Eff r ProcessHandle
runCommand cmd = do
  r <- liftIO $ CE.try @IOException $ IO.runCommand cmd
  fromEither r

runInteractiveProcess :: ()
  => r <: Error IOException
  => r <: IOE
  => FilePath
  -> [String]
  -> Maybe FilePath
  -> Maybe [(String, String)]
  -> Eff r (Handle, Handle, Handle, ProcessHandle)
runInteractiveProcess cmd args mbCwd mbEnv = do
  r <- liftIO $ CE.try @IOException $ IO.runInteractiveProcess cmd args mbCwd mbEnv
  fromEither r

runInteractiveCommand :: ()
  => r <: Error IOException
  => r <: IOE
  => String
  -> Eff r (Handle, Handle, Handle, ProcessHandle)
runInteractiveCommand cmd = do
  r <- liftIO $ CE.try @IOException $ IO.runInteractiveCommand cmd
  fromEither r

system :: ()
  => r <: Error IOException
  => r <: IOE
  => String
  -> Eff r ExitCode
system cmd = do
  r <- liftIO $ CE.try @IOException $ IO.system cmd
  fromEither r

rawSystem :: ()
  => r <: Error IOException
  => r <: IOE
  => String
  -> [String]
  -> Eff r ExitCode
rawSystem cmd args = do
  r <- liftIO $ CE.try @IOException $ IO.rawSystem cmd args
  fromEither r

waitSecondsForProcess :: ()
  => r <: Error TimedOut
  => r <: IOE
  => Int
  -> ProcessHandle
  -> Eff r (Maybe ExitCode)
waitSecondsForProcess seconds hProcess =
  liftIO (IO.waitSecondsForProcess seconds hProcess)
    & onLeftM @TimedOut throw