packages feed

polysemy-process 0.8.0.1 → 0.9.0.0

raw patch · 15 files changed

+470/−172 lines, 15 filesdep ~basedep ~incipit-coredep ~polysemy-concPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base, incipit-core, polysemy-conc, polysemy-resume, polysemy-test, polysemy-time

API changes (from Hackage documentation)

- Polysemy.Process: [RecvError] :: Process i o e m e
- Polysemy.Process: [Recv] :: Process i o e m o
- Polysemy.Process: [Send] :: i -> Process i o e m ()
- Polysemy.Process: recvError :: forall i o e r. Member (Process i o e) r => Sem r e
- Polysemy.Process.Effect.Process: [RecvError] :: Process i o e m e
- Polysemy.Process.Effect.Process: recvError :: forall i o e r. Member (Process i o e) r => Sem r e
+ Polysemy.Process: Done :: a -> ByteString -> ProcessOutputParseResult a
+ Polysemy.Process: Fail :: Text -> ProcessOutputParseResult a
+ Polysemy.Process: Partial :: (ByteString -> ProcessOutputParseResult a) -> ProcessOutputParseResult a
+ Polysemy.Process: Stderr :: OutputPipe
+ Polysemy.Process: Stdout :: OutputPipe
+ Polysemy.Process: [$sel:continue:Done] :: ProcessOutputParseResult a -> ByteString -> ProcessOutputParseResult a
+ Polysemy.Process: [$sel:error:Done] :: ProcessOutputParseResult a -> Text
+ Polysemy.Process: [$sel:leftover:Done] :: ProcessOutputParseResult a -> ByteString
+ Polysemy.Process: [$sel:value:Done] :: ProcessOutputParseResult a -> a
+ Polysemy.Process: data OutputPipe
+ Polysemy.Process: data ProcessInput a :: Effect
+ Polysemy.Process: data ProcessOutputParseResult a
+ Polysemy.Process: interpretInputHandle :: Member (Embed IO) r => Handle -> InterpreterFor (Input ByteString !! ProcessError) r
+ Polysemy.Process: interpretInputHandleBuffered :: Member (Embed IO) r => Handle -> InterpreterFor (Input ByteString !! ProcessError) r
+ Polysemy.Process: interpretInputOutputProcess :: forall i o r. Member (Process i o) r => InterpretersFor [Input o, Output i] r
+ Polysemy.Process: interpretOutputHandle :: Member (Embed IO) r => Handle -> InterpreterFor (Output ByteString !! ProcessError) r
+ Polysemy.Process: interpretOutputHandleBuffered :: Member (Embed IO) r => Handle -> InterpreterFor (Output ByteString !! ProcessError) r
+ Polysemy.Process: interpretProcessCurrent :: Members [ProcessInput i, ProcessOutput 'Stdout o, Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Process i o !! ProcessError) r
+ Polysemy.Process: interpretProcessHandles :: forall i o r. Members [ProcessInput i, ProcessOutput 'Stdout o, Resource, Race, Async, Embed IO] r => ProcessOptions -> Handle -> Handle -> InterpreterFor (Process i o !! ProcessError) r
+ Polysemy.Process: interpretProcessIO :: forall i o ie oe r. Members [Input ByteString !! ie, Output ByteString !! oe] r => Members [ProcessInput i, ProcessOutput 'Stdout o, Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Process i o !! ProcessError) r
+ Polysemy.Process: interpretProcessInputId :: InterpreterFor (ProcessInput ByteString) r
+ Polysemy.Process: interpretProcessInputText :: InterpreterFor (ProcessInput Text) r
+ Polysemy.Process: interpretProcessOutputIgnore :: forall p a r. InterpreterFor (ProcessOutput p a) r
+ Polysemy.Process: interpretProcessOutputIncremental :: forall p a r. (ByteString -> ProcessOutputParseResult a) -> InterpreterFor (ProcessOutput p (Either Text a)) r
+ Polysemy.Process: interpretProcessOutputLeft :: forall p a b r. Member (ProcessOutput p a) r => InterpreterFor (ProcessOutput p (Either a b)) r
+ Polysemy.Process: interpretProcessOutputRight :: forall p a b r. Member (ProcessOutput p b) r => InterpreterFor (ProcessOutput p (Either a b)) r
+ Polysemy.Process.Data.ProcessOutputParseResult: Done :: a -> ByteString -> ProcessOutputParseResult a
+ Polysemy.Process.Data.ProcessOutputParseResult: Fail :: Text -> ProcessOutputParseResult a
+ Polysemy.Process.Data.ProcessOutputParseResult: Partial :: (ByteString -> ProcessOutputParseResult a) -> ProcessOutputParseResult a
+ Polysemy.Process.Data.ProcessOutputParseResult: [$sel:continue:Done] :: ProcessOutputParseResult a -> ByteString -> ProcessOutputParseResult a
+ Polysemy.Process.Data.ProcessOutputParseResult: [$sel:error:Done] :: ProcessOutputParseResult a -> Text
+ Polysemy.Process.Data.ProcessOutputParseResult: [$sel:leftover:Done] :: ProcessOutputParseResult a -> ByteString
+ Polysemy.Process.Data.ProcessOutputParseResult: [$sel:value:Done] :: ProcessOutputParseResult a -> a
+ Polysemy.Process.Data.ProcessOutputParseResult: data ProcessOutputParseResult a
+ Polysemy.Process.Data.ProcessOutputParseResult: instance GHC.Show.Show a => GHC.Show.Show (Polysemy.Process.Data.ProcessOutputParseResult.ProcessOutputParseResult a)
+ Polysemy.Process.Effect.ProcessInput: [Encode] :: a -> ProcessInput a m ByteString
+ Polysemy.Process.Effect.ProcessInput: data ProcessInput a :: Effect
+ Polysemy.Process.Effect.ProcessOutput: Stderr :: OutputPipe
+ Polysemy.Process.Effect.ProcessOutput: Stdout :: OutputPipe
+ Polysemy.Process.Effect.ProcessOutput: data OutputPipe
+ Polysemy.Process.Effect.ProcessOutput: instance GHC.Classes.Eq Polysemy.Process.Effect.ProcessOutput.OutputPipe
+ Polysemy.Process.Effect.ProcessOutput: instance GHC.Show.Show Polysemy.Process.Effect.ProcessOutput.OutputPipe
+ Polysemy.Process.Interpreter.Process: interpretInputHandle :: Member (Embed IO) r => Handle -> InterpreterFor (Input ByteString !! ProcessError) r
+ Polysemy.Process.Interpreter.Process: interpretInputHandleBuffered :: Member (Embed IO) r => Handle -> InterpreterFor (Input ByteString !! ProcessError) r
+ Polysemy.Process.Interpreter.Process: interpretInputOutputProcess :: forall i o r. Member (Process i o) r => InterpretersFor [Input o, Output i] r
+ Polysemy.Process.Interpreter.Process: interpretOutputHandle :: Member (Embed IO) r => Handle -> InterpreterFor (Output ByteString !! ProcessError) r
+ Polysemy.Process.Interpreter.Process: interpretOutputHandleBuffered :: Member (Embed IO) r => Handle -> InterpreterFor (Output ByteString !! ProcessError) r
+ Polysemy.Process.Interpreter.Process: interpretProcessCurrent :: Members [ProcessInput i, ProcessOutput 'Stdout o, Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Process i o !! ProcessError) r
+ Polysemy.Process.Interpreter.Process: interpretProcessHandles :: forall i o r. Members [ProcessInput i, ProcessOutput 'Stdout o, Resource, Race, Async, Embed IO] r => ProcessOptions -> Handle -> Handle -> InterpreterFor (Process i o !! ProcessError) r
+ Polysemy.Process.Interpreter.Process: interpretProcessIO :: forall i o ie oe r. Members [Input ByteString !! ie, Output ByteString !! oe] r => Members [ProcessInput i, ProcessOutput 'Stdout o, Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Process i o !! ProcessError) r
+ Polysemy.Process.Interpreter.ProcessInput: interpretProcessInputId :: InterpreterFor (ProcessInput ByteString) r
+ Polysemy.Process.Interpreter.ProcessInput: interpretProcessInputText :: InterpreterFor (ProcessInput Text) r
+ Polysemy.Process.Interpreter.ProcessOutput: interpretProcessOutputIgnore :: forall p a r. InterpreterFor (ProcessOutput p a) r
+ Polysemy.Process.Interpreter.ProcessOutput: interpretProcessOutputIncremental :: forall p a r. (ByteString -> ProcessOutputParseResult a) -> InterpreterFor (ProcessOutput p (Either Text a)) r
+ Polysemy.Process.Interpreter.ProcessOutput: interpretProcessOutputLeft :: forall p a b r. Member (ProcessOutput p a) r => InterpreterFor (ProcessOutput p (Either a b)) r
+ Polysemy.Process.Interpreter.ProcessOutput: interpretProcessOutputRight :: forall p a b r. Member (ProcessOutput p b) r => InterpreterFor (ProcessOutput p (Either a b)) r
+ Polysemy.Process.Interpreter.ProcessOutput: parseMany :: Parser a -> Maybe (Parser a) -> ByteString -> (Maybe (Parser a), ([Either Text a], ByteString))
- Polysemy.Process: data Process i o e :: Effect
+ Polysemy.Process: data Process i o :: Effect
- Polysemy.Process: data ProcessOutput a :: Effect
+ Polysemy.Process: data ProcessOutput (p :: OutputPipe) a :: Effect
- Polysemy.Process: interpretProcess :: forall resource err o e r. Member (Scoped resource (SystemProcess !! err)) r => Members [ProcessOutput o, ProcessOutput e, Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Scoped () (Process ByteString o e) !! ProcessError) r
+ Polysemy.Process: interpretProcess :: forall resource err i o r. Member (Scoped resource (SystemProcess !! err)) r => Members [ProcessOutput 'Stdout o, ProcessOutput 'Stderr o, ProcessInput i, Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Scoped () (Process i o) !! ProcessError) r
- Polysemy.Process: interpretProcessByteString :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r
+ Polysemy.Process: interpretProcessByteString :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Scoped () (Process ByteString ByteString) !! ProcessError) r
- Polysemy.Process: interpretProcessByteStringLines :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r
+ Polysemy.Process: interpretProcessByteStringLines :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Scoped () (Process ByteString ByteString) !! ProcessError) r
- Polysemy.Process: interpretProcessByteStringLinesNative :: Members [Resource, Race, Async, Embed IO] r => ProcessOptions -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r
+ Polysemy.Process: interpretProcessByteStringLinesNative :: Members [Resource, Race, Async, Embed IO] r => ProcessOptions -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString ByteString) !! ProcessError) r
- Polysemy.Process: interpretProcessByteStringNative :: Members [Resource, Race, Async, Embed IO] r => ProcessOptions -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r
+ Polysemy.Process: interpretProcessByteStringNative :: Members [Resource, Race, Async, Embed IO] r => ProcessOptions -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString ByteString) !! ProcessError) r
- Polysemy.Process: interpretProcessOutputId :: InterpreterFor (ProcessOutput ByteString) r
+ Polysemy.Process: interpretProcessOutputId :: forall p r. InterpreterFor (ProcessOutput p ByteString) r
- Polysemy.Process: interpretProcessOutputLines :: InterpreterFor (ProcessOutput ByteString) r
+ Polysemy.Process: interpretProcessOutputLines :: forall p r. InterpreterFor (ProcessOutput p ByteString) r
- Polysemy.Process: interpretProcessOutputText :: InterpreterFor (ProcessOutput Text) r
+ Polysemy.Process: interpretProcessOutputText :: forall p r. InterpreterFor (ProcessOutput p Text) r
- Polysemy.Process: interpretProcessOutputTextLines :: InterpreterFor (ProcessOutput Text) r
+ Polysemy.Process: interpretProcessOutputTextLines :: forall p r. InterpreterFor (ProcessOutput p Text) r
- Polysemy.Process: interpretProcessText :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r
+ Polysemy.Process: interpretProcessText :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Scoped () (Process Text Text) !! ProcessError) r
- Polysemy.Process: interpretProcessTextLines :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r
+ Polysemy.Process: interpretProcessTextLines :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Scoped () (Process Text Text) !! ProcessError) r
- Polysemy.Process: interpretProcessTextLinesNative :: Members [Resource, Race, Async, Embed IO] r => ProcessOptions -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r
+ Polysemy.Process: interpretProcessTextLinesNative :: Members [Resource, Race, Async, Embed IO] r => ProcessOptions -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process Text Text) !! ProcessError) r
- Polysemy.Process: interpretProcessTextNative :: Members [Resource, Race, Async, Embed IO] r => ProcessOptions -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r
+ Polysemy.Process: interpretProcessTextNative :: Members [Resource, Race, Async, Embed IO] r => ProcessOptions -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process Text Text) !! ProcessError) r
- Polysemy.Process: recv :: forall i o e r. Member (Process i o e) r => Sem r o
+ Polysemy.Process: recv :: forall i o r. Member (Process i o) r => Sem r o
- Polysemy.Process: send :: forall i o e r. Member (Process i o e) r => i -> Sem r ()
+ Polysemy.Process: send :: forall i o r. Member (Process i o) r => i -> Sem r ()
- Polysemy.Process: withProcess :: forall resource i o e r. Member (Scoped resource (Process i o e)) r => InterpreterFor (Process i o e) r
+ Polysemy.Process: withProcess :: forall resource i o r. Member (Scoped resource (Process i o)) r => InterpreterFor (Process i o) r
- Polysemy.Process.Effect.Process: [Recv] :: Process i o e m o
+ Polysemy.Process.Effect.Process: [Recv] :: Process i o m o
- Polysemy.Process.Effect.Process: [Send] :: i -> Process i o e m ()
+ Polysemy.Process.Effect.Process: [Send] :: i -> Process i o m ()
- Polysemy.Process.Effect.Process: data Process i o e :: Effect
+ Polysemy.Process.Effect.Process: data Process i o :: Effect
- Polysemy.Process.Effect.Process: recv :: forall i o e r. Member (Process i o e) r => Sem r o
+ Polysemy.Process.Effect.Process: recv :: forall i o r. Member (Process i o) r => Sem r o
- Polysemy.Process.Effect.Process: runProcessIO :: forall i o e err r. Member (Process i o e !! err) r => InterpretersFor [Output i !! err, Input o !! err] r
+ Polysemy.Process.Effect.Process: runProcessIO :: forall i o err r. Member (Process i o !! err) r => InterpretersFor [Output i !! err, Input o !! err] r
- Polysemy.Process.Effect.Process: send :: forall i o e r. Member (Process i o e) r => i -> Sem r ()
+ Polysemy.Process.Effect.Process: send :: forall i o r. Member (Process i o) r => i -> Sem r ()
- Polysemy.Process.Effect.Process: withProcess :: forall resource i o e r. Member (Scoped resource (Process i o e)) r => InterpreterFor (Process i o e) r
+ Polysemy.Process.Effect.Process: withProcess :: forall resource i o r. Member (Scoped resource (Process i o)) r => InterpreterFor (Process i o) r
- Polysemy.Process.Effect.ProcessOutput: [Chunk] :: ByteString -> ByteString -> ProcessOutput a m ([a], ByteString)
+ Polysemy.Process.Effect.ProcessOutput: [Chunk] :: ByteString -> ByteString -> ProcessOutput p a m ([a], ByteString)
- Polysemy.Process.Effect.ProcessOutput: data ProcessOutput a :: Effect
+ Polysemy.Process.Effect.ProcessOutput: data ProcessOutput (p :: OutputPipe) a :: Effect
- Polysemy.Process.Interpreter.Process: interpretProcess :: forall resource err o e r. Member (Scoped resource (SystemProcess !! err)) r => Members [ProcessOutput o, ProcessOutput e, Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Scoped () (Process ByteString o e) !! ProcessError) r
+ Polysemy.Process.Interpreter.Process: interpretProcess :: forall resource err i o r. Member (Scoped resource (SystemProcess !! err)) r => Members [ProcessOutput 'Stdout o, ProcessOutput 'Stderr o, ProcessInput i, Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Scoped () (Process i o) !! ProcessError) r
- Polysemy.Process.Interpreter.Process: interpretProcessByteString :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r
+ Polysemy.Process.Interpreter.Process: interpretProcessByteString :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Scoped () (Process ByteString ByteString) !! ProcessError) r
- Polysemy.Process.Interpreter.Process: interpretProcessByteStringLines :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r
+ Polysemy.Process.Interpreter.Process: interpretProcessByteStringLines :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Scoped () (Process ByteString ByteString) !! ProcessError) r
- Polysemy.Process.Interpreter.Process: interpretProcessText :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r
+ Polysemy.Process.Interpreter.Process: interpretProcessText :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Scoped () (Process Text Text) !! ProcessError) r
- Polysemy.Process.Interpreter.Process: interpretProcessTextLines :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r
+ Polysemy.Process.Interpreter.Process: interpretProcessTextLines :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Scoped () (Process Text Text) !! ProcessError) r
- Polysemy.Process.Interpreter.ProcessOutput: interpretProcessOutputId :: InterpreterFor (ProcessOutput ByteString) r
+ Polysemy.Process.Interpreter.ProcessOutput: interpretProcessOutputId :: forall p r. InterpreterFor (ProcessOutput p ByteString) r
- Polysemy.Process.Interpreter.ProcessOutput: interpretProcessOutputLines :: InterpreterFor (ProcessOutput ByteString) r
+ Polysemy.Process.Interpreter.ProcessOutput: interpretProcessOutputLines :: forall p r. InterpreterFor (ProcessOutput p ByteString) r
- Polysemy.Process.Interpreter.ProcessOutput: interpretProcessOutputText :: InterpreterFor (ProcessOutput Text) r
+ Polysemy.Process.Interpreter.ProcessOutput: interpretProcessOutputText :: forall p r. InterpreterFor (ProcessOutput p Text) r
- Polysemy.Process.Interpreter.ProcessOutput: interpretProcessOutputTextLines :: InterpreterFor (ProcessOutput Text) r
+ Polysemy.Process.Interpreter.ProcessOutput: interpretProcessOutputTextLines :: forall p r. InterpreterFor (ProcessOutput p Text) r
- Polysemy.Process.Interpreter.ProcessStdio: interpretProcessByteStringLinesNative :: Members [Resource, Race, Async, Embed IO] r => ProcessOptions -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r
+ Polysemy.Process.Interpreter.ProcessStdio: interpretProcessByteStringLinesNative :: Members [Resource, Race, Async, Embed IO] r => ProcessOptions -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString ByteString) !! ProcessError) r
- Polysemy.Process.Interpreter.ProcessStdio: interpretProcessByteStringNative :: Members [Resource, Race, Async, Embed IO] r => ProcessOptions -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r
+ Polysemy.Process.Interpreter.ProcessStdio: interpretProcessByteStringNative :: Members [Resource, Race, Async, Embed IO] r => ProcessOptions -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString ByteString) !! ProcessError) r
- Polysemy.Process.Interpreter.ProcessStdio: interpretProcessTextLinesNative :: Members [Resource, Race, Async, Embed IO] r => ProcessOptions -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r
+ Polysemy.Process.Interpreter.ProcessStdio: interpretProcessTextLinesNative :: Members [Resource, Race, Async, Embed IO] r => ProcessOptions -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process Text Text) !! ProcessError) r
- Polysemy.Process.Interpreter.ProcessStdio: interpretProcessTextNative :: Members [Resource, Race, Async, Embed IO] r => ProcessOptions -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r
+ Polysemy.Process.Interpreter.ProcessStdio: interpretProcessTextNative :: Members [Resource, Race, Async, Embed IO] r => ProcessOptions -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process Text Text) !! ProcessError) r
- Polysemy.Process.ProcessOutput: [Chunk] :: ByteString -> ByteString -> ProcessOutput a m ([a], ByteString)
+ Polysemy.Process.ProcessOutput: [Chunk] :: ByteString -> ByteString -> ProcessOutput p a m ([a], ByteString)
- Polysemy.Process.ProcessOutput: data ProcessOutput a :: Effect
+ Polysemy.Process.ProcessOutput: data ProcessOutput (p :: OutputPipe) a :: Effect
- Polysemy.Process.ProcessOutput: interpretProcessOutputId :: InterpreterFor (ProcessOutput ByteString) r
+ Polysemy.Process.ProcessOutput: interpretProcessOutputId :: forall p r. InterpreterFor (ProcessOutput p ByteString) r
- Polysemy.Process.ProcessOutput: interpretProcessOutputLines :: InterpreterFor (ProcessOutput ByteString) r
+ Polysemy.Process.ProcessOutput: interpretProcessOutputLines :: forall p r. InterpreterFor (ProcessOutput p ByteString) r
- Polysemy.Process.ProcessOutput: interpretProcessOutputText :: InterpreterFor (ProcessOutput Text) r
+ Polysemy.Process.ProcessOutput: interpretProcessOutputText :: forall p r. InterpreterFor (ProcessOutput p Text) r
- Polysemy.Process.ProcessOutput: interpretProcessOutputTextLines :: InterpreterFor (ProcessOutput Text) r
+ Polysemy.Process.ProcessOutput: interpretProcessOutputTextLines :: forall p r. InterpreterFor (ProcessOutput p Text) r

