packages feed

liblawless-0.19.0: Source/IO.hs

{-# LANGUAGE TemplateHaskell #-}
{-|
Module:             IO
Description:        General IO functions specialized for 'Printable' instances.
Copyright:          © 2016 All rights reserved.
License:            GPL-3
Maintainer:         Evan Cofsky <evan@theunixman.com>
Stability:          experimental
Portability:        POSIX
-}

module IO (
    putStr,
    putStrLn,
    managed,
    Managed,
    MonadManaged(..),
    runManaged,
    TempFile,
    tfPath,
    tfHandle,
    tempFile,
    MonadIO,
    liftIO,
    PIO.hSeek,
    PIO.SeekMode(..),
    PIO.IOMode(..),
    file,
    tfile,
    textMode,
    binaryMode,
    hIsEOF,
    hClose,
    doesFileExist,
    removeFile,
    PIO.Handle
    ) where

import Lawless
import Control.Monad.IO.Class
import qualified System.Path.Directory as D
import qualified System.Path.IO as PIO
import qualified Data.Text.IO as T
import Text
import Textual
import Path
import qualified System.Path.PartClass as PC
import Control.Monad.Managed.Safe
import Exception
import qualified System.IO as SIO

-- * Printable I/O to stdio

liftPrintble ∷ (MonadIO m, Printable p) ⇒ (Text → IO ()) → p → m ()
liftPrintble f p = liftIO $ f (buildText ∘ print $ p)

putStr ∷ (MonadIO m, Printable p) ⇒ p → m ()
putStr = liftPrintble T.putStr

putStrLn ∷ (MonadIO m, Printable p) ⇒ p → m ()
putStrLn = liftPrintble T.putStrLn

-- * Managed temporary files
data TempFile = TempFile {
    _tfPath ∷ AbsFile,
    _tfHandle ∷ PIO.Handle
    }
makeLenses ''TempFile

tempFile ∷ AbsDir → RelFile → Managed TempFile
tempFile pth tmpl =
    let
        open = do
            (p, h) ← liftIO $ PIO.openTempFile pth tmpl
            liftIO $ binaryMode h
            return $ TempFile p h

        close tf = do
            liftIO $ PIO.hClose $ tf ^. tfHandle
            liftIO $ D.removeFile $ tf ^. tfPath
    in
        managed $ bracket open close

-- * Managed files

-- | Binary files, no buffering.
file ∷ PC.AbsRel ar ⇒ File ar → PIO.IOMode → Managed PIO.Handle
file pth m = managed $ \fh → do
    liftIO $ PIO.withBinaryFile pth m $ \h → do
        binaryMode h
        fh h

-- | Text files, line-buffered.
tfile ∷ PC.AbsRel ar ⇒ File ar → PIO.IOMode → Managed PIO.Handle
tfile pth m =managed $ \fh → do
    liftIO $ PIO.withBinaryFile pth m $ \h → do
        textMode h
        fh h

textMode ∷ MonadIO m ⇒ PIO.Handle → m ()
textMode h = liftIO $
    PIO.hSetBuffering h PIO.LineBuffering >>
    PIO.hSetBinaryMode h False

binaryMode ∷ MonadIO m ⇒ PIO.Handle → m ()
binaryMode h = liftIO $
    PIO.hSetBuffering h PIO.NoBuffering >>
    PIO.hSetBinaryMode h True

-- * Lifted IO

hIsEOF ∷ MonadIO m ⇒ SIO.Handle → m Bool
hIsEOF = liftIO ∘ SIO.hIsEOF

hClose ∷ MonadIO m ⇒ SIO.Handle → m ()
hClose = liftIO ∘ SIO.hClose

doesFileExist ∷ (MonadIO m, PC.AbsRel ar) ⇒ File ar → m Bool
doesFileExist = liftIO ∘ D.doesFileExist

removeFile ∷ (MonadIO m, PC.AbsRel ar) ⇒ File ar → m ()
removeFile = liftIO ∘ D.removeFile