module TDisplay.Output.Simple where import TDisplay import Data.List import System.IO.Unsafe {- | The TDisplaySimple object represents simple stdout strings with no other formatting. It is implemented via unsafePerformIO to avoid requiring render to be a Monad. The \"done\" value of TDisplaySimple is used to cause Haskell to evaluate the rendering method, as well as providing the return status from renderComplete. -} data TDisplaySimple = TDSimple { done::Bool } instance Show TDisplaySimple where show d = if done d then "" else "" instance TDisplay TDisplaySimple where render e _ = unsafePerformIO $ mapM_ render' e >> return (TDSimple True) where render' (TDString (TDTag _t f) s) | "text" `elem` f = putStr s | otherwise = return () render' (TDAtom m@(TDTag _t f)) | tdTag_EOL == m = putStrLn "" | tdTag_sep == m = putStr " " | "eol" `elem` f = putStrLn "" | "separator" `elem` f = putStr "\t" | otherwise = return () render' (TDGroup _ (Left g)) = subrender g render' (TDGroup _ (Right gs)) = subrender $ gs [] render' (TDHsepGroup _ (Left g)) = subrender $ i_sep $ nosep g render' (TDHsepGroup _ (Right gs)) = subrender $ i_sep $ nosep $ gs [] render' (TDVsepGroup _ (Left g)) = subrender $ i_eol $ noeol g render' (TDVsepGroup _ (Right gs)) = subrender $ i_eol $ noeol $ gs [] subrender = mapM_ render' nosep = filter ((/=) (TDAtom tdTag_sep)) noeol = filter ((/=) (TDAtom tdTag_EOL)) i_sep = intersperse (head tdSep) i_eol = intersperse (head tdEOL) renderComplete = done {- | runTDisplayIO is used to perform the necessary rendering in an IO Monad (e.g. main). It will render its argument until the display object returns true (for TDisplaySimple, this is usually a single rendering pass), and then output a completion message. The completion message is usually the empty string, indicating that the rendering has completed, but it may be an incomplete message if the renderComplete does not return true. The TDisplaySimple does not require complex, multi-pass rendering, but the variable result value causes Haskell to perform the rendering call to determine the value to pass (via show) to the final putStr IO monad operation, thereby ensuring the render occurs. -} runTDisplayIO :: [TDOutput] -> IO () runTDisplayIO x = return (until renderComplete (render x) (TDSimple False)) >>= putStrLn . show