]> git.immae.eu Git - github/fretlink/text-pipes.git/blobdiff - Pipes/Text/IO.hs
Merge pull request #18 from sid-kap/text_lines
[github/fretlink/text-pipes.git] / Pipes / Text / IO.hs
index 23aff6956422c08fb56bdf23cda50f7f33b089cf..51c69265a04ac49a9aaa047cf7b1952242efdc40 100644 (file)
@@ -11,8 +11,10 @@ module Pipes.Text.IO
    
    -- * Producers
    fromHandle
+   , fromHandleLn
    , stdin
    , readFile
+   , readFileLn
    -- * Consumers
    , toHandle
    , stdout
@@ -28,24 +30,21 @@ import qualified Data.Text as T
 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. 
+    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>
+    <https://hackage.haskell.org/package/pipes-bytestring-1.0.0/docs/Pipes-ByteString.html Pipes.ByteString>:
     
-    An 'IO.Handle' can be associated with a 'Producer' or 'Consumer' according 
+    A '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
@@ -65,11 +64,12 @@ To stream from files, the following is perhaps more Prelude-like (note that it u
 >
 > 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
 
+
 -}
 
 
@@ -121,6 +121,19 @@ fromHandle h =  go where
                                     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
@@ -138,6 +151,13 @@ readFile file = Safe.withFile file IO.ReadMode fromHandle
 {-# 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.
@@ -170,9 +190,6 @@ toHandle :: MonadIO m => IO.Handle -> Consumer' Text m r
 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@.