@@ -0,0 +1,184 @@
3+module Effectful.Process
8+ -- * Running sub-processes
13+ , P.CreateProcess(..)
18+ -- ** Simpler functions for common tasks
25+ , readCreateProcessWithExitCode
26+ , readProcessWithExitCode
30+ -- ** Related utilities
31+ , P.showCommandForUser
34+#if MIN_VERSION_process(1,6,12)
38+ -- * Process completion
42+ , interruptProcessGroupOf
44+ -- * Interprocess communication
49+import System.Exit (ExitCode)
50+import System.IO (Handle)
51+import System.Posix.Internals (FD)
52+import qualified System.Process as P
54+import Effectful.Internal.Effect
55+import Effectful.Internal.Monad
57+-- | An effect for running child processes using the @process@ library.
58+data Process :: Effect where
59+ Process :: Process m r
61+runProcess :: IOE :> es => Eff (Process : es) a -> Eff es a
62+runProcess = evalEffect (IdE Process)
64+----------------------------------------
65+-- Running sub-processes
67+-- | Lifted 'P.createProcess'.
71+ -> Eff es (Maybe Handle, Maybe Handle, Maybe Handle, P.ProcessHandle)
72+createProcess = unsafeEff_ . P.createProcess
74+-- | Lifted 'P.createProcess_'.
79+ -> Eff es (Maybe Handle, Maybe Handle, Maybe Handle, P.ProcessHandle)
80+createProcess_ msg = unsafeEff_ . P.createProcess_ msg
82+----------------------------------------
83+-- Simpler functions for common tasks
85+-- | Lifted 'P.callProcess'.
86+callProcess :: Process :> es => FilePath -> [String] -> Eff es ()
87+callProcess fp = unsafeEff_ . P.callProcess fp
89+-- | Lifted 'P.callCommand'.
90+callCommand :: Process :> es => String -> Eff es ()
91+callCommand = unsafeEff_ . P.callCommand
93+-- | Lifted 'P.spawnProcess'.
94+spawnProcess :: Process :> es => FilePath -> [String] -> Eff es P.ProcessHandle
95+spawnProcess fp = unsafeEff_ . P.spawnProcess fp
97+-- | Lifted 'P.spawnCommand'.
98+spawnCommand :: Process :> es => String -> Eff es P.ProcessHandle
99+spawnCommand = unsafeEff_ . P.spawnCommand
101+-- | Lifted 'P.readCreateProcess'.
102+readCreateProcess :: Process :> es => P.CreateProcess -> String -> Eff es String
103+readCreateProcess cp = unsafeEff_ . P.readCreateProcess cp
105+-- | Lifted 'P.readProcess'.
106+readProcess :: Process :> es => FilePath -> [String] -> String -> Eff es String
107+readProcess fp args = unsafeEff_ . P.readProcess fp args
109+-- | Lifted 'P.readCreateProcessWithExitCode'.
110+readCreateProcessWithExitCode
114+ -> Eff es (ExitCode, String, String)
115+readCreateProcessWithExitCode cp = unsafeEff_ . P.readCreateProcessWithExitCode cp
117+-- | Lifted 'P.readProcessWithExitCode'.
118+readProcessWithExitCode
123+ -> Eff es (ExitCode, String, String)
124+readProcessWithExitCode fp args = unsafeEff_ . P.readProcessWithExitCode fp args
126+-- | Lifted 'P.withCreateProcess'.
130+ -> (Maybe Handle -> Maybe Handle -> Maybe Handle -> P.ProcessHandle -> Eff es a)
132+withCreateProcess cp cb = unsafeEff $ \es ->
133+ unsafeSeqUnliftEff es $ \runInIO ->
134+ P.withCreateProcess cp (\inh outh errh ph -> runInIO $ cb inh outh errh ph)
136+-- | Lifted 'P.cleanupProcess'.
139+ => (Maybe Handle, Maybe Handle, Maybe Handle, P.ProcessHandle)
141+cleanupProcess = unsafeEff_ . P.cleanupProcess
143+----------------------------------------
146+-- | Lifted 'P.getPid'.
147+getPid :: Process :> es => P.ProcessHandle -> Eff es (Maybe P.Pid)
148+getPid = unsafeEff_ . P.getPid
150+#if MIN_VERSION_process(1,6,12)
151+-- | Lifted 'P.getCurrentPid'.
152+getCurrentPid :: Process :> es => Eff es P.Pid
153+getCurrentPid = unsafeEff_ P.getCurrentPid
156+----------------------------------------
157+-- Process completion
159+-- | Lifted 'P.waitForProcess'.
160+waitForProcess :: Process :> es => P.ProcessHandle -> Eff es ExitCode
161+waitForProcess = unsafeEff_ . P.waitForProcess
163+-- | Lifted 'P.getProcessExitCode'.
164+getProcessExitCode :: Process :> es => P.ProcessHandle -> Eff es (Maybe ExitCode)
165+getProcessExitCode = unsafeEff_ . P.getProcessExitCode
167+-- | Lifted 'P.terminateProcess'.
168+terminateProcess :: Process :> es => P.ProcessHandle -> Eff es ()
169+terminateProcess = unsafeEff_ . P.terminateProcess
171+-- | Lifted 'P.interruptProcessGroupOf'.
172+interruptProcessGroupOf :: Process :> es => P.ProcessHandle -> Eff es ()
173+interruptProcessGroupOf = unsafeEff_ . P.interruptProcessGroupOf
175+----------------------------------------
176+-- Interprocess communication
178+-- | Lifted 'P.createPipe'.
179+createPipe :: Process :> es => Eff es (Handle, Handle)
180+createPipe = unsafeEff_ P.createPipe
182+-- | Lifted 'P.createPipeFd'.
183+createPipeFd :: Process :> es => Eff es (FD, FD)
184+createPipeFd = unsafeEff_ P.createPipeFd