-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Ungarble output from several threads or commands -- -- Lets multiple threads and external processes concurrently output to -- the console, without it getting all garbled up. -- -- Built on top of that is a way of defining multiple output regions, -- which are automatically laid out on the screen and can be individually -- updated by concurrent threads. Can be used for progress displays etc. -- @package concurrent-output @version 1.7.3 -- | Concurrent output handling, internals. -- -- May change at any time. module System.Console.Concurrent.Internal data OutputHandle OutputHandle :: TMVar Lock -> TMVar OutputBuffer -> TMVar OutputBuffer -> TMVar Integer -> TMVar [Async ()] -> TMVar () -> OutputHandle [outputLock] :: OutputHandle -> TMVar Lock [outputBuffer] :: OutputHandle -> TMVar OutputBuffer [errorBuffer] :: OutputHandle -> TMVar OutputBuffer [outputThreads] :: OutputHandle -> TMVar Integer [processWaiters] :: OutputHandle -> TMVar [Async ()] [waitForProcessLock] :: OutputHandle -> TMVar () data Lock Locked :: Lock -- | A shared global variable for the OutputHandle. globalOutputHandle :: OutputHandle -- | Holds a lock while performing an action. This allows the action to -- perform its own output to the console, without using functions from -- this module. -- -- While this is running, other threads that try to lockOutput will -- block. Any calls to outputConcurrent and -- createProcessConcurrent will not block, but the output will be -- buffered and displayed only once the action is done. lockOutput :: (MonadIO m, MonadMask m) => m a -> m a -- | Blocks until we have the output lock. takeOutputLock :: IO () -- | Tries to take the output lock, without blocking. tryTakeOutputLock :: IO Bool withLock :: (TMVar Lock -> STM a) -> IO a takeOutputLock' :: Bool -> IO Bool -- | Only safe to call after taking the output lock. dropOutputLock :: IO () -- | Use this around any actions that use outputConcurrent or -- createProcessConcurrent -- -- This is necessary to ensure that buffered concurrent output actually -- gets displayed before the program exits. withConcurrentOutput :: (MonadIO m, MonadMask m) => m a -> m a -- | Blocks until any processes started by createProcessConcurrent -- have finished, and any buffered output is displayed. Also blocks while -- lockOutput is is use. -- -- withConcurrentOutput calls this at the end, so you do not -- normally need to use this. flushConcurrentOutput :: IO () -- | Values that can be output. class Outputable v toOutput :: Outputable v => v -> Text -- | Displays a value to stdout. -- -- No newline is appended to the value, so if you want a newline, be sure -- to include it yourself. -- -- Uses locking to ensure that the whole output occurs atomically even -- when other threads are concurrently generating output. -- -- When something else is writing to the console at the same time, this -- does not block. It buffers the value, so it will be displayed once the -- other writer is done. outputConcurrent :: Outputable v => v -> IO () -- | Like outputConcurrent, but displays to stderr. -- -- (Does not throw an exception.) errorConcurrent :: Outputable v => v -> IO () outputConcurrent' :: Outputable v => StdHandle -> v -> IO () newtype ConcurrentProcessHandle ConcurrentProcessHandle :: ProcessHandle -> ConcurrentProcessHandle toConcurrentProcessHandle :: (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle) -> (Maybe Handle, Maybe Handle, Maybe Handle, ConcurrentProcessHandle) -- | Use this to wait for processes started with -- createProcessConcurrent and createProcessForeground, and -- get their exit status. -- -- Note that such processes are actually automatically waited for -- internally, so not calling this explicitly will not result in zombie -- processes. This behavior differs from waitForProcess waitForProcessConcurrent :: ConcurrentProcessHandle -> IO ExitCode asyncProcessWaiter :: IO () -> IO () -- | Wrapper around createProcess that prevents multiple processes -- that are running concurrently from writing to stdout/stderr at the -- same time. -- -- If the process does not output to stdout or stderr, it's run by -- createProcess entirely as usual. Only processes that can generate -- output are handled specially: -- -- A process is allowed to write to stdout and stderr in the usual way, -- assuming it can successfully take the output lock. -- -- When the output lock is held (ie, by another concurrent process, or -- because outputConcurrent is being called at the same time), the -- process is instead run with its stdout and stderr redirected to a -- buffer. The buffered output will be displayed as soon as the output -- lock becomes free. -- -- Currently only available on Unix systems, not Windows. createProcessConcurrent :: CreateProcess -> IO (Maybe Handle, Maybe Handle, Maybe Handle, ConcurrentProcessHandle) -- | Wrapper around createProcess that makes sure a process is run -- in the foreground, with direct access to stdout and stderr. Useful -- when eg, running an interactive process. createProcessForeground :: CreateProcess -> IO (Maybe Handle, Maybe Handle, Maybe Handle, ConcurrentProcessHandle) fgProcess :: CreateProcess -> IO (Maybe Handle, Maybe Handle, Maybe Handle, ConcurrentProcessHandle) bgProcess :: CreateProcess -> IO (Maybe Handle, Maybe Handle, Maybe Handle, ConcurrentProcessHandle) willOutput :: StdStream -> Bool -- | Buffered output. data OutputBuffer OutputBuffer :: [OutputBufferedActivity] -> OutputBuffer data StdHandle StdOut :: StdHandle StdErr :: StdHandle toHandle :: StdHandle -> Handle bufferFor :: StdHandle -> TMVar OutputBuffer data OutputBufferedActivity Output :: Text -> OutputBufferedActivity InTempFile :: FilePath -> Bool -> OutputBufferedActivity [tempFile] :: OutputBufferedActivity -> FilePath [endsInNewLine] :: OutputBufferedActivity -> Bool data AtEnd AtEnd :: AtEnd data BufSig BufSig :: BufSig setupOutputBuffer :: StdHandle -> Handle -> StdStream -> Handle -> IO (StdHandle, MVar OutputBuffer, TMVar BufSig, TMVar AtEnd) outputDrainer :: StdStream -> Handle -> MVar OutputBuffer -> TMVar BufSig -> TMVar AtEnd -> IO () registerOutputThread :: IO () unregisterOutputThread :: IO () bufferWriter :: [(StdHandle, MVar OutputBuffer, TMVar BufSig, TMVar AtEnd)] -> IO () addOutputBuffer :: OutputBufferedActivity -> OutputBuffer -> IO OutputBuffer -- | Adds a value to the output buffer for later display. -- -- Note that buffering large quantities of data this way will keep it -- resident in memory until it can be displayed. While -- outputConcurrent uses temp files if the buffer gets too big, -- this STM function cannot do so. bufferOutputSTM :: Outputable v => StdHandle -> v -> STM () bufferOutputSTM' :: StdHandle -> OutputBuffer -> STM () -- | A STM action that waits for some buffered output to become available, -- and returns it. -- -- The function can select a subset of output when only some is desired; -- the fst part is returned and the snd is left in the buffer. -- -- This will prevent it from being displayed in the usual way, so you'll -- need to use emitOutputBuffer to display it yourself. outputBufferWaiterSTM :: (OutputBuffer -> (OutputBuffer, OutputBuffer)) -> STM (StdHandle, OutputBuffer) waitAnyBuffer :: OutputBuffer -> (OutputBuffer, OutputBuffer) -- | Use with outputBufferWaiterSTM to make it only return buffered -- output that ends with a newline. Anything buffered without a newline -- is left in the buffer. waitCompleteLines :: OutputBuffer -> (OutputBuffer, OutputBuffer) endsNewLine :: Text -> Bool -- | Emits the content of the OutputBuffer to the Handle -- -- If you use this, you should use lockOutput to ensure you're the -- only thread writing to the console. emitOutputBuffer :: StdHandle -> OutputBuffer -> IO () instance GHC.Classes.Eq System.Console.Concurrent.Internal.AtEnd instance GHC.Classes.Eq System.Console.Concurrent.Internal.OutputBuffer instance GHC.Classes.Eq System.Console.Concurrent.Internal.OutputBufferedActivity instance System.Console.Concurrent.Internal.Outputable Data.Text.Internal.Text instance System.Console.Concurrent.Internal.Outputable GHC.Base.String -- | Concurrent output handling. -- --
--   import Control.Concurrent.Async
--   import System.Console.Concurrent
--   
--   main = withConcurrentOutput $
--   	outputConcurrent "washed the car\n"
--   		`concurrently`
--   outputConcurrent "walked the dog\n"
--   	`concurrently`
--   	createProcessConcurrent (proc "ls" [])
--   
module System.Console.Concurrent -- | Use this around any actions that use outputConcurrent or -- createProcessConcurrent -- -- This is necessary to ensure that buffered concurrent output actually -- gets displayed before the program exits. withConcurrentOutput :: (MonadIO m, MonadMask m) => m a -> m a -- | Values that can be output. class Outputable v toOutput :: Outputable v => v -> Text -- | Displays a value to stdout. -- -- No newline is appended to the value, so if you want a newline, be sure -- to include it yourself. -- -- Uses locking to ensure that the whole output occurs atomically even -- when other threads are concurrently generating output. -- -- When something else is writing to the console at the same time, this -- does not block. It buffers the value, so it will be displayed once the -- other writer is done. outputConcurrent :: Outputable v => v -> IO () -- | Like outputConcurrent, but displays to stderr. -- -- (Does not throw an exception.) errorConcurrent :: Outputable v => v -> IO () data ConcurrentProcessHandle -- | Wrapper around createProcess that prevents multiple processes -- that are running concurrently from writing to stdout/stderr at the -- same time. -- -- If the process does not output to stdout or stderr, it's run by -- createProcess entirely as usual. Only processes that can generate -- output are handled specially: -- -- A process is allowed to write to stdout and stderr in the usual way, -- assuming it can successfully take the output lock. -- -- When the output lock is held (ie, by another concurrent process, or -- because outputConcurrent is being called at the same time), the -- process is instead run with its stdout and stderr redirected to a -- buffer. The buffered output will be displayed as soon as the output -- lock becomes free. -- -- Currently only available on Unix systems, not Windows. createProcessConcurrent :: CreateProcess -> IO (Maybe Handle, Maybe Handle, Maybe Handle, ConcurrentProcessHandle) -- | Use this to wait for processes started with -- createProcessConcurrent and createProcessForeground, and -- get their exit status. -- -- Note that such processes are actually automatically waited for -- internally, so not calling this explicitly will not result in zombie -- processes. This behavior differs from waitForProcess waitForProcessConcurrent :: ConcurrentProcessHandle -> IO ExitCode -- | Wrapper around createProcess that makes sure a process is run -- in the foreground, with direct access to stdout and stderr. Useful -- when eg, running an interactive process. createProcessForeground :: CreateProcess -> IO (Maybe Handle, Maybe Handle, Maybe Handle, ConcurrentProcessHandle) -- | Blocks until any processes started by createProcessConcurrent -- have finished, and any buffered output is displayed. Also blocks while -- lockOutput is is use. -- -- withConcurrentOutput calls this at the end, so you do not -- normally need to use this. flushConcurrentOutput :: IO () -- | Holds a lock while performing an action. This allows the action to -- perform its own output to the console, without using functions from -- this module. -- -- While this is running, other threads that try to lockOutput will -- block. Any calls to outputConcurrent and -- createProcessConcurrent will not block, but the output will be -- buffered and displayed only once the action is done. lockOutput :: (MonadIO m, MonadMask m) => m a -> m a -- | Buffered output. data OutputBuffer data StdHandle StdOut :: StdHandle StdErr :: StdHandle -- | Adds a value to the output buffer for later display. -- -- Note that buffering large quantities of data this way will keep it -- resident in memory until it can be displayed. While -- outputConcurrent uses temp files if the buffer gets too big, -- this STM function cannot do so. bufferOutputSTM :: Outputable v => StdHandle -> v -> STM () -- | A STM action that waits for some buffered output to become available, -- and returns it. -- -- The function can select a subset of output when only some is desired; -- the fst part is returned and the snd is left in the buffer. -- -- This will prevent it from being displayed in the usual way, so you'll -- need to use emitOutputBuffer to display it yourself. outputBufferWaiterSTM :: (OutputBuffer -> (OutputBuffer, OutputBuffer)) -> STM (StdHandle, OutputBuffer) waitAnyBuffer :: OutputBuffer -> (OutputBuffer, OutputBuffer) -- | Use with outputBufferWaiterSTM to make it only return buffered -- output that ends with a newline. Anything buffered without a newline -- is left in the buffer. waitCompleteLines :: OutputBuffer -> (OutputBuffer, OutputBuffer) -- | Emits the content of the OutputBuffer to the Handle -- -- If you use this, you should use lockOutput to ensure you're the -- only thread writing to the console. emitOutputBuffer :: StdHandle -> OutputBuffer -> IO () -- | Console regions are displayed near the bottom of the console, and can -- be updated concurrently by threads. Any other output displayed using -- outputConcurrent and createProcessConcurrent will scroll -- up above the open console regions. -- -- For example, this program: -- --
--   import Control.Concurrent.Async
--   import Control.Concurrent
--   import System.Console.Concurrent
--   import System.Console.Regions
--   import System.Process
--   
--   main = displayConsoleRegions $ do
--   	mapConcurrently download [1..5]
--   	`concurrently` mapM_ message [1..10]
--   	`concurrently` createProcessConcurrent (proc "echo" ["hello world"])
--   
--   message :: Int -> IO ()
--   message n = do
--   	threadDelay 500000
--   	outputConcurrent ("Message " ++ show n ++ "\n")
--   
--   download :: Int -> IO ()
--   download n = withConsoleRegion Linear $ \r -> do
--   	setConsoleRegion r basemsg
--   	go n r
--     where
--   	basemsg = "Download " ++ show n
--   go c r
--   	| c < 1 = finishConsoleRegion r (basemsg ++ " done!")
--   		| otherwise = do
--   			threadDelay 1000000
--   			appendConsoleRegion r " ... "
--   			go (c-1) r
--   
-- -- Will display like this: -- --
--   Message 1
--   hello world
--   Message 2
--   Download 1 ...
--   Download 2 ...
--   Download 3 ...
--   
-- -- Once the 1st download has finished, and another message has displayed, -- the console will update like this: -- --
--   Message 1
--   hello world
--   Message 2
--   Download 1 done!
--   Message 3
--   Download 2 ... ...
--   Download 3 ... ...
--   
module System.Console.Regions -- | A handle allowing access to a region of the console. data ConsoleRegion -- | Controls how a region is laid out in the console. -- -- Here's an annotated example of how the console layout works. -- --
--   scrolling......
--   scrolling......
--   scrolling......
--   aaaaaa......... -- Linear
--   bbbbbbbbbbbbbbb -- Linear
--   bbb............       (expanded to multiple lines)
--   ccccccccc...... -- Linear
--   ddddeeeefffffff -- [InLine]
--   fffffggggg.....       (expanded to multiple lines)
--   
data RegionLayout Linear :: RegionLayout InLine :: ConsoleRegion -> RegionLayout -- | Values that can be displayed in a region. class ToRegionContent v toRegionContent :: ToRegionContent v => v -> RegionContent newtype RegionContent RegionContent :: (STM Text) -> RegionContent -- | Many actions in this module can be run in either the IO monad or the -- STM monad. Using STM allows making several changes to the displayed -- regions atomically, with the display updated a single time. class LiftRegion m liftRegion :: LiftRegion m => STM a -> m a -- | Handles all display for the other functions in this module. -- -- Note that this uses lockOutput, so it takes over all output to -- the console while the passed IO action is running. As well as -- displaying the console regions, this handles display of anything -- buffered by outputConcurrent and -- createProcessConcurrent. -- -- When standard output is not an ANSI capable terminal, console regions -- are not displayed. displayConsoleRegions :: (MonadIO m, MonadMask m) => m a -> m a -- | Runs the action with a new console region, closing the region when the -- action finishes or on exception. withConsoleRegion :: (LiftRegion m, MonadIO m, MonadMask m) => RegionLayout -> (ConsoleRegion -> m a) -> m a -- | Opens a new console region. openConsoleRegion :: LiftRegion m => RegionLayout -> m ConsoleRegion -- | Makes a new region, but does not add it to the display. newConsoleRegion :: (LiftRegion m) => ToRegionContent v => RegionLayout -> v -> m ConsoleRegion -- | Closes a console region. Once closed, the region is removed from the -- display. closeConsoleRegion :: LiftRegion m => ConsoleRegion -> m () -- | Sets the value of a console region. This will cause the console to be -- updated to display the new value. -- -- It's fine for the value to be longer than the terminal is wide, or to -- include newlines ('\n'). Regions expand to multiple lines as -- necessary. -- -- The value can include ANSI SGR escape sequences for changing the -- colors etc of all or part of a region. -- -- Other ANSI escape sequences, especially those doing cursor movement, -- will mess up the layouts of regions. Caveat emptor. setConsoleRegion :: (ToRegionContent v, LiftRegion m) => ConsoleRegion -> v -> m () -- | Appends a value to the current value of a console region. -- --
--   appendConsoleRegion progress "." -- add another dot to progress display
--   
appendConsoleRegion :: (Outputable v, LiftRegion m) => ConsoleRegion -> v -> m () -- | Closes the console region, and displays the passed value in the -- scrolling area above the active console regions. When Nothing is -- passed, displays the current value of the console region. finishConsoleRegion :: (Outputable v, LiftRegion m) => ConsoleRegion -> v -> m () -- | Gets the current content of a console region. getConsoleRegion :: LiftRegion m => ConsoleRegion -> m Text -- | Changes how a console region displays. -- -- Each time the region's value changes, the STM action is provided with -- the current value of the region, and returns the value to display. -- -- For example, this will prevent a region from ever displaying more than -- 10 characters wide, and will make it display text reversed: -- --
--   tuneDisplay myregion $ pure . T.take 10
--   tuneDisplay myregion $ pure . T.reverse
--   
-- -- Note that repeated calls to tuneDisplay are cumulative. -- -- Normally, the STM action should avoid retrying, as that would block -- all display updates. tuneDisplay :: LiftRegion m => ConsoleRegion -> (Text -> STM Text) -> m () -- | Gets the width of the console. -- -- On Unix, this is automatically updated when the terminal is resized. -- On Windows, it is only initialized on program start. consoleWidth :: STM Int -- | Get the height of the console. consoleHeight :: STM Int -- | All the regions that are currently displayed on the screen. -- -- The list is ordered from the bottom of the screen up. Reordering it -- will change the order in which regions are displayed. It's also fine -- to remove, duplicate, or add new regions to the list. regionList :: TMVar [ConsoleRegion] instance GHC.Show.Show System.Console.Regions.LineUpdate instance GHC.Classes.Eq System.Console.Regions.LineUpdate instance GHC.Classes.Eq System.Console.Regions.RegionLayout instance GHC.Classes.Eq System.Console.Regions.ConsoleRegion instance System.Console.Regions.LiftRegion GHC.Conc.Sync.STM instance System.Console.Regions.LiftRegion GHC.Types.IO instance System.Console.Regions.ToRegionContent GHC.Base.String instance System.Console.Regions.ToRegionContent Data.Text.Internal.Text instance System.Console.Regions.ToRegionContent (GHC.Conc.Sync.STM Data.Text.Internal.Text) -- | The functions exported by this module are intended to be drop-in -- replacements for those from System.Process, when converting a whole -- program to use System.Console.Concurrent. -- -- Not currently available on Windows. module System.Process.Concurrent -- | Calls createProcessConcurrent -- -- You should use the waitForProcess in this module on the resulting -- ProcessHandle. Using System.Process.waitForProcess instead can have -- mildly unexpected results. -- -- Not available on Windows. createProcess :: CreateProcess -> IO (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle) -- | Calls waitForProcessConcurrent -- -- You should only use this on a ProcessHandle obtained by calling -- createProcess from this module. Using this with a ProcessHandle -- obtained from System.Process.createProcess etc will have extremely -- unexpected results; it can wait a very long time before returning. waitForProcess :: ProcessHandle -> IO ExitCode