pipes-cliff 0.2.0.0 → 0.4.0.0
raw patch · 4 files changed
+184/−105 lines, 4 filesnew-component:exe:standardOutputAndErrorPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Pipes.Cliff: background :: MonadSafe m => IO a -> m (Async a)
+ Pipes.Cliff: waitForThread :: MonadIO m => Async a -> m a
+ Pipes.Cliff.Examples: standardOutputAndError :: IO ByteString
- Pipes.Cliff: pipeError :: (MonadIO mi, MonadSafe mi, MonadIO m, MonadSafe m) => NonPipe -> NonPipe -> CreateProcess -> m (Producer ByteString mi (), ProcessHandle)
+ Pipes.Cliff: pipeError :: (MonadSafe mi, MonadSafe m) => NonPipe -> NonPipe -> CreateProcess -> m (Producer ByteString mi (), ProcessHandle)
- Pipes.Cliff: pipeInput :: (MonadIO mi, MonadSafe mi, MonadIO m, MonadSafe m) => NonPipe -> NonPipe -> CreateProcess -> m (Consumer ByteString mi (), ProcessHandle)
+ Pipes.Cliff: pipeInput :: (MonadSafe mi, MonadSafe m) => NonPipe -> NonPipe -> CreateProcess -> m (Consumer ByteString mi (), ProcessHandle)
- Pipes.Cliff: pipeInputError :: (MonadIO mi, MonadSafe mi, MonadIO mo, MonadSafe mo, MonadIO m, MonadSafe m) => NonPipe -> CreateProcess -> m (Consumer ByteString mi (), Producer ByteString mo (), ProcessHandle)
+ Pipes.Cliff: pipeInputError :: (MonadSafe mi, MonadSafe mo, MonadSafe m) => NonPipe -> CreateProcess -> m (Consumer ByteString mi (), Producer ByteString mo (), ProcessHandle)
- Pipes.Cliff: pipeInputOutput :: (MonadIO mi, MonadSafe mi, MonadIO mo, MonadSafe mo, MonadIO m, MonadSafe m) => NonPipe -> CreateProcess -> m (Consumer ByteString mi (), Producer ByteString mo (), ProcessHandle)
+ Pipes.Cliff: pipeInputOutput :: (MonadSafe mi, MonadSafe mo, MonadSafe m) => NonPipe -> CreateProcess -> m (Consumer ByteString mi (), Producer ByteString mo (), ProcessHandle)
- Pipes.Cliff: pipeInputOutputError :: (MonadIO mi, MonadSafe mi, MonadIO mo, MonadSafe mo, MonadIO me, MonadSafe me, MonadIO m, MonadSafe m) => CreateProcess -> m (Consumer ByteString mi (), Producer ByteString mo (), Producer ByteString me (), ProcessHandle)
+ Pipes.Cliff: pipeInputOutputError :: (MonadSafe mi, MonadSafe mo, MonadSafe me, MonadSafe m) => CreateProcess -> m (Consumer ByteString mi (), Producer ByteString mo (), Producer ByteString me (), ProcessHandle)
- Pipes.Cliff: pipeNone :: (MonadIO m, MonadSafe m) => NonPipe -> NonPipe -> NonPipe -> CreateProcess -> m ProcessHandle
+ Pipes.Cliff: pipeNone :: MonadSafe m => NonPipe -> NonPipe -> NonPipe -> CreateProcess -> m ProcessHandle
- Pipes.Cliff: pipeOutput :: (MonadIO mi, MonadSafe mi, MonadIO m, MonadSafe m) => NonPipe -> NonPipe -> CreateProcess -> m (Producer ByteString mi (), ProcessHandle)
+ Pipes.Cliff: pipeOutput :: (MonadSafe mi, MonadSafe m) => NonPipe -> NonPipe -> CreateProcess -> m (Producer ByteString mi (), ProcessHandle)
- Pipes.Cliff: pipeOutputError :: (MonadIO mi, MonadSafe mi, MonadIO mo, MonadSafe mo, MonadIO m, MonadSafe m) => NonPipe -> CreateProcess -> m (Producer ByteString mi (), Producer ByteString mo (), ProcessHandle)
+ Pipes.Cliff: pipeOutputError :: (MonadSafe mi, MonadSafe mo, MonadSafe m) => NonPipe -> CreateProcess -> m (Producer ByteString mi (), Producer ByteString mo (), ProcessHandle)
Files
- lib/Pipes/Cliff.hs +39/−27
- lib/Pipes/Cliff/Examples.hs +34/−0
- pipes-cliff.cabal +104/−78
- tests/standardOutputAndError.hs +7/−0
lib/Pipes/Cliff.hs view
@@ -66,13 +66,17 @@ , pipeOutputError , pipeInputOutputError - -- * Conveniences+ -- * Background operations - -- | These make it a bit easier to write both simple and- -- complicated pipelines.+ -- | Often it is necessary to run threads in the background; in+ -- addition, all subprocesses run in the background. These+ -- functions allow you to launch threads in the background and to+ -- wait on background threads and subprocesses. , conveyor+ , background , waitForProcess+ , waitForThread -- * Re-exports -- $reexports@@ -85,7 +89,7 @@ import System.IO import Pipes import Pipes.Concurrent-import Control.Concurrent.Async (Async, async, cancel)+import Control.Concurrent.Async (Async, async, cancel, wait) import Data.ByteString (ByteString) import qualified Data.ByteString as BS import qualified System.Process as Process@@ -282,7 +286,7 @@ -- while receiving data, the error is caught and production ceases. -- The exception is not re-thrown. produceFromHandle- :: (MonadIO m, Pipes.Safe.MonadCatch m)+ :: (Pipes.Safe.MonadCatch m, MonadIO m) => Bool -- ^ Be quiet? -> Handle@@ -303,7 +307,7 @@ -- sending data, the error is caught and consumption ceases. The -- exception is not re-thrown. consumeToHandle- :: (MonadIO m, Pipes.Safe.MonadCatch m)+ :: (Pipes.Safe.MonadCatch m, MonadIO m) => Bool -- ^ Be quiet? -> Handle@@ -325,7 +329,7 @@ -- | Acquires a resource and registers a finalizer. initialize- :: (Pipes.Safe.MonadSafe m, MonadIO m)+ :: Pipes.Safe.MonadSafe m => IO a -> (a -> IO ()) -> m a@@ -336,22 +340,23 @@ -- | Creates a mailbox; seals it when done. newMailbox- :: (Pipes.Safe.MonadSafe m, MonadIO m)+ :: Pipes.Safe.MonadSafe m => m (Output a, Input a, STM ()) newMailbox = initialize (spawn' messageBuffer) (\(_, _, seal) -> atomically seal) -- | Runs a thread in the background. Initializes a finalizer that--- will cancel the thread.-background :: (Pipes.Safe.MonadSafe m, MonadIO m) => IO a -> m (Async a)+-- will cancel the thread if it is still running when the+-- 'Pipes.Safe.MonadSafe' computation completes.+background :: Pipes.Safe.MonadSafe m => IO a -> m (Async a) background action = initialize (async action) cancel -- | Creates a thread that will run in the background and pump -- messages from the given mailbox to the process via its handle. -- Closes the Handle when done. processPump- :: (MonadIO m, Pipes.Safe.MonadSafe m)+ :: Pipes.Safe.MonadSafe m => Bool -- ^ Quiet? -> Handle@@ -372,7 +377,7 @@ -- messages from the process and place them into the given mailbox. -- Closes the handle when done. processPull- :: (Pipes.Safe.MonadSafe m, MonadIO m)+ :: Pipes.Safe.MonadSafe m => Bool -- ^ Quiet? -> Handle@@ -394,7 +399,7 @@ -- | Creates a mailbox that sends messages to the given process, and -- sets up and runs threads to pump messages to the process. makeToProcess- :: (Pipes.Safe.MonadSafe mp, MonadIO mp, Pipes.Safe.MonadSafe m, MonadIO m)+ :: (Pipes.Safe.MonadSafe mp, Pipes.Safe.MonadSafe m) => Bool -- ^ Quiet? -> Handle@@ -408,7 +413,7 @@ -- and sets up and runs threads to receive the messages and deliver -- them to the mailbox. makeFromProcess- :: (Pipes.Safe.MonadSafe m, MonadIO m, Pipes.Safe.MonadSafe mp, MonadIO mp)+ :: (Pipes.Safe.MonadSafe m, Pipes.Safe.MonadSafe mp) => Bool -- ^ Quiet? -> Handle@@ -451,7 +456,7 @@ -- | Creates a subprocess. Registers destroyers for each handle -- created, as well as for the ProcessHandle. createProcess- :: (MonadIO m, Pipes.Safe.MonadSafe m)+ :: Pipes.Safe.MonadSafe m => Bool -- ^ Quiet? -> Process.CreateProcess@@ -479,6 +484,13 @@ waitForProcess :: MonadIO m => ProcessHandle -> m ExitCode waitForProcess h = liftIO $ Process.waitForProcess h +-- | A version of 'Control.Concurrent.Async.wait' with an overloaded+-- 'MonadIO' return type. Allows you to wait for the return value of+-- threads launched with 'background'. If the thread throws an+-- exception, 'waitForThread' will throw that same exception.+waitForThread :: MonadIO m => Async a -> m a+waitForThread = liftIO . wait+ {- $process Each of these functions creates a process. The process begins@@ -517,7 +529,7 @@ -- | Do not create any 'Proxy' to or from the process. pipeNone- :: (MonadIO m, Pipes.Safe.MonadSafe m)+ :: Pipes.Safe.MonadSafe m => NonPipe -- ^ Standard input -> NonPipe@@ -535,7 +547,7 @@ -- | Create a 'Consumer' for standard input. pipeInput- :: (MonadIO mi, Pipes.Safe.MonadSafe mi, MonadIO m, Pipes.Safe.MonadSafe m)+ :: (Pipes.Safe.MonadSafe mi, Pipes.Safe.MonadSafe m) => NonPipe -- ^ Standard output -> NonPipe@@ -553,7 +565,7 @@ -- | Create a 'Producer' for standard output. pipeOutput- :: (MonadIO mi, Pipes.Safe.MonadSafe mi, MonadIO m, Pipes.Safe.MonadSafe m)+ :: (Pipes.Safe.MonadSafe mi, Pipes.Safe.MonadSafe m) => NonPipe -- ^ Standard input -> NonPipe@@ -570,7 +582,7 @@ -- | Create a 'Producer' for standard error. pipeError- :: (MonadIO mi, Pipes.Safe.MonadSafe mi, MonadIO m, Pipes.Safe.MonadSafe m)+ :: (Pipes.Safe.MonadSafe mi, Pipes.Safe.MonadSafe m) => NonPipe -- ^ Standard input -> NonPipe@@ -588,8 +600,8 @@ -- | Create a 'Consumer' for standard input and a 'Producer' for -- standard output. pipeInputOutput- :: ( MonadIO mi, Pipes.Safe.MonadSafe mi, MonadIO mo, Pipes.Safe.MonadSafe mo- , MonadIO m, Pipes.Safe.MonadSafe m)+ :: ( Pipes.Safe.MonadSafe mi, Pipes.Safe.MonadSafe mo+ , Pipes.Safe.MonadSafe m) => NonPipe -- ^ Standard error -> CreateProcess@@ -610,8 +622,8 @@ -- | Create a 'Consumer' for standard input and a 'Producer' for -- standard error. pipeInputError- :: ( MonadIO mi, Pipes.Safe.MonadSafe mi, MonadIO mo, Pipes.Safe.MonadSafe mo- , MonadIO m, Pipes.Safe.MonadSafe m)+ :: ( Pipes.Safe.MonadSafe mi, Pipes.Safe.MonadSafe mo+ , Pipes.Safe.MonadSafe m) => NonPipe -- ^ Standard output -> CreateProcess@@ -632,8 +644,8 @@ -- | Create a 'Producer' for standard output and a 'Producer' for -- standard error. pipeOutputError- :: ( MonadIO mi, Pipes.Safe.MonadSafe mi, MonadIO mo- , Pipes.Safe.MonadSafe mo, MonadIO m+ :: ( Pipes.Safe.MonadSafe mi+ , Pipes.Safe.MonadSafe mo , Pipes.Safe.MonadSafe m) => NonPipe -- ^ Standard input@@ -655,8 +667,8 @@ -- | Create a 'Consumer' for standard input, a 'Producer' for standard -- output, and a 'Producer' for standard error. pipeInputOutputError- :: ( MonadIO mi, Pipes.Safe.MonadSafe mi, MonadIO mo, Pipes.Safe.MonadSafe mo,- MonadIO me, Pipes.Safe.MonadSafe me, MonadIO m, Pipes.Safe.MonadSafe m)+ :: ( Pipes.Safe.MonadSafe mi, Pipes.Safe.MonadSafe mo,+ Pipes.Safe.MonadSafe me, Pipes.Safe.MonadSafe m) => CreateProcess -> m ( Consumer ByteString mi () , Producer ByteString mo ()
lib/Pipes/Cliff/Examples.hs view
@@ -58,6 +58,39 @@ mkNumStr = flip BS8.snoc '\n' . BS8.pack . show +-- | Produces an infinite stream of numbers, sends it to @tr@ for some+-- mangling, and then to @sh@, which will copy each line both to+-- standard output and to standard error. From @sh@, standard output+-- is then sent off to @less@, and standard error is sent to a+-- separate thread which will collect the results and return them.+--+-- This example shows you how to write a pipeline that deals with+-- both standard output and standard error.+--+-- It's also interesting to note here that because of the buffering+-- that happens in various places throughout the pipeline, and because+-- less itself also buffers its input, the output you will see from+-- the @sh@ process's standard error will be much longer than the+-- output the user actually viewed in @less@.+standardOutputAndError :: IO BS8.ByteString+standardOutputAndError = runSafeT $ do+ (toTr, fromTr, _) <- pipeInputOutput Inherit+ (procSpec "tr" ["[0-9]", "[a-z]"])+ (toSh, fromShOut, fromShErr, _) <- pipeInputOutputError+ (procSpec "sh" ["-c", script])+ (toLess, _) <- pipeInput Inherit Inherit+ (procSpec "less" [])+ conveyor $ produceNumbers >-> toTr+ conveyor $ fromTr >-> toSh+ conveyor $ fromShOut >-> toLess+ thread <- background+ . runSafeT+ . P.fold BS8.append BS8.empty id+ $ fromShErr+ waitForThread thread+ where+ script = "while read line; do echo $line; echo $line 1>&2; done"+ -- | Like 'alphaNumbers' but just sends a limited number -- of numbers to @cat@. A useful test to make sure that pipelines -- shut down automatically.@@ -94,3 +127,4 @@ (procSpec "tr" ["[0-9]", "[a-z]"]) conveyor $ produceNumbers >-> P.take 300 >-> toTr P.fold BS8.append BS8.empty id fromTr+
pipes-cliff.cabal view
@@ -3,11 +3,11 @@ -- http://www.github.com/massysett/cartel -- -- Script name used to generate: genCabal.hs--- Generated on: 2015-03-20 09:28:58.76288 EDT+-- Generated on: 2015-03-22 13:30:11.54764 EDT -- Cartel library version: 0.14.2.0 name: pipes-cliff-version: 0.2.0.0+version: 0.4.0.0 cabal-version: >= 1.16 license: BSD3 license-file: LICENSE@@ -68,105 +68,131 @@ main-is: numsToLess.hs if flag(tests) buildable: True+ default-language: Haskell2010+ ghc-options:+ -Wall+ hs-source-dirs:+ lib+ tests+ other-modules:+ Pipes.Cliff+ Pipes.Cliff.Examples+ build-depends:+ base >= 4.6.0.0 && < 4.8+ , pipes >= 4.1 && < 4.2+ , pipes-safe >= 2.2 && < 2.3+ , bytestring >= 0.10.4 && < 0.11+ , process >= 1.2.0.0 && < 1.3+ , async >= 2.0 && < 2.1+ , pipes-concurrency >= 2.0 && < 2.1+ ghc-options:+ -threaded else buildable: False- default-language: Haskell2010- ghc-options:- -Wall- hs-source-dirs:- lib- tests- other-modules:- Pipes.Cliff- Pipes.Cliff.Examples- build-depends:- base >= 4.6.0.0 && < 4.8- , pipes >= 4.1 && < 4.2- , pipes-safe >= 2.2 && < 2.3- , bytestring >= 0.10.4 && < 0.11- , process >= 1.2.0.0 && < 1.3- , async >= 2.0 && < 2.1- , pipes-concurrency >= 2.0 && < 2.1- ghc-options:- -threaded Executable alphaNumbers main-is: alphaNumbers.hs if flag(tests) buildable: True+ default-language: Haskell2010+ ghc-options:+ -Wall+ hs-source-dirs:+ lib+ tests+ other-modules:+ Pipes.Cliff+ Pipes.Cliff.Examples+ build-depends:+ base >= 4.6.0.0 && < 4.8+ , pipes >= 4.1 && < 4.2+ , pipes-safe >= 2.2 && < 2.3+ , bytestring >= 0.10.4 && < 0.11+ , process >= 1.2.0.0 && < 1.3+ , async >= 2.0 && < 2.1+ , pipes-concurrency >= 2.0 && < 2.1+ ghc-options:+ -threaded else buildable: False- default-language: Haskell2010- ghc-options:- -Wall- hs-source-dirs:- lib- tests- other-modules:- Pipes.Cliff- Pipes.Cliff.Examples- build-depends:- base >= 4.6.0.0 && < 4.8- , pipes >= 4.1 && < 4.2- , pipes-safe >= 2.2 && < 2.3- , bytestring >= 0.10.4 && < 0.11- , process >= 1.2.0.0 && < 1.3- , async >= 2.0 && < 2.1- , pipes-concurrency >= 2.0 && < 2.1- ghc-options:- -threaded Executable limitedAlphaNumbers main-is: limitedAlphaNumbers.hs if flag(tests) buildable: True+ default-language: Haskell2010+ ghc-options:+ -Wall+ hs-source-dirs:+ lib+ tests+ other-modules:+ Pipes.Cliff+ Pipes.Cliff.Examples+ build-depends:+ base >= 4.6.0.0 && < 4.8+ , pipes >= 4.1 && < 4.2+ , pipes-safe >= 2.2 && < 2.3+ , bytestring >= 0.10.4 && < 0.11+ , process >= 1.2.0.0 && < 1.3+ , async >= 2.0 && < 2.1+ , pipes-concurrency >= 2.0 && < 2.1+ ghc-options:+ -threaded else buildable: False- default-language: Haskell2010- ghc-options:- -Wall- hs-source-dirs:- lib- tests- other-modules:- Pipes.Cliff- Pipes.Cliff.Examples- build-depends:- base >= 4.6.0.0 && < 4.8- , pipes >= 4.1 && < 4.2- , pipes-safe >= 2.2 && < 2.3- , bytestring >= 0.10.4 && < 0.11- , process >= 1.2.0.0 && < 1.3- , async >= 2.0 && < 2.1- , pipes-concurrency >= 2.0 && < 2.1- ghc-options:- -threaded Executable alphaNumbersByteString main-is: alphaNumbersByteString.hs if flag(tests) buildable: True+ default-language: Haskell2010+ ghc-options:+ -Wall+ hs-source-dirs:+ lib+ tests+ other-modules:+ Pipes.Cliff+ Pipes.Cliff.Examples+ build-depends:+ base >= 4.6.0.0 && < 4.8+ , pipes >= 4.1 && < 4.2+ , pipes-safe >= 2.2 && < 2.3+ , bytestring >= 0.10.4 && < 0.11+ , process >= 1.2.0.0 && < 1.3+ , async >= 2.0 && < 2.1+ , pipes-concurrency >= 2.0 && < 2.1+ ghc-options:+ -threaded else buildable: False- default-language: Haskell2010- ghc-options:- -Wall- hs-source-dirs:- lib- tests- other-modules:- Pipes.Cliff- Pipes.Cliff.Examples- build-depends:- base >= 4.6.0.0 && < 4.8- , pipes >= 4.1 && < 4.2- , pipes-safe >= 2.2 && < 2.3- , bytestring >= 0.10.4 && < 0.11- , process >= 1.2.0.0 && < 1.3- , async >= 2.0 && < 2.1- , pipes-concurrency >= 2.0 && < 2.1- ghc-options:- -threaded++Executable standardOutputAndError+ main-is: standardOutputAndError.hs+ if flag(tests)+ buildable: True+ default-language: Haskell2010+ ghc-options:+ -Wall+ hs-source-dirs:+ lib+ tests+ other-modules:+ Pipes.Cliff+ Pipes.Cliff.Examples+ build-depends:+ base >= 4.6.0.0 && < 4.8+ , pipes >= 4.1 && < 4.2+ , pipes-safe >= 2.2 && < 2.3+ , bytestring >= 0.10.4 && < 0.11+ , process >= 1.2.0.0 && < 1.3+ , async >= 2.0 && < 2.1+ , pipes-concurrency >= 2.0 && < 2.1+ ghc-options:+ -threaded+ else+ buildable: False Flag tests description: Build test executables
+ tests/standardOutputAndError.hs view
@@ -0,0 +1,7 @@+module Main where++import Pipes.Cliff.Examples+import qualified Data.ByteString.Char8 as BS8++main :: IO ()+main = standardOutputAndError >>= BS8.putStr