Files

− changelog.md
@@ -1,16 +0,0 @@-# 0.8.0.0-* Add `ProcessOptions`, replacing the primitive parameters of `Process` interpreters.-* Add an option for `Process` that determines whether to kill the process after exiting the scope.--# 0.6.0.0--* Allow `Process` to emit custom chunks constructed by an interpreter of `ProcessOutput` instead of `ByteString`s-  containing whatever the `Handle` produced.-* Rename stdio interpreters.-* Add helper `resolveExecutable` that looks up names in `$PATH` and ensures the files are executable.-* Add effect `Pty` for interacting with pseudo terminals.-* Add low-level process abstraction effect, `SystemProcess`.--# 0.5.0.0--* Add the effect `Process`, wrapping `System.Process.Typed` using `Scoped`.
lib/Polysemy/Process.hs view
@@ -5,9 +5,8 @@    -- * Effects   -- ** Process-  Process (..),+  Process,   recv,-  recvError,   send,   withProcess,   ProcessOptions (ProcessOptions),@@ -15,7 +14,12 @@    -- ** ProcessOutput   ProcessOutput,+  OutputPipe (Stdout, Stderr),+  ProcessOutputParseResult (..), +  -- ** ProcessInput+  ProcessInput,+   -- ** SystemProcess   SystemProcess,   withSystemProcess,@@ -35,13 +39,29 @@   interpretProcessByteStringLines,   interpretProcessText,   interpretProcessTextLines,+  interpretInputOutputProcess,+  interpretInputHandleBuffered,+  interpretInputHandle,+  interpretOutputHandleBuffered,+  interpretOutputHandle,+  interpretProcessIO,+  interpretProcessHandles,+  interpretProcessCurrent,    -- ** ProcessOutput+  interpretProcessOutputIgnore,   interpretProcessOutputId,+  interpretProcessOutputLeft,+  interpretProcessOutputRight,   interpretProcessOutputLines,   interpretProcessOutputText,   interpretProcessOutputTextLines,+  interpretProcessOutputIncremental, +  -- ** ProcessInput+  interpretProcessInputId,+  interpretProcessInputText,+   -- ** SystemProcess   interpretSystemProcessWithProcess,   interpretSystemProcessNativeSingle,@@ -61,24 +81,36 @@  import Polysemy.Process.Data.ProcessKill (ProcessKill (..)) import Polysemy.Process.Data.ProcessOptions (ProcessOptions (ProcessOptions))-import Polysemy.Process.Effect.Process (Process (..), recv, recvError, send, withProcess)-import Polysemy.Process.Effect.ProcessOutput (ProcessOutput)+import Polysemy.Process.Data.ProcessOutputParseResult (ProcessOutputParseResult (..))+import Polysemy.Process.Effect.Process (Process (..), recv, send, withProcess)+import Polysemy.Process.Effect.ProcessInput (ProcessInput)+import Polysemy.Process.Effect.ProcessOutput (OutputPipe (Stderr, Stdout), ProcessOutput) import Polysemy.Process.Effect.Pty (Pty, withPty)-import Polysemy.Process.Effect.SystemProcess (-  SystemProcess,-  withSystemProcess,-  )+import Polysemy.Process.Effect.SystemProcess (SystemProcess, withSystemProcess) import Polysemy.Process.Executable (resolveExecutable) import Polysemy.Process.Interpreter.Process (+  interpretInputHandle,+  interpretInputHandleBuffered,+  interpretInputOutputProcess,+  interpretOutputHandle,+  interpretOutputHandleBuffered,   interpretProcess,   interpretProcessByteString,   interpretProcessByteStringLines,+  interpretProcessCurrent,+  interpretProcessHandles,+  interpretProcessIO,   interpretProcessText,   interpretProcessTextLines,   )+import Polysemy.Process.Interpreter.ProcessInput (interpretProcessInputId, interpretProcessInputText) import Polysemy.Process.Interpreter.ProcessOutput (   interpretProcessOutputId,+  interpretProcessOutputIgnore,+  interpretProcessOutputIncremental,+  interpretProcessOutputLeft,   interpretProcessOutputLines,+  interpretProcessOutputRight,   interpretProcessOutputText,   interpretProcessOutputTextLines,   )
+ lib/Polysemy/Process/Data/ProcessOutputParseResult.hs view
@@ -0,0 +1,21 @@+-- |A data type encoding the result of an incremental parser for process output.+module Polysemy.Process.Data.ProcessOutputParseResult where++import Text.Show (showParen, showString, showsPrec)++-- |An incremental parse result, potentially a partial result containing a continuation function.+data ProcessOutputParseResult a =+  Done { value :: a, leftover :: ByteString }+  |+  Partial { continue :: ByteString -> ProcessOutputParseResult a }+  |+  Fail { error :: Text }++instance Show a => Show (ProcessOutputParseResult a) where+  showsPrec d = \case+    Done {..} ->+      showParen (d > 10) (showString "Done { value = " <> showsPrec 11 value <> showString ", leftover = " <> showsPrec 11 leftover <> showString " }")+    Partial _ ->+      showString "Partial"+    Fail e ->+      showParen (d > 10) (showString "Fail { error = " <> showString (show e) <> showString " }")
lib/Polysemy/Process/Effect/Process.hs view
@@ -4,12 +4,12 @@ module Polysemy.Process.Effect.Process where  import Polysemy.Conc.Effect.Scoped (Scoped, scoped)+import Polysemy.Input (Input (Input))+import Polysemy.Output (Output (Output)) import Polysemy.Resume (interpretResumable, restop, type (!!)) import Prelude hiding (send)-import Polysemy.Input (Input(Input))-import Polysemy.Output (Output(Output)) --- |Abstraction of a process with stdin/stdout/stderr.+-- |Abstraction of a process with input and output. -- -- This effect is intended to be used in a scoped manner: --@@ -19,7 +19,7 @@ -- import Polysemy.Process -- import qualified System.Process.Typed as System ----- prog :: Member (Scoped resource (Process Text Text e !! err)) r => Sem r Text+-- prog :: Member (Scoped resource (Process Text Text !! err)) r => Sem r Text -- prog = --  resumeAs "failed" do --    withProcess do@@ -31,50 +31,43 @@ --   out <- runConc $ interpretProcessNative (System.proc "cat" []) prog --   putStrLn out -- @-data Process i o e :: Effect where-  Recv :: Process i o e m o-  RecvError :: Process i o e m e-  Send :: i -> Process i o e m ()+data Process i o :: Effect where+  Recv :: Process i o m o+  Send :: i -> Process i o m ()  makeSem_ ''Process --- |Obtain a chunk of stdout.+-- |Obtain a chunk of output. recv ::-  ∀ i o e r .-  Member (Process i o e) r =>+  ∀ i o r .+  Member (Process i o) r =>   Sem r o --- |Obtain a chunk of stderr.-recvError ::-  ∀ i o e r .-  Member (Process i o e) r =>-  Sem r e- -- |Send data to stdin. send ::-  ∀ i o e r .-  Member (Process i o e) r =>+  ∀ i o r .+  Member (Process i o) r =>   i ->   Sem r ()  -- |Create a scoped resource for 'Process'. withProcess ::-  ∀ resource i o e r .-  Member (Scoped resource (Process i o e)) r =>-  InterpreterFor (Process i o e) r+  ∀ resource i o r .+  Member (Scoped resource (Process i o)) r =>+  InterpreterFor (Process i o) r withProcess =   scoped @resource  -- |Convert 'Output' and 'Input' to 'Process'. runProcessIO ::-  ∀ i o e err r .-  Member (Process i o e !! err) r =>+  ∀ i o err r .+  Member (Process i o !! err) r =>   InterpretersFor [Output i !! err, Input o !! err] r runProcessIO =   interpretResumable \case     Input ->-      restop @err @(Process i o e) (recv @i @o @e)+      restop @err @(Process i o) (recv @i @o)   .   interpretResumable \case     Output o ->-      restop @err @(Process i o e) (send @i @o @e o)+      restop @err @(Process i o) (send @i @o o)
+ lib/Polysemy/Process/Effect/ProcessInput.hs view
@@ -0,0 +1,15 @@+{-# options_haddock prune #-}++-- |Description: ProcessInput effect, Internal.+module Polysemy.Process.Effect.ProcessInput where++-- |This effect is used by the effect 'Polysemy.Process.Process' to encode values for process input.+-- example using a parser.+data ProcessInput a :: Effect where+  -- |Encode a value for enqueueing it to a process' stdin.+  Encode ::+    -- |The value to encode.+    a ->+    ProcessInput a m ByteString++makeSem ''ProcessInput
lib/Polysemy/Process/Effect/ProcessOutput.hs view
@@ -3,11 +3,20 @@ -- |Description: ProcessOutput effect, Internal. module Polysemy.Process.Effect.ProcessOutput where +-- |Kind tag for selecting the 'ProcessOutput' handler for stdout/stderr.+data OutputPipe =+  -- |Tag for stdout.+  Stdout+  |+  -- |Tag for stderr.+  Stderr+  deriving stock (Eq, Show)+ -- |This effect is used by the effect 'Polysemy.Process.Process' to accumulate and decode chunks of 'ByteString's, for -- example using a parser. -- The interpreter may be stateful or stateless, since the constructor 'Chunk' is expected to be called with both the -- accumulated unprocessed output as well as the new chunk.-data ProcessOutput a :: Effect where+data ProcessOutput (p :: OutputPipe) a :: Effect where   -- |Add a chunk of output to the accumulator, returning any number of successfully parsed values and the leftover   -- output.   Chunk ::@@ -15,6 +24,6 @@     ByteString ->     -- |The new chunk read from the process.     ByteString ->-    ProcessOutput a m ([a], ByteString)+    ProcessOutput p a m ([a], ByteString)  makeSem ''ProcessOutput
lib/Polysemy/Process/Interpreter/Process.hs view
@@ -4,6 +4,7 @@ module Polysemy.Process.Interpreter.Process where  import Control.Concurrent.STM.TBMQueue (TBMQueue)+import Data.ByteString (hGetSome, hPut) import qualified Polysemy.Conc as Conc import Polysemy.Conc.Async (withAsync_) import qualified Polysemy.Conc.Data.QueueResult as QueueResult@@ -13,20 +14,27 @@ import Polysemy.Conc.Effect.Scoped (Scoped) import Polysemy.Conc.Interpreter.Queue.TBM (interpretQueueTBMWith, withTBMQueue) import Polysemy.Conc.Interpreter.Scoped (interpretScopedResumableWith_)-import Polysemy.Resume (Stop, resumeOr, resume_, stop, type (!!))+import Polysemy.Input (Input (Input))+import Polysemy.Output (Output (Output))+import Polysemy.Resume (Stop, interpretResumable, resumeOr, resume_, stop, stopNote, type (!!)) import Prelude hiding (fromException)+import System.IO (BufferMode (NoBuffering), Handle, hSetBuffering, stdin, stdout)  import Polysemy.Process.Data.ProcessError (ProcessError (Terminated)) import Polysemy.Process.Data.ProcessKill (ProcessKill (KillAfter, KillImmediately, KillNever)) import Polysemy.Process.Data.ProcessOptions (ProcessOptions (ProcessOptions)) import qualified Polysemy.Process.Effect.Process as Process import Polysemy.Process.Effect.Process (Process)+import qualified Polysemy.Process.Effect.ProcessInput as ProcessInput+import Polysemy.Process.Effect.ProcessInput (ProcessInput) import qualified Polysemy.Process.Effect.ProcessOutput as ProcessOutput-import Polysemy.Process.Effect.ProcessOutput (ProcessOutput)+import Polysemy.Process.Effect.ProcessOutput (OutputPipe (Stderr, Stdout), ProcessOutput) import qualified Polysemy.Process.Effect.SystemProcess as SystemProcess import Polysemy.Process.Effect.SystemProcess (SystemProcess, withSystemProcess)+import Polysemy.Process.Interpreter.ProcessInput (interpretProcessInputId, interpretProcessInputText) import Polysemy.Process.Interpreter.ProcessOutput (   interpretProcessOutputId,+  interpretProcessOutputIgnore,   interpretProcessOutputLines,   interpretProcessOutputText,   interpretProcessOutputTextLines,@@ -44,26 +52,24 @@   Err { unErr :: a }   deriving stock (Eq, Show) -data ProcessQueues o e =+data ProcessQueues i o =   ProcessQueues {-    pqIn :: TBMQueue (In ByteString),-    pqOut :: TBMQueue (Out o),-    pqErr :: TBMQueue (Err e)+    pqIn :: TBMQueue (In i),+    pqOut :: TBMQueue (Out o)   }  interpretQueues ::   Members [Resource, Race, Embed IO] r =>-  ProcessQueues o e ->-  InterpretersFor [Queue (In ByteString), Queue (Out o), Queue (Err e)] r-interpretQueues (ProcessQueues inQ outQ errQ) =-  interpretQueueTBMWith errQ .+  ProcessQueues i o ->+  InterpretersFor [Queue (In i), Queue (Out o)] r+interpretQueues (ProcessQueues inQ outQ) =   interpretQueueTBMWith outQ .   interpretQueueTBMWith inQ  handleProcessWithQueues ::-  ∀ o e m r a .-  Members [Queue (In ByteString), Queue (Out o), Queue (Err e), Stop ProcessError] r =>-  Process ByteString o e m a ->+  ∀ i o m r a .+  Members [Queue (In i), Queue (Out o), Stop ProcessError] r =>+  Process i o m a ->   Sem r a handleProcessWithQueues = \case   Process.Recv ->@@ -74,67 +80,59 @@         stop (Terminated "impossible: empty")       QueueResult.Success (Out msg) ->         pure msg-  Process.RecvError ->-    Queue.read >>= \case-      QueueResult.Closed ->-        stop (Terminated "closed")-      QueueResult.NotAvailable ->-        stop (Terminated "impossible: empty")-      QueueResult.Success (Err msg) ->-        pure msg   Process.Send msg -> do-    whenM (Queue.closed @(In ByteString)) (stop (Terminated "closed"))+    whenM (Queue.closed @(In i)) (stop (Terminated "closed"))     Queue.write (In msg)  withSTMResources ::-  ∀ o e r a .+  ∀ i o r a .   Members [Resource, Embed IO] r =>   Int ->-  (ProcessQueues o e -> Sem r a) ->+  (ProcessQueues i o -> Sem r a) ->   Sem r a withSTMResources qSize action = do   withTBMQueue qSize \ inQ ->     withTBMQueue qSize \ outQ ->-      withTBMQueue qSize \ errQ ->-        action (ProcessQueues inQ outQ errQ)+      action (ProcessQueues inQ outQ)  withQueues ::+  ∀ i o r .   Members [Race, Resource, Embed IO] r =>   Int ->-  InterpretersFor [Queue (In ByteString), Queue (Out o), Queue (Err e)] r+  InterpretersFor [Queue (In i), Queue (Out o)] r withQueues qSize action =   withSTMResources qSize \ qs -> interpretQueues qs action  outputQueue ::-  ∀ pipe chunk err r .-  Coercible (pipe chunk) chunk =>-  Members [SystemProcess !! err, ProcessOutput chunk, Queue (pipe chunk), Embed IO] r =>+  ∀ p chunk err eff r .+  Members [eff !! err, ProcessOutput p chunk, Queue (Out chunk), Embed IO] r =>   Bool ->-  Sem (SystemProcess : r) ByteString ->+  Sem (eff : r) ByteString ->   Sem r () outputQueue discardWhenFull readChunk = do   spin ""   where     spin buffer =-      resumeOr @err readChunk (write buffer) (const (Queue.close @(pipe chunk)))+      resumeOr @err readChunk (write buffer) (const (Queue.close @(Out chunk)))     write buffer msg = do-      (chunks, newBuffer) <- ProcessOutput.chunk buffer msg-      for_ chunks \ (coerce @chunk @(pipe chunk) -> c) ->+      (chunks, newBuffer) <- ProcessOutput.chunk @p @chunk buffer msg+      for_ chunks \ (Out -> c) ->         if discardWhenFull then void (Queue.tryWrite c) else Queue.write c       spin newBuffer  inputQueue ::-  ∀ err r .-  Members [SystemProcess !! err, Queue (In ByteString), Embed IO] r =>-  (ByteString -> Sem (SystemProcess : r) ()) ->+  ∀ i err eff r .+  Members [eff !! err, ProcessInput i, Queue (In i), Embed IO] r =>+  (ByteString -> Sem (eff : r) ()) ->   Sem r () inputQueue writeChunk =   spin   where     spin =-      Queue.read >>= \case-        QueueResult.Success (In msg) ->-          resumeOr @err (writeChunk msg) (const spin) (const (Queue.close @(In ByteString)))+      Queue.read @(In i) >>= \case+        QueueResult.Success (In msg) -> do+          bytes <- ProcessInput.encode msg+          resumeOr @err (writeChunk bytes) (const spin) (const (Queue.close @(In i)))         _ ->           unit @@ -161,78 +159,185 @@     void SystemProcess.pid     handleKill kill -type ScopeEffects o e err =-  [Queue (In ByteString), Queue (Out o), Queue (Err e), SystemProcess !! err]+type ScopeEffects i o err =+  [Queue (In i), Queue (Out o), SystemProcess !! err]  scope ::-  ∀ o e resource err r .+  ∀ i o resource err r .   Member (Scoped resource (SystemProcess !! err)) r =>-  Members [ProcessOutput e, ProcessOutput o, Resource, Race, Async, Embed IO] r =>+  Members [ProcessInput i, ProcessOutput 'Stdout o, ProcessOutput 'Stderr o, Resource, Race, Async, Embed IO] r =>   ProcessOptions ->-  InterpretersFor (ScopeEffects o e err) r+  InterpretersFor (ScopeEffects i o err) r scope (ProcessOptions discard qSize kill) =   withSystemProcess @resource .   withQueues qSize .-  withAsync_ (outputQueue @Err @e @err discard SystemProcess.readStderr) .-  withAsync_ (outputQueue @Out @o @err discard SystemProcess.readStdout) .-  withAsync_ (inputQueue @err SystemProcess.writeStdin) .+  withAsync_ (outputQueue @'Stderr @o @err @SystemProcess discard SystemProcess.readStderr) .+  withAsync_ (outputQueue @'Stdout @o @err @SystemProcess discard SystemProcess.readStdout) .+  withAsync_ (inputQueue @i @err @SystemProcess SystemProcess.writeStdin) .   withKill @err kill  -- |Interpret 'Process' with a system process resource whose file descriptors are connected to three 'TBMQueue's, -- deferring decoding of stdout and stderr to the interpreters of two 'ProcessOutput' effects. interpretProcess ::-  ∀ resource err o e r .+  ∀ resource err i o r .   Member (Scoped resource (SystemProcess !! err)) r =>-  Members [ProcessOutput o, ProcessOutput e, Resource, Race, Async, Embed IO] r =>+  Members [ProcessOutput 'Stdout o, ProcessOutput 'Stderr o, ProcessInput i, Resource, Race, Async, Embed IO] r =>   ProcessOptions ->-  InterpreterFor (Scoped () (Process ByteString o e) !! ProcessError) r+  InterpreterFor (Scoped () (Process i o) !! ProcessError) r interpretProcess options =-  interpretScopedResumableWith_ @(ScopeEffects o e err) (scope @o @e @resource options) handleProcessWithQueues+  interpretScopedResumableWith_ @(ScopeEffects i o err) (scope @i @o @resource options) handleProcessWithQueues --- |Interpret 'Process' with a system process resource whose file descriptors are connected to three 'TBMQueue's,+-- |Interpret 'Process' with a system process resource whose stdin/stdout are connected to two 'TBMQueue's, -- producing 'ByteString's.+-- Silently discards stderr. interpretProcessByteString ::   ∀ resource err r .   Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r =>   ProcessOptions ->-  InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r+  InterpreterFor (Scoped () (Process ByteString ByteString) !! ProcessError) r interpretProcessByteString options =-  interpretProcessOutputId .+  interpretProcessOutputIgnore @'Stderr @ByteString .+  interpretProcessOutputId @'Stdout .+  interpretProcessInputId .   interpretProcess @resource @err options .-  raiseUnder+  raiseUnder3 --- |Interpret 'Process' with a system process resource whose file descriptors are connected to three 'TBMQueue's,+-- |Interpret 'Process' with a system process resource whose stdin/stdout are connected to two 'TBMQueue's, -- producing chunks of lines of 'ByteString's.+-- Silently discards stderr. interpretProcessByteStringLines ::   ∀ resource err r .   Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r =>   ProcessOptions ->-  InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r+  InterpreterFor (Scoped () (Process ByteString ByteString) !! ProcessError) r interpretProcessByteStringLines options =-  interpretProcessOutputLines .+  interpretProcessOutputIgnore @'Stderr @ByteString .+  interpretProcessOutputLines @'Stdout .+  interpretProcessInputId .   interpretProcess @resource @err options .-  raiseUnder+  raiseUnder3 --- |Interpret 'Process' with a system process resource whose file descriptors are connected to three 'TBMQueue's,+-- |Interpret 'Process' with a system process resource whose stdin/stdout are connected to two 'TBMQueue's, -- producing 'Text's.+-- Silently discards stderr. interpretProcessText ::   ∀ resource err r .   Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r =>   ProcessOptions ->-  InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r+  InterpreterFor (Scoped () (Process Text Text) !! ProcessError) r interpretProcessText options =-  interpretProcessOutputText .+  interpretProcessOutputIgnore @'Stderr @Text .+  interpretProcessOutputText @'Stdout .+  interpretProcessInputText .   interpretProcess @resource @err options .-  raiseUnder+  raiseUnder3 --- |Interpret 'Process' with a system process resource whose file descriptors are connected to three 'TBMQueue's,+-- |Interpret 'Process' with a system process resource whose stdin/stdout are connected to two 'TBMQueue's, -- producing chunks of lines of 'Text's.+-- Silently discards stderr. interpretProcessTextLines ::   ∀ resource err r .   Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r =>   ProcessOptions ->-  InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r+  InterpreterFor (Scoped () (Process Text Text) !! ProcessError) r interpretProcessTextLines options =-  interpretProcessOutputTextLines .+  interpretProcessOutputIgnore @'Stderr @Text .+  interpretProcessOutputTextLines @'Stdout .+  interpretProcessInputText .   interpretProcess @resource @err options .-  raiseUnder+  raiseUnder3++-- |Reinterpret 'Input' and 'Output' as 'Process'.+interpretInputOutputProcess ::+  ∀ i o r .+  Member (Process i o) r =>+  InterpretersFor [Input o, Output i] r+interpretInputOutputProcess =+  runOutputSem (Process.send @i @o) .+  runInputSem (Process.recv @i @o)++-- |Interpret 'Input ByteString' by polling a 'Handle' and stopping with 'ProcessError' when it fails.+interpretInputHandleBuffered ::+  Member (Embed IO) r =>+  Handle ->+  InterpreterFor (Input ByteString !! ProcessError) r+interpretInputHandleBuffered handle =+  interpretResumable \case+    Input ->+      stopNote (Terminated "handle closed") =<< tryMaybe (hGetSome handle 4096)++-- |Interpret 'Input ByteString' by polling a 'Handle' and stopping with 'ProcessError' when it fails.+-- This variant deactivates buffering for the 'Handle'.+interpretInputHandle ::+  Member (Embed IO) r =>+  Handle ->+  InterpreterFor (Input ByteString !! ProcessError) r+interpretInputHandle handle sem = do+  tryAny_ (hSetBuffering handle NoBuffering)+  interpretInputHandleBuffered handle sem++-- |Interpret 'Output ByteString' by writing to a 'Handle' and stopping with 'ProcessError' when it fails.+interpretOutputHandleBuffered ::+  Member (Embed IO) r =>+  Handle ->+  InterpreterFor (Output ByteString !! ProcessError) r+interpretOutputHandleBuffered handle =+  interpretResumable \case+    Output o ->+      stopNote (Terminated "handle closed") =<< tryMaybe (hPut handle o)++-- |Interpret 'Output ByteString' by writing to a 'Handle' and stopping with 'ProcessError' when it fails.+-- This variant deactivates buffering for the 'Handle'.+interpretOutputHandle ::+  Member (Embed IO) r =>+  Handle ->+  InterpreterFor (Output ByteString !! ProcessError) r+interpretOutputHandle handle sem = do+  tryAny_ (hSetBuffering handle NoBuffering)+  interpretOutputHandleBuffered handle sem++-- |Interpret 'Process' in terms of 'Input' and 'Output'.+-- Since the @i@ and @o@ parameters correspond to the abstraction of stdio fds of an external system process, @i@ is+-- written by 'Output' and @o@ is read from 'Input'.+-- This is useful to abstract the current process's stdio as an external process, with input and output swapped.+interpretProcessIO ::+  ∀ i o ie oe r .+  Members [Input ByteString !! ie, Output ByteString !! oe] r =>+  Members [ProcessInput i, ProcessOutput 'Stdout o, Resource, Race, Async, Embed IO] r =>+  ProcessOptions ->+  InterpreterFor (Process i o !! ProcessError) r+interpretProcessIO (ProcessOptions discard qSize _) =+  withQueues @i @o qSize .+  withAsync_ (outputQueue @'Stdout @o @ie @(Input ByteString) discard input) .+  withAsync_ (inputQueue @i @oe @(Output ByteString) output) .+  interpretResumable handleProcessWithQueues .+  raiseUnder2++-- |Interpret 'Process' in terms of two 'Handle's.+-- This is useful to abstract the current process's stdio as an external process, with input and output swapped.+-- The first 'Handle' argument corresponds to the @o@ parameter, the second one to @i@, despite the first one usually+-- being the current process's stdin.+-- This is due to 'Process' abstracting an external process to whose stdin would be /written/, while the current one's+-- is /read/.+interpretProcessHandles ::+  ∀ i o r .+  Members [ProcessInput i, ProcessOutput 'Stdout o, Resource, Race, Async, Embed IO] r =>+  ProcessOptions ->+  Handle ->+  Handle ->+  InterpreterFor (Process i o !! ProcessError) r+interpretProcessHandles options hIn hOut =+  interpretOutputHandle hOut .+  interpretInputHandle hIn .+  interpretProcessIO @i @o @ProcessError @ProcessError options .+  raiseUnder2++-- |Interpret 'Process' using the current process's stdin and stdout.+-- This mirrors the usual abstraction of an external process, to whose stdin would be /written/, while the current one's+-- is /read/.+interpretProcessCurrent ::+  Members [ProcessInput i, ProcessOutput 'Stdout o, Resource, Race, Async, Embed IO] r =>+  ProcessOptions ->+  InterpreterFor (Process i o !! ProcessError) r+interpretProcessCurrent options =+  interpretProcessHandles options stdin stdout
+ lib/Polysemy/Process/Interpreter/ProcessInput.hs view
@@ -0,0 +1,22 @@+{-# options_haddock prune #-}++-- |Description: ProcessInput Interpreters, Internal+module Polysemy.Process.Interpreter.ProcessInput where++import Polysemy.Process.Effect.ProcessInput (ProcessInput (Encode))++-- |Interpret 'ProcessInput' by passing 'ByteString' through.+interpretProcessInputId :: InterpreterFor (ProcessInput ByteString) r+interpretProcessInputId =+  interpret \case+    Encode value ->+      pure value+{-# inline interpretProcessInputId #-}++-- |Interpret 'ProcessInput' by UTF-8-encoding 'Text'.+interpretProcessInputText :: InterpreterFor (ProcessInput Text) r+interpretProcessInputText =+  interpret \case+    Encode value ->+      pure (encodeUtf8 value)+{-# inline interpretProcessInputText #-}
lib/Polysemy/Process/Interpreter/ProcessOutput.hs view
@@ -5,16 +5,52 @@  import qualified Data.ByteString as ByteString +import Polysemy.Process.Data.ProcessOutputParseResult (ProcessOutputParseResult (Done, Fail, Partial)) import Polysemy.Process.Effect.ProcessOutput (ProcessOutput (Chunk))+import qualified Polysemy.Process.Effect.ProcessOutput as ProcessOutput +-- |Interpret 'ProcessOutput' by discarding any output.+interpretProcessOutputIgnore ::+  ∀ p a r .+  InterpreterFor (ProcessOutput p a) r+interpretProcessOutputIgnore =+  interpret \case+    Chunk _ _ ->+      pure ([], "")+{-# inline interpretProcessOutputIgnore #-}+ -- |Interpret 'ProcessOutput' by immediately emitting raw 'ByteString's without accumulation.-interpretProcessOutputId :: InterpreterFor (ProcessOutput ByteString) r+interpretProcessOutputId ::+  ∀ p r .+  InterpreterFor (ProcessOutput p ByteString) r interpretProcessOutputId =   interpret \case     Chunk buffer new ->       pure ([buffer <> new], "") {-# inline interpretProcessOutputId #-} +-- |Transformer for 'ProcessOutput' that lifts results into 'Left', creating 'ProcessOutput p (Either a b)' from+-- 'ProcessOutput p a'.+interpretProcessOutputLeft ::+  ∀ p a b r .+  Member (ProcessOutput p a) r =>+  InterpreterFor (ProcessOutput p (Either a b)) r+interpretProcessOutputLeft =+  interpret \case+    Chunk buf new ->+      first (fmap Left) <$> ProcessOutput.chunk @p buf new++-- |Transformer for 'ProcessOutput' that lifts results into 'Right', creating 'ProcessOutput p (Either a b)' from+-- 'ProcessOutput p b'.+interpretProcessOutputRight ::+  ∀ p a b r .+  Member (ProcessOutput p b) r =>+  InterpreterFor (ProcessOutput p (Either a b)) r+interpretProcessOutputRight =+  interpret \case+    Chunk buf new ->+      first (fmap Right) <$> ProcessOutput.chunk @p buf new+ splitLines :: ByteString -> ByteString -> ([ByteString], ByteString) splitLines buffer new =   second fold (foldr' folder ([], Nothing) parts)@@ -27,7 +63,9 @@       (a : z, Just r)  -- |Interpret 'ProcessOutput' by emitting individual 'ByteString' lines of output.-interpretProcessOutputLines :: InterpreterFor (ProcessOutput ByteString) r+interpretProcessOutputLines ::+  ∀ p r .+  InterpreterFor (ProcessOutput p ByteString) r interpretProcessOutputLines =   interpret \case     Chunk buffer new ->@@ -35,7 +73,9 @@ {-# inline interpretProcessOutputLines #-}  -- |Interpret 'ProcessOutput' by immediately emitting 'Text' without accumulation.-interpretProcessOutputText :: InterpreterFor (ProcessOutput Text) r+interpretProcessOutputText ::+  ∀ p r .+  InterpreterFor (ProcessOutput p Text) r interpretProcessOutputText =   interpret \case     Chunk buffer new ->@@ -43,9 +83,51 @@ {-# inline interpretProcessOutputText #-}  -- |Interpret 'ProcessOutput' by emitting individual 'Text' lines of output.-interpretProcessOutputTextLines :: InterpreterFor (ProcessOutput Text) r+interpretProcessOutputTextLines ::+  ∀ p r .+  InterpreterFor (ProcessOutput p Text) r interpretProcessOutputTextLines =   interpret \case     Chunk buffer new ->       pure (first (fmap decodeUtf8) (splitLines buffer new)) {-# inline interpretProcessOutputTextLines #-}++type Parser a =+  ByteString -> ProcessOutputParseResult a++-- |Internal helper for 'interpretProcessOutputIncremental' that repeatedly parses elements from a chunk until the+-- parser returns a failure or a partial result.+parseMany ::+  Parser a ->+  Maybe (Parser a) ->+  ByteString ->+  (Maybe (Parser a), ([Either Text a], ByteString))+parseMany parse =+  spin id+  where+    spin cons cont = \case+      "" ->+        (cont, (cons [], ""))+      chunk ->+        case fromMaybe parse cont chunk of+          Fail e ->+            (Nothing, (cons [Left e], ""))+          Partial c ->+            (Just c, (cons [], ""))+          Done a rest ->+            spin (cons . (Right a :)) Nothing rest++-- |Whenever a chunk of output arrives, call the supplied incremental parser whose result must be converted to+-- 'ProcessOutputParseResult'.+-- If a partial parse result is produced, it is stored in the state and resumed when the next chunk is available.+-- If parsing an @a@ succeeds, the parser recurses until it fails.+interpretProcessOutputIncremental ::+  ∀ p a r .+  (ByteString -> ProcessOutputParseResult a) ->+  InterpreterFor (ProcessOutput p (Either Text a)) r+interpretProcessOutputIncremental parse =+  evalState (Nothing :: Maybe (ByteString -> ProcessOutputParseResult a)) .+  atomicStateToState @(Maybe (ByteString -> ProcessOutputParseResult a)) .+  interpret \case+    Chunk buffer new -> atomicState (flip (parseMany parse) (buffer <> new))+  . raiseUnder2
lib/Polysemy/Process/Interpreter/ProcessStdio.hs view
@@ -21,48 +21,52 @@ import Polysemy.Process.Interpreter.SystemProcess (PipesProcess, interpretSystemProcessNative)  -- |Interpret 'Process' as a native 'Polysemy.Process.SystemProcess', producing unaccumulated chunks of 'ByteString'.+-- Silently discards stderr. interpretProcessByteStringNative ::   Members [Resource, Race, Async, Embed IO] r =>-  -- |Whether to discard output chunks if the queue is full.   ProcessOptions ->+  -- |Basic config. The pipes will be changed to 'System.IO.Handle' by the interpreter.   ProcessConfig () () () ->-  InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r+  InterpreterFor (Scoped () (Process ByteString ByteString) !! ProcessError) r interpretProcessByteStringNative options conf =   interpretSystemProcessNative conf .   interpretProcessByteString @PipesProcess @SystemProcessError options .   raiseUnder  -- |Interpret 'Process' as a native 'Polysemy.Process.SystemProcess', producing lines of 'ByteString'.+-- Silently discards stderr. interpretProcessByteStringLinesNative ::   Members [Resource, Race, Async, Embed IO] r =>   ProcessOptions ->   -- |Basic config. The pipes will be changed to 'System.IO.Handle' by the interpreter.   ProcessConfig () () () ->-  InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r+  InterpreterFor (Scoped () (Process ByteString ByteString) !! ProcessError) r interpretProcessByteStringLinesNative options conf =   interpretSystemProcessNative conf .   interpretProcessByteStringLines @PipesProcess @SystemProcessError options .   raiseUnder  -- |Interpret 'Process' as a native 'Polysemy.Process.SystemProcess', producing unaccumulated chunks of 'Text'.+-- Silently discards stderr. interpretProcessTextNative ::   Members [Resource, Race, Async, Embed IO] r =>   ProcessOptions ->   -- |Basic config. The pipes will be changed to 'System.IO.Handle' by the interpreter.   ProcessConfig () () () ->-  InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r+  InterpreterFor (Scoped () (Process Text Text) !! ProcessError) r interpretProcessTextNative options conf =   interpretSystemProcessNative conf .   interpretProcessText @PipesProcess @SystemProcessError options .   raiseUnder  -- |Interpret 'Process' as a native 'Polysemy.Process.SystemProcess', producing lines of 'Text'.+-- Silently discards stderr. interpretProcessTextLinesNative ::   Members [Resource, Race, Async, Embed IO] r =>   ProcessOptions ->   -- |Basic config. The pipes will be changed to 'System.IO.Handle' by the interpreter.   ProcessConfig () () () ->-  InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r+  InterpreterFor (Scoped () (Process Text Text) !! ProcessError) r interpretProcessTextLinesNative options conf =   interpretSystemProcessNative conf .   interpretProcessTextLines @PipesProcess @SystemProcessError options .
lib/Polysemy/Process/Interpreter/Pty.hs view
@@ -34,8 +34,8 @@   PtyResources ->   Sem r () releasePty PtyResources {primary, pty} = do-  ignoreException (closePty pty)-  ignoreException (closeFd primary)+  tryAny_ (closePty pty)+  tryAny_ (closeFd primary)  withPty ::   Members [Resource, Embed IO] r =>
lib/Polysemy/Process/Interpreter/SystemProcess.hs view
@@ -101,6 +101,16 @@ processId process =   terminate "getPid returned Nothing" =<< embed (getPid (unsafeProcessHandle process)) +checkEof ::+  Member (Stop SystemProcessError) r =>+  ByteString ->+  Sem r ByteString+checkEof = \case+  "" ->+    stop (SystemProcessError.Terminated "Process terminated, empty ByteString read from handle")+  b ->+    pure b+ -- |Interpret 'SystemProcess' with a concrete 'System.Process' with connected pipes. interpretSystemProcessWithProcess ::   ∀ r .@@ -115,9 +125,9 @@       pid <- processId process       tryStop "signal failed" (Signal.signalProcess sig pid)     SystemProcess.ReadStdout ->-      tryStop "stdout failed" (hGetSome (getStdout process) 4096)+      checkEof =<< tryStop "stdout failed" (hGetSome (getStdout process) 4096)     SystemProcess.ReadStderr ->-      tryStop "stderr failed" (hGetSome (getStderr process) 4096)+      checkEof =<< tryStop "stderr failed" (hGetSome (getStderr process) 4096)     SystemProcess.WriteStdin msg ->       tryStop "stdin failed" (hPut (getStdin process) msg)     SystemProcess.Wait ->
polysemy-process.cabal view
@@ -5,21 +5,18 @@ -- see: https://github.com/sol/hpack  name:           polysemy-process-version:        0.8.0.1-synopsis:       Polysemy Effects for System Processes-description:    See <https://hackage.haskell.org/package/polysemy-process/docs/Polysemy-Process.html>+version:        0.9.0.0+synopsis:       Polysemy effects for system processes+description:    See https://hackage.haskell.org/package/polysemy-process/docs/Polysemy-Process.html category:       Concurrency homepage:       https://github.com/tek/polysemy-conc#readme bug-reports:    https://github.com/tek/polysemy-conc/issues author:         Torsten Schmits-maintainer:     haskell@tryp.io-copyright:      2021 Torsten Schmits+maintainer:     hackage@tryp.io+copyright:      2022 Torsten Schmits license:        BSD-2-Clause-Patent license-file:   LICENSE build-type:     Simple-extra-source-files:-    readme.md-    changelog.md  source-repository head   type: git@@ -31,15 +28,18 @@       Polysemy.Process.Data.ProcessError       Polysemy.Process.Data.ProcessKill       Polysemy.Process.Data.ProcessOptions+      Polysemy.Process.Data.ProcessOutputParseResult       Polysemy.Process.Data.PtyError       Polysemy.Process.Data.PtyResources       Polysemy.Process.Data.SystemProcessError       Polysemy.Process.Effect.Process+      Polysemy.Process.Effect.ProcessInput       Polysemy.Process.Effect.ProcessOutput       Polysemy.Process.Effect.Pty       Polysemy.Process.Effect.SystemProcess       Polysemy.Process.Executable       Polysemy.Process.Interpreter.Process+      Polysemy.Process.Interpreter.ProcessInput       Polysemy.Process.Interpreter.ProcessOutput       Polysemy.Process.Interpreter.ProcessStdio       Polysemy.Process.Interpreter.Pty@@ -63,6 +63,7 @@       DeriveFoldable       DeriveFunctor       DeriveGeneric+      DeriveLift       DeriveTraversable       DerivingStrategies       DerivingVia@@ -95,6 +96,7 @@       RankNTypes       RecordWildCards       RecursiveDo+      RoleAnnotations       ScopedTypeVariables       StandaloneDeriving       TemplateHaskell@@ -107,16 +109,16 @@       UndecidableInstances       UnicodeSyntax       ViewPatterns-  ghc-options: -Wall -Wredundant-constraints -Wincomplete-uni-patterns -Wmissing-deriving-strategies -Widentities+  ghc-options: -Wall -Wredundant-constraints -Wincomplete-uni-patterns -Wmissing-deriving-strategies -Widentities -Wunused-packages   build-depends:-      base ==4.*-    , incipit-core >=0.2+      base >=4.12 && <5+    , incipit-core >=0.3     , path >=0.7     , path-io >=1.6.2     , polysemy >=1.6-    , polysemy-conc-    , polysemy-resume >=0.3-    , polysemy-time >=0.4+    , polysemy-conc >=0.9+    , polysemy-resume >=0.5+    , polysemy-time >=0.5     , posix-pty >=0.2     , process     , stm-chans >=2@@ -124,8 +126,8 @@     , unix   mixins:       base hiding (Prelude)-  if impl(ghc >= 8.10)-    ghc-options: -Wunused-packages+    , incipit-core (IncipitCore as Prelude)+    , incipit-core hiding (IncipitCore)   default-language: Haskell2010  test-suite polysemy-process-unit@@ -149,6 +151,7 @@       DeriveFoldable       DeriveFunctor       DeriveGeneric+      DeriveLift       DeriveTraversable       DerivingStrategies       DerivingVia@@ -181,6 +184,7 @@       RankNTypes       RecordWildCards       RecursiveDo+      RoleAnnotations       ScopedTypeVariables       StandaloneDeriving       TemplateHaskell@@ -193,22 +197,22 @@       UndecidableInstances       UnicodeSyntax       ViewPatterns-  ghc-options: -Wall -Wredundant-constraints -Wincomplete-uni-patterns -Wmissing-deriving-strategies -Widentities -threaded -rtsopts -with-rtsopts=-N+  ghc-options: -Wall -Wredundant-constraints -Wincomplete-uni-patterns -Wmissing-deriving-strategies -Widentities -Wunused-packages -threaded -rtsopts -with-rtsopts=-N   build-depends:-      base ==4.*-    , incipit-core+      base >=4.12 && <5+    , incipit-core >=0.3     , polysemy     , polysemy-conc     , polysemy-plugin     , polysemy-process     , polysemy-resume-    , polysemy-test+    , polysemy-test >=0.6     , polysemy-time     , tasty     , tasty-expected-failure     , typed-process   mixins:       base hiding (Prelude)-  if impl(ghc >= 8.10)-    ghc-options: -Wunused-packages+    , incipit-core (IncipitCore as Prelude)+    , incipit-core hiding (IncipitCore)   default-language: Haskell2010
− readme.md
@@ -1,8 +0,0 @@-# About--This library provides [Polysemy] effects for system processes and pseudo terminals.--Please visit [Hackage] for documentation.--[Polysemy]: https://hackage.haskell.org/package/polysemy-[Hackage]: https://hackage.haskell.org/package/polysemy-process/docs/Polysemy-Process.html
test/Polysemy/Process/Test/ProcessTest.hs view
@@ -2,6 +2,7 @@  module Polysemy.Process.Test.ProcessTest where +import qualified Data.ByteString as ByteString import qualified Polysemy.Conc as Conc import Polysemy.Conc.Effect.Scoped (Scoped) import Polysemy.Conc.Interpreter.Race (interpretRace)@@ -19,7 +20,9 @@ import Polysemy.Process.Data.ProcessOptions (ProcessOptions (kill)) import qualified Polysemy.Process.Effect.Process as Process import Polysemy.Process.Effect.Process (withProcess)+import Polysemy.Process.Interpreter.ProcessOutput (parseMany) import Polysemy.Process.Interpreter.ProcessStdio (interpretProcessByteStringNative, interpretProcessTextLinesNative)+import Polysemy.Process.Data.ProcessOutputParseResult (ProcessOutputParseResult(Done, Partial))  config :: ProcessConfig () () () config =@@ -29,18 +32,18 @@ messageLines =   replicate 4 "line" -message :: ByteString+message :: Text message =-  encodeUtf8 (unlines messageLines)+  unlines messageLines  test_process :: UnitTest test_process =   runTestAuto $ interpretRace $ asyncToIOFinal $ interpretProcessByteStringNative def config do     response <- resumeHoistError @ProcessError @(Scoped _ _) show do       withProcess do-        Process.send message+        Process.send (encodeUtf8 message)         Race.timeout_ (throw "timed out") (Seconds 5) Process.recv-    message === response+    message === decodeUtf8 response  test_processLines :: UnitTest test_processLines =@@ -51,8 +54,8 @@         Race.timeout_ (throw "timed out") (Seconds 5) (replicateM 4 Process.recv)     messageLines === response -test_processKill :: UnitTest-test_processKill =+test_processKillNever :: UnitTest+test_processKillNever =   runTestAuto $ interpretRace $ asyncToIOFinal $ interpretProcessTextLinesNative def { kill = KillNever } config do     result <- resumeHoistError @ProcessError @(Scoped _ _) show do       Conc.timeout unit (MilliSeconds 100) do@@ -63,10 +66,32 @@     -- the process and makes the right side terminate regularly.     assertLeft () result +test_processIncremental :: UnitTest+test_processIncremental =+  runTestAuto do+    (Nothing, ([Right "aa", Right "bb"], "")) === first void (parseMany parse Nothing "aabb")+    let (c1, r1) = parseMany parse Nothing "aabbc"+    ([Right "aa", Right "bb"], "") === r1+    case ($ "c") <$> c1 of+      Just (Done a "") -> "cc" === a+      a -> fail ("not Done: " <> show a)+    let (c2, r2) = parseMany parse Nothing "a"+    ([], "") === r2+    case ($ "a") <$> c2 of+      Just (Done a "") -> "aa" === a+      a -> fail ("not Done: " <> show a)+    (Nothing, ([Right "aa"], "")) === first void (parseMany parse c2 "a")+  where+    parse b+      | ByteString.length b == 1 =+        Partial (parse . (b <>))+      | otherwise =+        Done (ByteString.take 2 b) (ByteString.drop 2 b)+ test_processAll :: TestTree test_processAll =   testGroup "process" [-    unitTest "process" test_process,-    unitTest "process lines" test_processLines,-    ignoreTest (unitTest "process kill" test_processKill)+    unitTest "read raw chunks" test_process,+    unitTest "read lines" test_processLines,+    ignoreTest (unitTest "don't kill the process at the end of the scope" test_processKillNever)   ]