polysemy-process-0.12.0.0: lib/Polysemy/Process/Interpreter/Pty.hs
{-# options_haddock prune #-}
-- |Description: Pty Interpreters, Internal
module Polysemy.Process.Interpreter.Pty where
import Polysemy.Resume (Stop, interpretScopedResumable, stopEitherWith, stopNote, type (!!))
import Polysemy.Scoped (Scoped_)
import System.Posix (closeFd, fdToHandle, openPseudoTerminal)
import System.Posix.Pty (closePty, createPty, ptyDimensions, resizePty)
import Polysemy.Process.Data.PtyError (PtyError (PtyError))
import Polysemy.Process.Data.PtyResources (PtyResources (PtyResources, handle, primary, pty, secondary))
import Polysemy.Process.Effect.Pty (Cols (Cols), Pty (Handle, Resize, Size), Rows (Rows))
tryStop ::
Members [Stop PtyError, Embed IO] r =>
IO a ->
Sem r a
tryStop =
stopEitherWith PtyError <=< tryIOError
acquirePty ::
Member (Embed IO) r =>
Sem (Stop PtyError : r) PtyResources
acquirePty = do
(primary, secondary) <- tryStop openPseudoTerminal
pty <- stopNote (PtyError "no pty returned") =<< tryStop (createPty secondary)
handle <- tryStop (fdToHandle secondary)
pure PtyResources {..}
releasePty ::
Member (Embed IO) r =>
PtyResources ->
Sem r ()
releasePty PtyResources {primary, pty} = do
tryAny_ (closePty pty)
tryAny_ (closeFd primary)
withPty ::
Members [Resource, Embed IO] r =>
(PtyResources -> Sem (Stop PtyError : r) a) ->
Sem (Stop PtyError : r) a
withPty =
bracket acquirePty releasePty
-- |Interpret Pty as a 'System.Posix.Pty'.
interpretPty ::
Members [Resource, Embed IO] r =>
InterpreterFor (Scoped_ Pty !! PtyError) r
interpretPty =
interpretScopedResumable (const withPty) \ PtyResources {..} -> \case
Handle ->
pure handle
Resize rows cols -> do
tryStop (resizePty pty (fromIntegral rows, fromIntegral cols))
Size ->
bimap Rows Cols <$> tryStop (ptyDimensions pty)