module Hedgehog.Internal.Region (
Region(..)
, newEmptyRegion
, newOpenRegion
, openRegion
, setRegion
, displayRegions
, displayRegion
, moveToBottom
, finishRegion
) where
import Control.Concurrent.STM (STM, TVar)
import qualified Control.Concurrent.STM.TMVar as TMVar
import qualified Control.Concurrent.STM.TVar as TVar
import Control.Monad.Catch (MonadMask(..), bracket)
import Control.Monad.IO.Class (MonadIO(..))
import System.Console.Regions (ConsoleRegion, RegionLayout(..), LiftRegion(..))
import qualified System.Console.Regions as Console
data Body =
Empty
| Open ConsoleRegion
| Closed
newtype Region =
Region {
unRegion :: TVar Body
}
newEmptyRegion :: LiftRegion m => m Region
newEmptyRegion =
liftRegion $ do
ref <- TVar.newTVar Empty
pure $ Region ref
newOpenRegion :: LiftRegion m => m Region
newOpenRegion =
liftRegion $ do
region <- Console.openConsoleRegion Linear
ref <- TVar.newTVar $ Open region
pure $ Region ref
openRegion :: LiftRegion m => Region -> String -> m ()
openRegion (Region var) content =
liftRegion $ do
body <- TVar.readTVar var
case body of
Empty -> do
region <- Console.openConsoleRegion Linear
TVar.writeTVar var $ Open region
Console.setConsoleRegion region content
Open region ->
Console.setConsoleRegion region content
Closed ->
pure ()
setRegion :: LiftRegion m => Region -> String -> m ()
setRegion (Region var) content =
liftRegion $ do
body <- TVar.readTVar var
case body of
Empty ->
pure ()
Open region ->
Console.setConsoleRegion region content
Closed ->
pure ()
displayRegions :: (MonadIO m, MonadMask m) => m a -> m a
displayRegions io =
Console.displayConsoleRegions io
displayRegion ::
MonadIO m
=> MonadMask m
=> LiftRegion m
=> (Region -> m a)
-> m a
displayRegion =
displayRegions . bracket newOpenRegion finishRegion
moveToBottom :: Region -> STM ()
moveToBottom (Region var) =
liftRegion $ do
body <- TVar.readTVar var
case body of
Empty ->
pure ()
Open region -> do
mxs <- TMVar.tryTakeTMVar Console.regionList
case mxs of
Nothing ->
pure ()
Just xs0 ->
let
xs1 =
filter (/= region) xs0
in
TMVar.putTMVar Console.regionList (region : xs1)
Closed ->
pure ()
finishRegion :: LiftRegion m => Region -> m ()
finishRegion (Region var) =
liftRegion $ do
body <- TVar.readTVar var
case body of
Empty -> do
TVar.writeTVar var Closed
Open region -> do
content <- Console.getConsoleRegion region
Console.finishConsoleRegion region content
TVar.writeTVar var Closed
Closed ->
pure ()