packages feed

ansiform-0.7.8.5: src/Ansiform/Internal/Render.hs

-- | Capture page, section and printer output as a string.
module Ansiform.Internal.Render (renderPage, renderSection, renderPrinter) where

--------------------------------------------------------------------------------
import           Control.Exception (bracket)
import           System.Directory (getTemporaryDirectory, removeFile)
import           System.IO (Handle, hClose, hFlush, openTempFile)
import           Ansiform.Internal.Page
import           Ansiform.Internal.Printer
import           Ansiform.Internal.Section
import           Ansiform.Internal.Settings


-- Rendering
--------------------------------------------------------------------------------

-- | Renders a page and returns the captured output.
renderPage :: Page -> Settings -> IO String
renderPage p s = snd <$> captureOutput (\h -> renderWithConfig h)
  where
    renderWithConfig h = do
        cfg <- runSettingsOn h s
        runPageIOOn h (return cfg) p

-- | Renders a section and returns the captured output.
renderSection :: Section -> Settings -> IO String
renderSection sec s = snd <$> captureOutput (\h -> renderWithConfig h)
  where
    renderWithConfig h = do
        cfg <- runSettingsOn h s
        runSectionIOOn h (return cfg) sec

-- | Renders a single printer and returns the captured output.
renderPrinter :: Printer -> Settings -> IO String
renderPrinter pr s = snd <$> captureOutput (\h -> renderWithConfig h)
  where
    renderWithConfig h = do
        cfg <- runSettingsOn h s
        runPrinterIOOn h (return cfg) pr


-- Support Functions
--------------------------------------------------------------------------------

-- Runs an action against a temporary output handle and returns its content.
captureOutput :: (Handle -> IO a) -> IO (a, String)
captureOutput action = do
    tmp <- getTemporaryDirectory
    bracket (openTempFile tmp "ansiform-render") cleanup $ \(path, h) -> do
        result <- action h
        hFlush h
        hClose h
        output <- readFile path
        length output `seq` return (result, output)
  where
    cleanup (path, h) = do
        hClose h
        removeFile path