-- * Producers
fromHandle
+ , fromHandleLn
, stdin
, readFile
+ , readFileLn
-- * Consumers
, toHandle
, stdout
import qualified Data.Text.IO as T
import Pipes
import qualified Pipes.Safe.Prelude as Safe
-import qualified Pipes.Safe as Safe
-import Pipes.Safe (MonadSafe(..), Base(..))
+import Pipes.Safe (MonadSafe(..))
import Prelude hiding (readFile, writeFile)
{- $textio
- Where pipes IO replaces lazy IO, @Producer Text m r@ replaces lazy 'Text'.
+ Where pipes @IO@ replaces lazy @IO@, @Producer Text IO r@ replaces lazy 'Text'.
This module exports some convenient functions for producing and consuming
- pipes 'Text' in IO, with caveats described below. The main points are as in
- <https://hackage.haskell.org/package/pipes-bytestring-1.0.0/docs/Pipes-ByteString.html @Pipes.ByteString@>
+ pipes 'Text' in @IO@, namely, 'readFile', 'writeFile', 'fromHandle', 'toHandle',
+ 'stdin' and 'stdout'. Some caveats described below.
+
+ The main points are as in
+ <https://hackage.haskell.org/package/pipes-bytestring-1.0.0/docs/Pipes-ByteString.html Pipes.ByteString>:
+
+ A 'Handle' can be associated with a 'Producer' or 'Consumer' according
+ as it is read or written to.
- An 'IO.Handle' can be associated with a 'Producer' or 'Consumer' according as it is read or written to.
-
- To stream to or from 'IO.Handle's, one can use 'fromHandle' or 'toHandle'. For
- example, the following program copies a document from one file to another:
-
> import Pipes
> import qualified Pipes.Text as Text
> import qualified Pipes.Text.IO as Text
>
> main = runSafeT $ runEffect $ Text.readFile "inFile.txt" >-> Text.writeFile "outFile.txt"
- You can stream to and from 'stdin' and 'stdout' using the predefined 'stdin'
+ Finally, you can stream to and from 'stdin' and 'stdout' using the predefined 'stdin'
and 'stdout' pipes, as with the following \"echo\" program:
> main = runEffect $ Text.stdin >-> Text.stdout
+
-}
* Like the functions in @Data.Text.IO@, they attempt to work with the system encoding.
- * Like the functions in @Data.Text.IO@, they are slower than ByteString operations. Where
+ * Like the functions in @Data.Text.IO@, they significantly slower than ByteString operations. Where
you know what encoding you are working with, use @Pipes.ByteString@ and @Pipes.Text.Encoding@ instead,
e.g. @view utf8 Bytes.stdin@ instead of @Text.stdin@
- * Like the functions in @Data.Text.IO@ , they use Text exceptions.
+ * Like the functions in @Data.Text.IO@ , they use Text exceptions, not the standard Pipes protocols.
Something like
go
{-# INLINABLE fromHandle#-}
+
+fromHandleLn :: MonadIO m => IO.Handle -> Producer Text m ()
+fromHandleLn h = go where
+ getLine :: IO (Either G.IOException Text)
+ getLine = try (T.hGetLine h)
+
+ go = do txt <- liftIO getLine
+ case txt of
+ Left e -> return ()
+ Right y -> do yield y
+ go
+{-# INLINABLE fromHandleLn #-}
+
-- | Stream text from 'stdin'
stdin :: MonadIO m => Producer Text m ()
stdin = fromHandle IO.stdin
{-# INLINE readFile #-}
+{-| Stream lines of text from a file
+-}
+readFileLn :: MonadSafe m => FilePath -> Producer Text m ()
+readFileLn file = Safe.withFile file IO.ReadMode fromHandleLn
+{-# INLINE readFileLn #-}
+
+
{-| Stream text to 'stdout'
Unlike 'toHandle', 'stdout' gracefully terminates on a broken output pipe.
toHandle h = for cat (liftIO . T.hPutStr h)
{-# INLINABLE toHandle #-}
-{-# RULES "p >-> toHandle h" forall p h .
- p >-> toHandle h = for p (\txt -> liftIO (T.hPutStr h txt))
- #-}
-- | Stream text into a file. Uses @pipes-safe@.