{-# OPTIONS_HADDOCK hide #-} module Graphics.Vty.Inline.Unsafe where import Graphics.Vty import Data.IORef import GHC.IO.Handle (hDuplicate) import System.IO (stdin, stdout, hSetBuffering, BufferMode(NoBuffering)) import System.IO.Unsafe import System.Posix.IO (handleToFd) globalVty :: IORef (Maybe Vty) {-# NOINLINE globalVty #-} globalVty = unsafePerformIO $ newIORef Nothing globalOutput :: IORef (Maybe Output) {-# NOINLINE globalOutput #-} globalOutput = unsafePerformIO $ newIORef Nothing mkDupeConfig :: IO Config mkDupeConfig = do hSetBuffering stdout NoBuffering hSetBuffering stdin NoBuffering stdinDupe <- hDuplicate stdin >>= handleToFd stdoutDupe <- hDuplicate stdout >>= handleToFd return $ defaultConfig { inputFd = Just stdinDupe, outputFd = Just stdoutDupe } -- | This will create a Vty instance using 'mkVty' and execute an IO -- action provided that instance. The created Vty instance will be -- stored to the unsafe 'IORef' 'globalVty'. -- -- This instance will use duplicates of the stdin and stdout Handles. withVty :: (Vty -> IO b) -> IO b withVty f = do mvty <- readIORef globalVty vty <- case mvty of Nothing -> do vty <- mkDupeConfig >>= mkVty writeIORef globalVty (Just vty) return vty Just vty -> return vty f vty withOutput :: (Output -> IO b) -> IO b withOutput f = do mout <- readIORef globalOutput out <- case mout of Nothing -> do config <- mappend <$> userConfig <*> mkDupeConfig out <- outputForConfig config writeIORef globalOutput (Just out) return out Just out -> return out f out