module System.IO.Silently (
silence, hSilence,
capture, hCapture
) where
import GHC.IO.Handle (hDuplicate, hDuplicateTo)
import System.IO (Handle, stdout, hClose, openTempFile, openFile, IOMode(..))
import Control.Exception (bracket)
import System.Directory (removeFile,getTemporaryDirectory)
silence :: IO a -> IO a
silence = hSilence [stdout]
hSilence :: [Handle] -> IO a -> IO a
hSilence handles action = bracket (openFile "/dev/null" AppendMode)
hClose
prepareAndRun
where
prepareAndRun tmpHandle = go handles
where
go [] = action
go (h:hs) = bracket (do old <- hDuplicate h
hDuplicateTo tmpHandle h
return old)
(\old -> hDuplicateTo old h)
(\_ -> go hs)
getTempOrCurrentDirectory :: IO String
getTempOrCurrentDirectory = getTemporaryDirectory `Prelude.catch` (\ex -> return ".")
capture :: IO a -> IO (String, a)
capture = hCapture [stdout]
hCapture :: [Handle] -> IO a -> IO (String, a)
hCapture handles action = do
tmpDir <- getTempOrCurrentDirectory
bracket (openTempFile tmpDir "capture")
cleanup
prepareAndRun
where
cleanup (tmpFile,tmpHandle) = do
hClose tmpHandle
removeFile tmpFile
prepareAndRun (tmpFile,tmpHandle) = go handles
where
go [] = do
a <- action
hClose tmpHandle
str <- readFile tmpFile
forceList str
return (str,a)
go (h:hs) = bracket (do old <- hDuplicate h
hDuplicateTo tmpHandle h
return old)
(\old -> hDuplicateTo old h)
(\_ -> go hs)
forceList [] = return ()
forceList (x:xs) = forceList xs