{-#LANGUAGE RankNTypes#-}
module Pipes.Text.IO
(
fromHandle
, stdin
, readFile
, toHandle
, stdout
, writeFile
) where
import qualified System.IO as IO
import Control.Exception (throwIO, try)
import Foreign.C.Error (Errno(Errno), ePIPE)
import qualified GHC.IO.Exception as G
import Data.Text (Text)
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 Prelude hiding (readFile, writeFile)
fromHandle :: MonadIO m => IO.Handle -> Producer Text m ()
fromHandle h = go where
go = do txt <- liftIO (T.hGetChunk h)
if T.null txt then return ()
else do yield txt
go
stdin :: MonadIO m => Producer Text m ()
stdin = fromHandle IO.stdin
{-# INLINE stdin #-}
readFile :: MonadSafe m => FilePath -> Producer Text m ()
readFile file = Safe.withFile file IO.ReadMode fromHandle
{-# INLINE readFile #-}
stdout :: MonadIO m => Consumer' Text m ()
stdout = go
where
go = do
txt <- await
x <- liftIO $ try (T.putStr txt)
case x of
Left (G.IOError { G.ioe_type = G.ResourceVanished
, G.ioe_errno = Just ioe })
| Errno ioe == ePIPE
-> return ()
Left e -> liftIO (throwIO e)
Right () -> go
toHandle :: MonadIO m => IO.Handle -> Consumer' Text m r
toHandle h = for cat (liftIO . T.hPutStr h)
{-# RULES "p >-> toHandle h" forall p h .
p >-> toHandle h = for p (\txt -> liftIO (T.hPutStr h txt))
#-}
writeFile :: (MonadSafe m) => FilePath -> Consumer' Text m ()
writeFile file = Safe.withFile file IO.WriteMode toHandle
{-# INLINE writeFile #-}