module Chiasma.Test.Tmux where

import qualified Chronos
import Chronos (datetimeToTime)
import Exon (exon)
import Hedgehog (TestT)
import Hedgehog.Internal.Property (Failure)
import Path (Abs, Dir, File, Path, relfile, (</>))
import Path.IO (createTempDir, doesFileExist, getTempDir, removeDirRecur)
import Polysemy.Chronos (ChronosTime, interpretTimeChronos)
import qualified Polysemy.Conc as Race
import Polysemy.Conc (interpretRace)
import qualified Polysemy.Log as Log
import Polysemy.Log (Severity (Trace), interpretLogStdoutLevelConc)
import Polysemy.Process (interpretSystemProcessNativeOpaqueSingle, resolveExecutable)
import qualified Polysemy.Process.Effect.Pty as Pty
import Polysemy.Process.Effect.Pty (Pty, withPty)
import qualified Polysemy.Process.Effect.SystemProcess as SystemProcess
import Polysemy.Process.Effect.SystemProcess (SystemProcess)
import Polysemy.Process.Interpreter.Pty (interpretPty)
import qualified Polysemy.Test as Test
import Polysemy.Test (Hedgehog, Test, TestError (TestError), runTestAuto)
import qualified Polysemy.Time as Time
import Polysemy.Time (MilliSeconds (MilliSeconds), Seconds (Seconds), mkDatetime)
import System.Process.Typed (ProcessConfig, StreamSpec, proc, setStderr, setStdin, setStdout, useHandleClose)

import Chiasma.Codec.Data.Pane (Pane)
import Chiasma.Codec.Data.Session (Session (Session))
import Chiasma.Command.Pane (capturePane)
import Chiasma.Data.CodecError (CodecError)
import Chiasma.Data.Panes (Panes)
import Chiasma.Data.RenderError (RenderError)
import Chiasma.Data.TmuxCommand (TmuxCommand (KillServer, ListSessions))
import Chiasma.Data.TmuxError (TmuxError)
import Chiasma.Data.TmuxNative (TmuxNative (..))
import Chiasma.Effect.Codec (Codec, NativeCodecE)
import qualified Chiasma.Effect.TmuxApi as TmuxApi
import Chiasma.Effect.TmuxClient (NativeTmux, TmuxClient)
import Chiasma.Interpreter.Codec (interpretCodecPanes, interpretCodecTmuxCommand)
import Chiasma.Interpreter.TmuxClient (interpretTmuxNative)
import Chiasma.Path (pathText)
import qualified Chiasma.Test.Data.TmuxTestConfig as TmuxTestConfig
import Chiasma.Test.Data.TmuxTestConfig (TmuxTestConfig (TmuxTestConfig))
import Chiasma.Tmux (withTmux)

xtermArgs :: Int -> Int -> Int -> [Text]
xtermArgs :: Int -> Int -> Int -> [Text]
xtermArgs Int
width Int
height Int
fontSize =
  [Item [Text]
"-geometry", Int -> Text
forall b a. (Show a, IsString b) => a -> b
show Int
width Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"x" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall b a. (Show a, IsString b) => a -> b
show Int
height, Item [Text]
"-fn", Text
"xft:monospace:size=" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall b a. (Show a, IsString b) => a -> b
show Int
fontSize, Item [Text]
"-e", Item [Text]
"tmux"]

bashrcContent :: [Text]
bashrcContent :: [Text]
bashrcContent =
  [
    Item [Text]
"PS1='$ '"
  ]

createTmuxConf ::
  Member Test r =>
  Path Abs File ->
  [Text] ->
  Sem r (Path Abs File)
createTmuxConf :: forall (r :: EffectRow).
Member Test r =>
Path Abs File -> [Text] -> Sem r (Path Abs File)
createTmuxConf Path Abs File
wait [Text]
content = do
  Path Abs File
bashrc <- [Text] -> Path Rel File -> Sem r (Path Abs File)
forall (r :: EffectRow).
Member Test r =>
[Text] -> Path Rel File -> Sem r (Path Abs File)
Test.tempFile [Text]
bashrcContent [relfile|bashrc|]
  [Text] -> Path Rel File -> Sem r (Path Abs File)
forall (r :: EffectRow).
Member Test r =>
[Text] -> Path Rel File -> Sem r (Path Abs File)
Test.tempFile (Path Abs File -> [Text]
forall {l} {b} {t}. (IsList l, Item l ~ Text) => Path b t -> l
defaultContent Path Abs File
bashrc [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ [Text]
content [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ [Text]
initCommands) [relfile|tmux.conf|]
  where
    defaultContent :: Path b t -> l
defaultContent Path b t
rc =
      [[exon|set -g default-command '/usr/bin/env bash --noprofile --rcfile #{pathText rc}'|]]
    initCommands :: [Text]
initCommands =
      [
        [exon|run-shell -b 'touch #{pathText wait}'|]
      ]

testTmuxProcessConfig ::
  Members [Pty, Test, Embed IO] r =>
  Path Abs File ->
  TmuxTestConfig ->
  Path Abs File ->
  Sem r (ProcessConfig () () ())
testTmuxProcessConfig :: forall (r :: EffectRow).
Members '[Pty, Test, Embed IO] r =>
Path Abs File
-> TmuxTestConfig
-> Path Abs File
-> Sem r (ProcessConfig () () ())
testTmuxProcessConfig Path Abs File
wait (TmuxTestConfig {Bool
Int
[Text]
Severity
Rows
Cols
$sel:waitForPrompt:TmuxTestConfig :: TmuxTestConfig -> Bool
$sel:logLevel:TmuxTestConfig :: TmuxTestConfig -> Severity
$sel:conf:TmuxTestConfig :: TmuxTestConfig -> [Text]
$sel:gui:TmuxTestConfig :: TmuxTestConfig -> Bool
$sel:fontSize:TmuxTestConfig :: TmuxTestConfig -> Int
$sel:height:TmuxTestConfig :: TmuxTestConfig -> Cols
$sel:width:TmuxTestConfig :: TmuxTestConfig -> Rows
waitForPrompt :: Bool
logLevel :: Severity
conf :: [Text]
gui :: Bool
fontSize :: Int
height :: Cols
width :: Rows
..}) Path Abs File
socket = do
  Path Abs File
confFile <- Path Abs File -> [Text] -> Sem r (Path Abs File)
forall (r :: EffectRow).
Member Test r =>
Path Abs File -> [Text] -> Sem r (Path Abs File)
createTmuxConf Path Abs File
wait [Text]
conf
  Rows -> Cols -> Sem r ()
forall (r :: EffectRow). Member Pty r => Rows -> Cols -> Sem r ()
Pty.resize Rows
width Cols
height
  Handle
handle <- Sem r Handle
forall (r :: EffectRow). Member Pty r => Sem r Handle
Pty.handle
  let
    tmuxArgs :: [Text]
tmuxArgs =
      [Item [Text]
"-S", Path Abs File -> Text
forall b t. Path b t -> Text
pathText Path Abs File
socket, Item [Text]
"-f", Path Abs File -> Text
forall b t. Path b t -> Text
pathText Path Abs File
confFile]
    prc :: ProcessConfig () () ()
prc =
      if Bool
gui
      then FilePath -> [FilePath] -> ProcessConfig () () ()
proc FilePath
"xterm" (Text -> FilePath
forall a. ToString a => a -> FilePath
toString (Text -> FilePath) -> [Text] -> [FilePath]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Int -> Int -> [Text]
xtermArgs (Rows -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Rows
width) (Cols -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Cols
height) Int
fontSize [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ [Text]
tmuxArgs)
      else FilePath -> [FilePath] -> ProcessConfig () () ()
proc FilePath
"tmux" (Text -> FilePath
forall a. ToString a => a -> FilePath
toString (Text -> FilePath) -> [Text] -> [FilePath]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Text]
tmuxArgs)
  pure ((forall (st :: StreamType). StreamSpec st ())
-> ProcessConfig () () () -> ProcessConfig () () ()
forall {stdin0} {stdout0} {stderr0}.
(forall (st :: StreamType). StreamSpec st ())
-> ProcessConfig stdin0 stdout0 stderr0 -> ProcessConfig () () ()
stdio (Handle -> StreamSpec st ()
forall (anyStreamType :: StreamType).
Handle -> StreamSpec anyStreamType ()
useHandleClose Handle
handle) ProcessConfig () () ()
prc)
  where
    stdio :: (forall (st :: StreamType). StreamSpec st ())
-> ProcessConfig stdin0 stdout0 stderr0 -> ProcessConfig () () ()
stdio (forall (st :: StreamType). StreamSpec st ()
s ::  st . StreamSpec st ()) =
      StreamSpec 'STInput ()
-> ProcessConfig stdin0 () () -> ProcessConfig () () ()
forall stdin stdin0 stdout stderr.
StreamSpec 'STInput stdin
-> ProcessConfig stdin0 stdout stderr
-> ProcessConfig stdin stdout stderr
setStdin StreamSpec 'STInput ()
forall (st :: StreamType). StreamSpec st ()
s (ProcessConfig stdin0 () () -> ProcessConfig () () ())
-> (ProcessConfig stdin0 stdout0 stderr0
    -> ProcessConfig stdin0 () ())
-> ProcessConfig stdin0 stdout0 stderr0
-> ProcessConfig () () ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StreamSpec 'STOutput ()
-> ProcessConfig stdin0 stdout0 () -> ProcessConfig stdin0 () ()
forall stdout stdin stdout0 stderr.
StreamSpec 'STOutput stdout
-> ProcessConfig stdin stdout0 stderr
-> ProcessConfig stdin stdout stderr
setStdout StreamSpec 'STOutput ()
forall (st :: StreamType). StreamSpec st ()
s (ProcessConfig stdin0 stdout0 () -> ProcessConfig stdin0 () ())
-> (ProcessConfig stdin0 stdout0 stderr0
    -> ProcessConfig stdin0 stdout0 ())
-> ProcessConfig stdin0 stdout0 stderr0
-> ProcessConfig stdin0 () ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StreamSpec 'STOutput ()
-> ProcessConfig stdin0 stdout0 stderr0
-> ProcessConfig stdin0 stdout0 ()
forall stderr stdin stdout stderr0.
StreamSpec 'STOutput stderr
-> ProcessConfig stdin stdout stderr0
-> ProcessConfig stdin stdout stderr
setStderr StreamSpec 'STOutput ()
forall (st :: StreamType). StreamSpec st ()
s

waitForServer ::
   enc dec t d r .
  Members [Scoped_ (TmuxClient enc dec) !! TmuxError, Codec TmuxCommand enc dec !! CodecError, Time t d] r =>
  Sem r ()
waitForServer :: forall enc dec t d (r :: EffectRow).
Members
  '[Scoped_ (TmuxClient enc dec) !! TmuxError,
    Codec TmuxCommand enc dec !! CodecError, Time t d]
  r =>
Sem r ()
waitForServer =
  MilliSeconds -> Sem r Bool -> Sem r ()
forall t d u (r :: EffectRow).
(Member (Time t d) r, TimeUnit u) =>
u -> Sem r Bool -> Sem r ()
Time.while (Int64 -> MilliSeconds
MilliSeconds Int64
10) do
    forall err (eff :: (* -> *) -> * -> *) (r :: EffectRow) a.
Member (Resumable err eff) r =>
a -> Sem (eff : r) a -> Sem r a
resumeAs @CodecError @(Codec _ _ _) Bool
True (Sem (Codec TmuxCommand enc dec : r) Bool -> Sem r Bool)
-> Sem (Codec TmuxCommand enc dec : r) Bool -> Sem r Bool
forall a b. (a -> b) -> a -> b
$ forall err (eff :: (* -> *) -> * -> *) (r :: EffectRow) a.
Member (Resumable err eff) r =>
a -> Sem (eff : r) a -> Sem r a
resumeAs @TmuxError @(Scoped_ _) Bool
True (Sem
   (Scoped_ (TmuxClient enc dec) : Codec TmuxCommand enc dec : r) Bool
 -> Sem (Codec TmuxCommand enc dec : r) Bool)
-> Sem
     (Scoped_ (TmuxClient enc dec) : Codec TmuxCommand enc dec : r) Bool
-> Sem (Codec TmuxCommand enc dec : r) Bool
forall a b. (a -> b) -> a -> b
$ Sem
  ((TmuxApi TmuxCommand !! CodecError)
     : Scoped_ (TmuxClient enc dec) : Codec TmuxCommand enc dec : r)
  Bool
-> Sem
     (Scoped_ (TmuxClient enc dec) : Codec TmuxCommand enc dec : r) Bool
forall (command :: * -> *) err i o (r :: EffectRow).
Members '[ScopedTmux i o, Codec command i o !! err] r =>
InterpreterFor (TmuxApi command !! err) r
withTmux do
      [Session]
s <- [] [Session]
-> Sem
     (TmuxApi TmuxCommand
        : (TmuxApi TmuxCommand !! CodecError)
        : Scoped_ (TmuxClient enc dec) : Codec TmuxCommand enc dec : r)
     [Session]
-> Sem
     ((TmuxApi TmuxCommand !! CodecError)
        : Scoped_ (TmuxClient enc dec) : Codec TmuxCommand enc dec : r)
     [Session]
forall err (eff :: (* -> *) -> * -> *) (r :: EffectRow) a.
Member (Resumable err eff) r =>
a -> Sem (eff : r) a -> Sem r a
<! TmuxCommand [Session]
-> Sem
     (TmuxApi TmuxCommand
        : (TmuxApi TmuxCommand !! CodecError)
        : Scoped_ (TmuxClient enc dec) : Codec TmuxCommand enc dec : r)
     [Session]
forall (command :: * -> *) (r :: EffectRow) a.
Member (TmuxApi command) r =>
command a -> Sem r a
TmuxApi.send TmuxCommand [Session]
ListSessions
      pure ([Session]
s [Session] -> [Session] -> Bool
forall a. Eq a => a -> a -> Bool
/= [SessionId -> Text -> Session
Session SessionId
0 Text
"0"])

waitForEmptyPrompt ::
   enc dec t d r .
  Members [Scoped_ (TmuxClient enc dec) !! TmuxError, Codec TmuxCommand enc dec !! CodecError, Time t d] r =>
  Sem r ()
waitForEmptyPrompt :: forall enc dec t d (r :: EffectRow).
Members
  '[Scoped_ (TmuxClient enc dec) !! TmuxError,
    Codec TmuxCommand enc dec !! CodecError, Time t d]
  r =>
Sem r ()
waitForEmptyPrompt =
  MilliSeconds -> Sem r Bool -> Sem r ()
forall t d u (r :: EffectRow).
(Member (Time t d) r, TimeUnit u) =>
u -> Sem r Bool -> Sem r ()
Time.while (Int64 -> MilliSeconds
MilliSeconds Int64
10) do
    forall err (eff :: (* -> *) -> * -> *) (r :: EffectRow) a.
Member (Resumable err eff) r =>
a -> Sem (eff : r) a -> Sem r a
resumeAs @CodecError @(Codec _ _ _) Bool
True (Sem (Codec TmuxCommand enc dec : r) Bool -> Sem r Bool)
-> Sem (Codec TmuxCommand enc dec : r) Bool -> Sem r Bool
forall a b. (a -> b) -> a -> b
$ forall err (eff :: (* -> *) -> * -> *) (r :: EffectRow) a.
Member (Resumable err eff) r =>
a -> Sem (eff : r) a -> Sem r a
resumeAs @TmuxError @(Scoped_ _) Bool
True (Sem
   (Scoped_ (TmuxClient enc dec) : Codec TmuxCommand enc dec : r) Bool
 -> Sem (Codec TmuxCommand enc dec : r) Bool)
-> Sem
     (Scoped_ (TmuxClient enc dec) : Codec TmuxCommand enc dec : r) Bool
-> Sem (Codec TmuxCommand enc dec : r) Bool
forall a b. (a -> b) -> a -> b
$ Sem
  ((TmuxApi TmuxCommand !! CodecError)
     : Scoped_ (TmuxClient enc dec) : Codec TmuxCommand enc dec : r)
  Bool
-> Sem
     (Scoped_ (TmuxClient enc dec) : Codec TmuxCommand enc dec : r) Bool
forall (command :: * -> *) err i o (r :: EffectRow).
Members '[ScopedTmux i o, Codec command i o !! err] r =>
InterpreterFor (TmuxApi command !! err) r
withTmux do
      [Text]
prompt <- [] [Text]
-> Sem
     (TmuxApi TmuxCommand
        : (TmuxApi TmuxCommand !! CodecError)
        : Scoped_ (TmuxClient enc dec) : Codec TmuxCommand enc dec : r)
     [Text]
-> Sem
     ((TmuxApi TmuxCommand !! CodecError)
        : Scoped_ (TmuxClient enc dec) : Codec TmuxCommand enc dec : r)
     [Text]
forall err (eff :: (* -> *) -> * -> *) (r :: EffectRow) a.
Member (Resumable err eff) r =>
a -> Sem (eff : r) a -> Sem r a
<! PaneId
-> Sem
     (TmuxApi TmuxCommand
        : (TmuxApi TmuxCommand !! CodecError)
        : Scoped_ (TmuxClient enc dec) : Codec TmuxCommand enc dec : r)
     [Text]
forall (r :: EffectRow).
Member (TmuxApi TmuxCommand) r =>
PaneId -> Sem r [Text]
capturePane PaneId
0
      pure ([Item [Text]
"$"] [Text] -> [Text] -> Bool
forall a. Eq a => a -> a -> Bool
/= [Text]
prompt)

waitForFile ::
  Members [Time t d, Embed IO] r =>
  Path Abs File ->
  Sem r ()
waitForFile :: forall t d (r :: EffectRow).
Members '[Time t d, Embed IO] r =>
Path Abs File -> Sem r ()
waitForFile Path Abs File
file =
  MilliSeconds -> Sem r Bool -> Sem r ()
forall t d u (r :: EffectRow).
(Member (Time t d) r, TimeUnit u) =>
u -> Sem r Bool -> Sem r ()
Time.while (Int64 -> MilliSeconds
MilliSeconds Int64
10) do
    Bool -> Bool
not (Bool -> Bool) -> Sem r Bool -> Sem r Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Path Abs File -> Sem r Bool
forall (m :: * -> *) b. MonadIO m => Path b File -> m Bool
doesFileExist Path Abs File
file

runAndKillTmux ::
   err enc dec t d r a .
  Members [Scoped_ (TmuxClient enc dec) !! TmuxError, Codec TmuxCommand enc dec !! CodecError] r =>
  Members [SystemProcess !! err, Time t d, Log, Resource, Error Text, Race, Embed IO] r =>
  Bool ->
  Sem r a ->
  Sem r a
runAndKillTmux :: forall err enc dec t d (r :: EffectRow) a.
(Members
   '[Scoped_ (TmuxClient enc dec) !! TmuxError,
     Codec TmuxCommand enc dec !! CodecError]
   r,
 Members
   '[SystemProcess !! err, Time t d, Log, Resource, Error Text, Race,
     Embed IO]
   r) =>
Bool -> Sem r a -> Sem r a
runAndKillTmux Bool
waitForPrompt Sem r a
thunk = do
  Sem r (Either Any ()) -> Sem r ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Sem r Any -> Seconds -> Sem r () -> Sem r (Either Any ())
forall a b u (r :: EffectRow).
(TimeUnit u, Member Race r) =>
Sem r a -> u -> Sem r b -> Sem r (Either a b)
Race.timeout (Text -> Sem r Any
forall e (r :: EffectRow) a. Member (Error e) r => e -> Sem r a
throw Text
"tmux didn't create sessions") (Int64 -> Seconds
Seconds Int64
3) Sem r ()
forall enc dec t d (r :: EffectRow).
Members
  '[Scoped_ (TmuxClient enc dec) !! TmuxError,
    Codec TmuxCommand enc dec !! CodecError, Time t d]
  r =>
Sem r ()
waitForServer)
  Bool -> Sem r () -> Sem r ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
waitForPrompt do
    Sem r (Either Any ()) -> Sem r ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Sem r Any -> Seconds -> Sem r () -> Sem r (Either Any ())
forall a b u (r :: EffectRow).
(TimeUnit u, Member Race r) =>
Sem r a -> u -> Sem r b -> Sem r (Either a b)
Race.timeout (Text -> Sem r Any
forall e (r :: EffectRow) a. Member (Error e) r => e -> Sem r a
throw Text
"empty prompt did not appear in pane 0") (Int64 -> Seconds
Seconds Int64
3) Sem r ()
forall enc dec t d (r :: EffectRow).
Members
  '[Scoped_ (TmuxClient enc dec) !! TmuxError,
    Codec TmuxCommand enc dec !! CodecError, Time t d]
  r =>
Sem r ()
waitForEmptyPrompt)
  a
result <- Sem r a -> Sem r () -> Sem r a
forall (r :: EffectRow) a b.
Member Resource r =>
Sem r a -> Sem r b -> Sem r a
finally Sem r a
thunk do
    forall err (eff :: (* -> *) -> * -> *) (r :: EffectRow) a.
Member (Resumable err eff) r =>
Sem (eff : r) a -> Sem r a -> Sem r a
resumeWith @_ @(Scoped_ _) (Sem
  ((TmuxApi TmuxCommand !! CodecError)
     : Scoped_ (TmuxClient enc dec) : r)
  ()
-> Sem (Scoped_ (TmuxClient enc dec) : r) ()
forall (command :: * -> *) err i o (r :: EffectRow).
Members '[ScopedTmux i o, Codec command i o !! err] r =>
InterpreterFor (TmuxApi command !! err) r
withTmux (Sem
  (TmuxApi TmuxCommand
     : (TmuxApi TmuxCommand !! CodecError)
     : Scoped_ (TmuxClient enc dec) : r)
  ()
-> Sem
     ((TmuxApi TmuxCommand !! CodecError)
        : Scoped_ (TmuxClient enc dec) : r)
     ()
forall err (eff :: (* -> *) -> * -> *) (r :: EffectRow).
Member (Resumable err eff) r =>
Sem (eff : r) () -> Sem r ()
resume_ (TmuxCommand ()
-> Sem
     (TmuxApi TmuxCommand
        : (TmuxApi TmuxCommand !! CodecError)
        : Scoped_ (TmuxClient enc dec) : r)
     ()
forall (command :: * -> *) (r :: EffectRow) a.
Member (TmuxApi command) r =>
command a -> Sem r a
TmuxApi.send TmuxCommand ()
KillServer))) (Text -> Sem r ()
forall (r :: EffectRow).
(HasCallStack, Member Log r) =>
Text -> Sem r ()
Log.error Text
"failed to kill server")
    Sem (SystemProcess : r) () -> Sem r ()
forall err (eff :: (* -> *) -> * -> *) (r :: EffectRow).
Member (Resumable err eff) r =>
Sem (eff : r) () -> Sem r ()
resume_ Sem (SystemProcess : r) ()
forall (r :: EffectRow). Member SystemProcess r => Sem r ()
SystemProcess.kill
  a
result a -> Sem r () -> Sem r a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Sem (SystemProcess : r) () -> Sem r ()
forall err (eff :: (* -> *) -> * -> *) (r :: EffectRow).
Member (Resumable err eff) r =>
Sem (eff : r) () -> Sem r ()
resume_ (Sem (SystemProcess : r) ExitCode -> Sem (SystemProcess : r) ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void Sem (SystemProcess : r) ExitCode
forall (r :: EffectRow). Member SystemProcess r => Sem r ExitCode
SystemProcess.wait)

type TestTmuxEffects =
  [
    NativeTmux,
    NativeTmux !! TmuxError,
    NativeCodecE TmuxCommand,
    NativeCodecE (Panes Pane),
    Reader TmuxNative
  ]

withTestTmux ::
  Members [Test, Time t d, Log, Resource, Stop TmuxError, Error Text, Race, Async, Embed IO] r =>
  TmuxTestConfig ->
  Sem (TestTmuxEffects ++ r) a ->
  Path Abs Dir ->
  Sem r a
withTestTmux :: forall t d (r :: EffectRow) a.
Members
  '[Test, Time t d, Log, Resource, Stop TmuxError, Error Text, Race,
    Async, Embed IO]
  r =>
TmuxTestConfig
-> Sem (TestTmuxEffects ++ r) a -> Path Abs Dir -> Sem r a
withTestTmux tConf :: TmuxTestConfig
tConf@TmuxTestConfig {Bool
waitForPrompt :: Bool
$sel:waitForPrompt:TmuxTestConfig :: TmuxTestConfig -> Bool
waitForPrompt} Sem (Append TestTmuxEffects r) a
thunk Path Abs Dir
tempDir = do
  let socket :: Path Abs File
socket = Path Abs Dir
tempDir Path Abs Dir -> Path Rel File -> Path Abs File
forall b t. Path b Dir -> Path Rel t -> Path b t
</> [relfile|tmux_socket|]
  let wait :: Path Abs File
wait = Path Abs Dir
tempDir Path Abs Dir -> Path Rel File -> Path Abs File
forall b t. Path b Dir -> Path Rel t -> Path b t
</> [relfile|wait|]
  Path Abs File
exe <- Either Text (Path Abs File) -> Sem r (Path Abs File)
forall e (r :: EffectRow) a.
Member (Error e) r =>
Either e a -> Sem r a
fromEither (Either Text (Path Abs File) -> Sem r (Path Abs File))
-> Sem r (Either Text (Path Abs File)) -> Sem r (Path Abs File)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Path Rel File
-> Maybe (Path Abs File) -> Sem r (Either Text (Path Abs File))
forall (r :: EffectRow).
Member (Embed IO) r =>
Path Rel File
-> Maybe (Path Abs File) -> Sem r (Either Text (Path Abs File))
resolveExecutable [relfile|tmux|] Maybe (Path Abs File)
forall a. Maybe a
Nothing
  Sem (Resumable PtyError (Scoped_ Pty) : r) a -> Sem r a
forall (r :: EffectRow).
Members '[Resource, Embed IO] r =>
InterpreterFor (Resumable PtyError (Scoped_ Pty)) r
interpretPty (Sem (Resumable PtyError (Scoped_ Pty) : r) a -> Sem r a)
-> Sem (Resumable PtyError (Scoped_ Pty) : r) a -> Sem r a
forall a b. (a -> b) -> a -> b
$ forall err (eff :: (* -> *) -> * -> *) err' (r :: EffectRow) a.
Members '[Resumable err eff, Error err'] r =>
(err -> err') -> Sem (eff : r) a -> Sem r a
resumeHoistError @_ @(Scoped_ _) PtyError -> Text
forall b a. (Show a, IsString b) => a -> b
show (Sem (Scoped_ Pty : Resumable PtyError (Scoped_ Pty) : r) a
 -> Sem (Resumable PtyError (Scoped_ Pty) : r) a)
-> Sem (Scoped_ Pty : Resumable PtyError (Scoped_ Pty) : r) a
-> Sem (Resumable PtyError (Scoped_ Pty) : r) a
forall a b. (a -> b) -> a -> b
$ Sem (Pty : Scoped_ Pty : Resumable PtyError (Scoped_ Pty) : r) a
-> Sem (Scoped_ Pty : Resumable PtyError (Scoped_ Pty) : r) a
forall (r :: EffectRow).
Member (Scoped_ Pty) r =>
InterpreterFor Pty r
withPty do
    ProcessConfig () () ()
pc <- Path Abs File
-> TmuxTestConfig
-> Path Abs File
-> Sem
     (Pty : Scoped_ Pty : Resumable PtyError (Scoped_ Pty) : r)
     (ProcessConfig () () ())
forall (r :: EffectRow).
Members '[Pty, Test, Embed IO] r =>
Path Abs File
-> TmuxTestConfig
-> Path Abs File
-> Sem r (ProcessConfig () () ())
testTmuxProcessConfig Path Abs File
wait TmuxTestConfig
tConf Path Abs File
socket
    ProcessConfig () () ()
-> InterpreterFor
     (SystemProcess !! SystemProcessError)
     (Pty : Scoped_ Pty : Resumable PtyError (Scoped_ Pty) : r)
forall i o e (r :: EffectRow).
Members '[Resource, Embed IO] r =>
ProcessConfig i o e
-> InterpreterFor (SystemProcess !! SystemProcessError) r
interpretSystemProcessNativeOpaqueSingle ProcessConfig () () ()
pc (Sem
   ((SystemProcess !! SystemProcessError)
      : Pty : Scoped_ Pty : Resumable PtyError (Scoped_ Pty) : r)
   a
 -> Sem
      (Pty : Scoped_ Pty : Resumable PtyError (Scoped_ Pty) : r) a)
-> Sem
     ((SystemProcess !! SystemProcessError)
        : Pty : Scoped_ Pty : Resumable PtyError (Scoped_ Pty) : r)
     a
-> Sem (Pty : Scoped_ Pty : Resumable PtyError (Scoped_ Pty) : r) a
forall a b. (a -> b) -> a -> b
$ TmuxNative
-> Sem
     (Reader TmuxNative
        : (SystemProcess !! SystemProcessError) : Pty : Scoped_ Pty
        : Resumable PtyError (Scoped_ Pty) : r)
     a
-> Sem
     ((SystemProcess !! SystemProcessError)
        : Pty : Scoped_ Pty : Resumable PtyError (Scoped_ Pty) : r)
     a
forall i (r :: EffectRow) a. i -> Sem (Reader i : r) a -> Sem r a
runReader (Path Abs File -> Maybe (Path Abs File) -> TmuxNative
TmuxNative Path Abs File
exe (Path Abs File -> Maybe (Path Abs File)
forall a. a -> Maybe a
Just Path Abs File
socket)) do
      Sem
  (Reader TmuxNative
     : (SystemProcess !! SystemProcessError) : Pty : Scoped_ Pty
     : Resumable PtyError (Scoped_ Pty) : r)
  (Either Any ())
-> Sem
     (Reader TmuxNative
        : (SystemProcess !! SystemProcessError) : Pty : Scoped_ Pty
        : Resumable PtyError (Scoped_ Pty) : r)
     ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Sem
   (Reader TmuxNative
      : (SystemProcess !! SystemProcessError) : Pty : Scoped_ Pty
      : Resumable PtyError (Scoped_ Pty) : r)
   (Either Any ())
 -> Sem
      (Reader TmuxNative
         : (SystemProcess !! SystemProcessError) : Pty : Scoped_ Pty
         : Resumable PtyError (Scoped_ Pty) : r)
      ())
-> Sem
     (Reader TmuxNative
        : (SystemProcess !! SystemProcessError) : Pty : Scoped_ Pty
        : Resumable PtyError (Scoped_ Pty) : r)
     (Either Any ())
-> Sem
     (Reader TmuxNative
        : (SystemProcess !! SystemProcessError) : Pty : Scoped_ Pty
        : Resumable PtyError (Scoped_ Pty) : r)
     ()
forall a b. (a -> b) -> a -> b
$ Sem
  (Reader TmuxNative
     : (SystemProcess !! SystemProcessError) : Pty : Scoped_ Pty
     : Resumable PtyError (Scoped_ Pty) : r)
  Any
-> Seconds
-> Sem
     (Reader TmuxNative
        : (SystemProcess !! SystemProcessError) : Pty : Scoped_ Pty
        : Resumable PtyError (Scoped_ Pty) : r)
     ()
-> Sem
     (Reader TmuxNative
        : (SystemProcess !! SystemProcessError) : Pty : Scoped_ Pty
        : Resumable PtyError (Scoped_ Pty) : r)
     (Either Any ())
forall a b u (r :: EffectRow).
(TimeUnit u, Member Race r) =>
Sem r a -> u -> Sem r b -> Sem r (Either a b)
Race.timeout (Text
-> Sem
     (Reader TmuxNative
        : (SystemProcess !! SystemProcessError) : Pty : Scoped_ Pty
        : Resumable PtyError (Scoped_ Pty) : r)
     Any
forall e (r :: EffectRow) a. Member (Error e) r => e -> Sem r a
throw Text
"tmux didn't start") (Int64 -> Seconds
Seconds Int64
3) (Path Abs File
-> Sem
     (Reader TmuxNative
        : (SystemProcess !! SystemProcessError) : Pty : Scoped_ Pty
        : Resumable PtyError (Scoped_ Pty) : r)
     ()
forall t d (r :: EffectRow).
Members '[Time t d, Embed IO] r =>
Path Abs File -> Sem r ()
waitForFile Path Abs File
wait)
      Sem
  ((Codec (Panes Pane) TmuxRequest TmuxResponse !! CodecError)
     : Reader TmuxNative : (SystemProcess !! SystemProcessError) : Pty
     : Scoped_ Pty : Resumable PtyError (Scoped_ Pty) : r)
  a
-> Sem
     (Reader TmuxNative
        : (SystemProcess !! SystemProcessError) : Pty : Scoped_ Pty
        : Resumable PtyError (Scoped_ Pty) : r)
     a
forall p (r :: EffectRow).
TmuxCodec p =>
InterpreterFor
  (Codec (Panes p) TmuxRequest TmuxResponse !! CodecError) r
interpretCodecPanes (Sem
   ((Codec (Panes Pane) TmuxRequest TmuxResponse !! CodecError)
      : Reader TmuxNative : (SystemProcess !! SystemProcessError) : Pty
      : Scoped_ Pty : Resumable PtyError (Scoped_ Pty) : r)
   a
 -> Sem
      (Reader TmuxNative
         : (SystemProcess !! SystemProcessError) : Pty : Scoped_ Pty
         : Resumable PtyError (Scoped_ Pty) : r)
      a)
-> Sem
     ((Codec (Panes Pane) TmuxRequest TmuxResponse !! CodecError)
        : Reader TmuxNative : (SystemProcess !! SystemProcessError) : Pty
        : Scoped_ Pty : Resumable PtyError (Scoped_ Pty) : r)
     a
-> Sem
     (Reader TmuxNative
        : (SystemProcess !! SystemProcessError) : Pty : Scoped_ Pty
        : Resumable PtyError (Scoped_ Pty) : r)
     a
forall a b. (a -> b) -> a -> b
$ Sem
  ((Codec TmuxCommand TmuxRequest TmuxResponse !! CodecError)
     : (Codec (Panes Pane) TmuxRequest TmuxResponse !! CodecError)
     : Reader TmuxNative : (SystemProcess !! SystemProcessError) : Pty
     : Scoped_ Pty : Resumable PtyError (Scoped_ Pty) : r)
  a
-> Sem
     ((Codec (Panes Pane) TmuxRequest TmuxResponse !! CodecError)
        : Reader TmuxNative : (SystemProcess !! SystemProcessError) : Pty
        : Scoped_ Pty : Resumable PtyError (Scoped_ Pty) : r)
     a
forall (r :: EffectRow).
InterpreterFor
  (Codec TmuxCommand TmuxRequest TmuxResponse !! CodecError) r
interpretCodecTmuxCommand (Sem
   ((Codec TmuxCommand TmuxRequest TmuxResponse !! CodecError)
      : (Codec (Panes Pane) TmuxRequest TmuxResponse !! CodecError)
      : Reader TmuxNative : (SystemProcess !! SystemProcessError) : Pty
      : Scoped_ Pty : Resumable PtyError (Scoped_ Pty) : r)
   a
 -> Sem
      ((Codec (Panes Pane) TmuxRequest TmuxResponse !! CodecError)
         : Reader TmuxNative : (SystemProcess !! SystemProcessError) : Pty
         : Scoped_ Pty : Resumable PtyError (Scoped_ Pty) : r)
      a)
-> Sem
     ((Codec TmuxCommand TmuxRequest TmuxResponse !! CodecError)
        : (Codec (Panes Pane) TmuxRequest TmuxResponse !! CodecError)
        : Reader TmuxNative : (SystemProcess !! SystemProcessError) : Pty
        : Scoped_ Pty : Resumable PtyError (Scoped_ Pty) : r)
     a
-> Sem
     ((Codec (Panes Pane) TmuxRequest TmuxResponse !! CodecError)
        : Reader TmuxNative : (SystemProcess !! SystemProcessError) : Pty
        : Scoped_ Pty : Resumable PtyError (Scoped_ Pty) : r)
     a
forall a b. (a -> b) -> a -> b
$ Sem
  (Resumable
     TmuxError (Scoped () (TmuxClient TmuxRequest TmuxResponse))
     : (Codec TmuxCommand TmuxRequest TmuxResponse !! CodecError)
     : (Codec (Panes Pane) TmuxRequest TmuxResponse !! CodecError)
     : Reader TmuxNative : (SystemProcess !! SystemProcessError) : Pty
     : Scoped_ Pty : Resumable PtyError (Scoped_ Pty) : r)
  a
-> Sem
     ((Codec TmuxCommand TmuxRequest TmuxResponse !! CodecError)
        : (Codec (Panes Pane) TmuxRequest TmuxResponse !! CodecError)
        : Reader TmuxNative : (SystemProcess !! SystemProcessError) : Pty
        : Scoped_ Pty : Resumable PtyError (Scoped_ Pty) : r)
     a
forall (r :: EffectRow).
Members
  '[Reader TmuxNative, Log, Resource, Race, Async, Embed IO] r =>
InterpreterFor
  (Resumable
     TmuxError (Scoped () (TmuxClient TmuxRequest TmuxResponse)))
  r
interpretTmuxNative (Sem
   (Resumable
      TmuxError (Scoped () (TmuxClient TmuxRequest TmuxResponse))
      : (Codec TmuxCommand TmuxRequest TmuxResponse !! CodecError)
      : (Codec (Panes Pane) TmuxRequest TmuxResponse !! CodecError)
      : Reader TmuxNative : (SystemProcess !! SystemProcessError) : Pty
      : Scoped_ Pty : Resumable PtyError (Scoped_ Pty) : r)
   a
 -> Sem
      ((Codec TmuxCommand TmuxRequest TmuxResponse !! CodecError)
         : (Codec (Panes Pane) TmuxRequest TmuxResponse !! CodecError)
         : Reader TmuxNative : (SystemProcess !! SystemProcessError) : Pty
         : Scoped_ Pty : Resumable PtyError (Scoped_ Pty) : r)
      a)
-> Sem
     (Resumable
        TmuxError (Scoped () (TmuxClient TmuxRequest TmuxResponse))
        : (Codec TmuxCommand TmuxRequest TmuxResponse !! CodecError)
        : (Codec (Panes Pane) TmuxRequest TmuxResponse !! CodecError)
        : Reader TmuxNative : (SystemProcess !! SystemProcessError) : Pty
        : Scoped_ Pty : Resumable PtyError (Scoped_ Pty) : r)
     a
-> Sem
     ((Codec TmuxCommand TmuxRequest TmuxResponse !! CodecError)
        : (Codec (Panes Pane) TmuxRequest TmuxResponse !! CodecError)
        : Reader TmuxNative : (SystemProcess !! SystemProcessError) : Pty
        : Scoped_ Pty : Resumable PtyError (Scoped_ Pty) : r)
     a
forall a b. (a -> b) -> a -> b
$ forall err (eff :: (* -> *) -> * -> *) (r :: EffectRow).
Members '[Resumable err eff, Stop err] r =>
InterpreterFor eff r
restop @TmuxError do
        Bool
-> Sem
     (Scoped () (TmuxClient TmuxRequest TmuxResponse)
        : Resumable
            TmuxError (Scoped () (TmuxClient TmuxRequest TmuxResponse))
        : (Codec TmuxCommand TmuxRequest TmuxResponse !! CodecError)
        : (Codec (Panes Pane) TmuxRequest TmuxResponse !! CodecError)
        : Reader TmuxNative : (SystemProcess !! SystemProcessError) : Pty
        : Scoped_ Pty : Resumable PtyError (Scoped_ Pty) : r)
     a
-> Sem
     (Scoped () (TmuxClient TmuxRequest TmuxResponse)
        : Resumable
            TmuxError (Scoped () (TmuxClient TmuxRequest TmuxResponse))
        : (Codec TmuxCommand TmuxRequest TmuxResponse !! CodecError)
        : (Codec (Panes Pane) TmuxRequest TmuxResponse !! CodecError)
        : Reader TmuxNative : (SystemProcess !! SystemProcessError) : Pty
        : Scoped_ Pty : Resumable PtyError (Scoped_ Pty) : r)
     a
forall err enc dec t d (r :: EffectRow) a.
(Members
   '[Scoped_ (TmuxClient enc dec) !! TmuxError,
     Codec TmuxCommand enc dec !! CodecError]
   r,
 Members
   '[SystemProcess !! err, Time t d, Log, Resource, Error Text, Race,
     Embed IO]
   r) =>
Bool -> Sem r a -> Sem r a
runAndKillTmux Bool
waitForPrompt (forall (index :: Nat) (inserted :: EffectRow) (head :: EffectRow)
       (oldTail :: EffectRow) (tail :: EffectRow) (old :: EffectRow)
       (full :: EffectRow) a.
(ListOfLength index head, WhenStuck index InsertAtUnprovidedIndex,
 old ~ Append head oldTail, tail ~ Append inserted oldTail,
 full ~ Append head tail,
 InsertAtIndex index head tail oldTail full inserted) =>
Sem old a -> Sem full a
insertAt @5 Sem
  (Scoped () (TmuxClient TmuxRequest TmuxResponse)
     : Resumable
         TmuxError (Scoped () (TmuxClient TmuxRequest TmuxResponse))
     : (Codec TmuxCommand TmuxRequest TmuxResponse !! CodecError)
     : (Codec (Panes Pane) TmuxRequest TmuxResponse !! CodecError)
     : Reader TmuxNative : r)
  a
Sem (Append TestTmuxEffects r) a
thunk)

withTempDir ::
  Members [Resource, Embed IO] r =>
  Path Abs Dir ->
  (Path Abs Dir -> Sem r a) ->
  Sem r a
withTempDir :: forall (r :: EffectRow) a.
Members '[Resource, Embed IO] r =>
Path Abs Dir -> (Path Abs Dir -> Sem r a) -> Sem r a
withTempDir Path Abs Dir
targetDir =
  Sem r (Path Abs Dir)
-> (Path Abs Dir -> Sem r (Either Text ()))
-> (Path Abs Dir -> Sem r a)
-> Sem r a
forall (r :: EffectRow) a c b.
Member Resource r =>
Sem r a -> (a -> Sem r c) -> (a -> Sem r b) -> Sem r b
bracket
    (Path Abs Dir -> FilePath -> Sem r (Path Abs Dir)
forall (m :: * -> *) b.
MonadIO m =>
Path b Dir -> FilePath -> m (Path Abs Dir)
createTempDir Path Abs Dir
targetDir FilePath
"chiasma-test")
    (IO () -> Sem r (Either Text ())
forall (r :: EffectRow) a.
Member (Embed IO) r =>
IO a -> Sem r (Either Text a)
tryAny (IO () -> Sem r (Either Text ()))
-> (Path Abs Dir -> IO ())
-> Path Abs Dir
-> Sem r (Either Text ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Path Abs Dir -> IO ()
forall (m :: * -> *) b. MonadIO m => Path b Dir -> m ()
removeDirRecur)

withSystemTempDir ::
  Members [Resource, Embed IO] r =>
  (Path Abs Dir -> Sem r a) ->
  Sem r a
withSystemTempDir :: forall (r :: EffectRow) a.
Members '[Resource, Embed IO] r =>
(Path Abs Dir -> Sem r a) -> Sem r a
withSystemTempDir Path Abs Dir -> Sem r a
f = do
  Path Abs Dir
targetDir <- Sem r (Path Abs Dir)
forall (m :: * -> *). MonadIO m => m (Path Abs Dir)
getTempDir
  Path Abs Dir -> (Path Abs Dir -> Sem r a) -> Sem r a
forall (r :: EffectRow) a.
Members '[Resource, Embed IO] r =>
Path Abs Dir -> (Path Abs Dir -> Sem r a) -> Sem r a
withTempDir Path Abs Dir
targetDir Path Abs Dir -> Sem r a
f

type TestStack =
  TestTmuxEffects ++ [
    ChronosTime,
    Log,
    Stop CodecError,
    Error CodecError,
    Stop RenderError,
    Error RenderError,
    Stop TmuxError,
    Error TmuxError,
    Error Text,
    Race,
    Async,
    Test,
    Fail,
    Error TestError,
    Hedgehog IO,
    Error Failure,
    Embed IO,
    Resource,
    Final IO
  ]

testTime :: Chronos.Time
testTime :: Time
testTime =
  Datetime -> Time
datetimeToTime (Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> Datetime
forall dt.
Calendar dt =>
Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> dt
mkDatetime Int64
2030 Int64
3 Int64
20 Int64
12 Int64
0 Int64
0)

runTmuxTest ::
  TmuxTestConfig ->
  Sem TestStack a ->
  TestT IO a
runTmuxTest :: forall a. TmuxTestConfig -> Sem TestStack a -> TestT IO a
runTmuxTest TmuxTestConfig
conf Sem TestStack a
thunk =
  Sem
  '[Test, Fail, Error TestError, Hedgehog IO, Error Failure,
    Embed IO, Resource, Final IO]
  a
-> TestT IO a
forall a.
HasCallStack =>
Sem
  '[Test, Fail, Error TestError, Hedgehog IO, Error Failure,
    Embed IO, Resource, Final IO]
  a
-> TestT IO a
runTestAuto (Sem
   '[Test, Fail, Error TestError, Hedgehog IO, Error Failure,
     Embed IO, Resource, Final IO]
   a
 -> TestT IO a)
-> Sem
     '[Test, Fail, Error TestError, Hedgehog IO, Error Failure,
       Embed IO, Resource, Final IO]
     a
-> TestT IO a
forall a b. (a -> b) -> a -> b
$
  Sem
  '[Async, Test, Fail, Error TestError, Hedgehog IO, Error Failure,
    Embed IO, Resource, Final IO]
  a
-> Sem
     '[Test, Fail, Error TestError, Hedgehog IO, Error Failure,
       Embed IO, Resource, Final IO]
     a
forall (r :: EffectRow) a.
Member (Final IO) r =>
Sem (Async : r) a -> Sem r a
asyncToIOFinal (Sem
   '[Async, Test, Fail, Error TestError, Hedgehog IO, Error Failure,
     Embed IO, Resource, Final IO]
   a
 -> Sem
      '[Test, Fail, Error TestError, Hedgehog IO, Error Failure,
        Embed IO, Resource, Final IO]
      a)
-> Sem
     '[Async, Test, Fail, Error TestError, Hedgehog IO, Error Failure,
       Embed IO, Resource, Final IO]
     a
-> Sem
     '[Test, Fail, Error TestError, Hedgehog IO, Error Failure,
       Embed IO, Resource, Final IO]
     a
forall a b. (a -> b) -> a -> b
$
  Sem
  '[Race, Async, Test, Fail, Error TestError, Hedgehog IO,
    Error Failure, Embed IO, Resource, Final IO]
  a
-> Sem
     '[Async, Test, Fail, Error TestError, Hedgehog IO, Error Failure,
       Embed IO, Resource, Final IO]
     a
forall (r :: EffectRow).
Member (Final IO) r =>
InterpreterFor Race r
interpretRace (Sem
   '[Race, Async, Test, Fail, Error TestError, Hedgehog IO,
     Error Failure, Embed IO, Resource, Final IO]
   a
 -> Sem
      '[Async, Test, Fail, Error TestError, Hedgehog IO, Error Failure,
        Embed IO, Resource, Final IO]
      a)
-> Sem
     '[Race, Async, Test, Fail, Error TestError, Hedgehog IO,
       Error Failure, Embed IO, Resource, Final IO]
     a
-> Sem
     '[Async, Test, Fail, Error TestError, Hedgehog IO, Error Failure,
       Embed IO, Resource, Final IO]
     a
forall a b. (a -> b) -> a -> b
$
  (Text -> TestError)
-> Sem
     '[Error Text, Race, Async, Test, Fail, Error TestError,
       Hedgehog IO, Error Failure, Embed IO, Resource, Final IO]
     a
-> Sem
     '[Race, Async, Test, Fail, Error TestError, Hedgehog IO,
       Error Failure, Embed IO, Resource, Final IO]
     a
forall e1 e2 (r :: EffectRow) a.
Member (Error e2) r =>
(e1 -> e2) -> Sem (Error e1 : r) a -> Sem r a
mapError Text -> TestError
TestError (Sem
   '[Error Text, Race, Async, Test, Fail, Error TestError,
     Hedgehog IO, Error Failure, Embed IO, Resource, Final IO]
   a
 -> Sem
      '[Race, Async, Test, Fail, Error TestError, Hedgehog IO,
        Error Failure, Embed IO, Resource, Final IO]
      a)
-> Sem
     '[Error Text, Race, Async, Test, Fail, Error TestError,
       Hedgehog IO, Error Failure, Embed IO, Resource, Final IO]
     a
-> Sem
     '[Race, Async, Test, Fail, Error TestError, Hedgehog IO,
       Error Failure, Embed IO, Resource, Final IO]
     a
forall a b. (a -> b) -> a -> b
$
  (TmuxError -> Text)
-> Sem
     '[Error TmuxError, Error Text, Race, Async, Test, Fail,
       Error TestError, Hedgehog IO, Error Failure, Embed IO, Resource,
       Final IO]
     a
-> Sem
     '[Error Text, Race, Async, Test, Fail, Error TestError,
       Hedgehog IO, Error Failure, Embed IO, Resource, Final IO]
     a
forall e1 e2 (r :: EffectRow) a.
Member (Error e2) r =>
(e1 -> e2) -> Sem (Error e1 : r) a -> Sem r a
mapError TmuxError -> Text
forall b a. (Show a, IsString b) => a -> b
show (Sem
   '[Error TmuxError, Error Text, Race, Async, Test, Fail,
     Error TestError, Hedgehog IO, Error Failure, Embed IO, Resource,
     Final IO]
   a
 -> Sem
      '[Error Text, Race, Async, Test, Fail, Error TestError,
        Hedgehog IO, Error Failure, Embed IO, Resource, Final IO]
      a)
-> Sem
     '[Error TmuxError, Error Text, Race, Async, Test, Fail,
       Error TestError, Hedgehog IO, Error Failure, Embed IO, Resource,
       Final IO]
     a
-> Sem
     '[Error Text, Race, Async, Test, Fail, Error TestError,
       Hedgehog IO, Error Failure, Embed IO, Resource, Final IO]
     a
forall a b. (a -> b) -> a -> b
$
  Sem
  '[Stop TmuxError, Error TmuxError, Error Text, Race, Async, Test,
    Fail, Error TestError, Hedgehog IO, Error Failure, Embed IO,
    Resource, Final IO]
  a
-> Sem
     '[Error TmuxError, Error Text, Race, Async, Test, Fail,
       Error TestError, Hedgehog IO, Error Failure, Embed IO, Resource,
       Final IO]
     a
forall err (r :: EffectRow) a.
Member (Error err) r =>
Sem (Stop err : r) a -> Sem r a
stopToError (Sem
   '[Stop TmuxError, Error TmuxError, Error Text, Race, Async, Test,
     Fail, Error TestError, Hedgehog IO, Error Failure, Embed IO,
     Resource, Final IO]
   a
 -> Sem
      '[Error TmuxError, Error Text, Race, Async, Test, Fail,
        Error TestError, Hedgehog IO, Error Failure, Embed IO, Resource,
        Final IO]
      a)
-> Sem
     '[Stop TmuxError, Error TmuxError, Error Text, Race, Async, Test,
       Fail, Error TestError, Hedgehog IO, Error Failure, Embed IO,
       Resource, Final IO]
     a
-> Sem
     '[Error TmuxError, Error Text, Race, Async, Test, Fail,
       Error TestError, Hedgehog IO, Error Failure, Embed IO, Resource,
       Final IO]
     a
forall a b. (a -> b) -> a -> b
$
  forall e1 e2 (r :: EffectRow) a.
Member (Error e2) r =>
(e1 -> e2) -> Sem (Error e1 : r) a -> Sem r a
mapError @RenderError @Text RenderError -> Text
forall b a. (Show a, IsString b) => a -> b
show (Sem
   '[Error RenderError, Stop TmuxError, Error TmuxError, Error Text,
     Race, Async, Test, Fail, Error TestError, Hedgehog IO,
     Error Failure, Embed IO, Resource, Final IO]
   a
 -> Sem
      '[Stop TmuxError, Error TmuxError, Error Text, Race, Async, Test,
        Fail, Error TestError, Hedgehog IO, Error Failure, Embed IO,
        Resource, Final IO]
      a)
-> Sem
     '[Error RenderError, Stop TmuxError, Error TmuxError, Error Text,
       Race, Async, Test, Fail, Error TestError, Hedgehog IO,
       Error Failure, Embed IO, Resource, Final IO]
     a
-> Sem
     '[Stop TmuxError, Error TmuxError, Error Text, Race, Async, Test,
       Fail, Error TestError, Hedgehog IO, Error Failure, Embed IO,
       Resource, Final IO]
     a
forall a b. (a -> b) -> a -> b
$
  Sem
  '[Stop RenderError, Error RenderError, Stop TmuxError,
    Error TmuxError, Error Text, Race, Async, Test, Fail,
    Error TestError, Hedgehog IO, Error Failure, Embed IO, Resource,
    Final IO]
  a
-> Sem
     '[Error RenderError, Stop TmuxError, Error TmuxError, Error Text,
       Race, Async, Test, Fail, Error TestError, Hedgehog IO,
       Error Failure, Embed IO, Resource, Final IO]
     a
forall err (r :: EffectRow) a.
Member (Error err) r =>
Sem (Stop err : r) a -> Sem r a
stopToError (Sem
   '[Stop RenderError, Error RenderError, Stop TmuxError,
     Error TmuxError, Error Text, Race, Async, Test, Fail,
     Error TestError, Hedgehog IO, Error Failure, Embed IO, Resource,
     Final IO]
   a
 -> Sem
      '[Error RenderError, Stop TmuxError, Error TmuxError, Error Text,
        Race, Async, Test, Fail, Error TestError, Hedgehog IO,
        Error Failure, Embed IO, Resource, Final IO]
      a)
-> Sem
     '[Stop RenderError, Error RenderError, Stop TmuxError,
       Error TmuxError, Error Text, Race, Async, Test, Fail,
       Error TestError, Hedgehog IO, Error Failure, Embed IO, Resource,
       Final IO]
     a
-> Sem
     '[Error RenderError, Stop TmuxError, Error TmuxError, Error Text,
       Race, Async, Test, Fail, Error TestError, Hedgehog IO,
       Error Failure, Embed IO, Resource, Final IO]
     a
forall a b. (a -> b) -> a -> b
$
  forall e1 e2 (r :: EffectRow) a.
Member (Error e2) r =>
(e1 -> e2) -> Sem (Error e1 : r) a -> Sem r a
mapError @CodecError @Text CodecError -> Text
forall b a. (Show a, IsString b) => a -> b
show (Sem
   '[Error CodecError, Stop RenderError, Error RenderError,
     Stop TmuxError, Error TmuxError, Error Text, Race, Async, Test,
     Fail, Error TestError, Hedgehog IO, Error Failure, Embed IO,
     Resource, Final IO]
   a
 -> Sem
      '[Stop RenderError, Error RenderError, Stop TmuxError,
        Error TmuxError, Error Text, Race, Async, Test, Fail,
        Error TestError, Hedgehog IO, Error Failure, Embed IO, Resource,
        Final IO]
      a)
-> Sem
     '[Error CodecError, Stop RenderError, Error RenderError,
       Stop TmuxError, Error TmuxError, Error Text, Race, Async, Test,
       Fail, Error TestError, Hedgehog IO, Error Failure, Embed IO,
       Resource, Final IO]
     a
-> Sem
     '[Stop RenderError, Error RenderError, Stop TmuxError,
       Error TmuxError, Error Text, Race, Async, Test, Fail,
       Error TestError, Hedgehog IO, Error Failure, Embed IO, Resource,
       Final IO]
     a
forall a b. (a -> b) -> a -> b
$
  Sem
  '[Stop CodecError, Error CodecError, Stop RenderError,
    Error RenderError, Stop TmuxError, Error TmuxError, Error Text,
    Race, Async, Test, Fail, Error TestError, Hedgehog IO,
    Error Failure, Embed IO, Resource, Final IO]
  a
-> Sem
     '[Error CodecError, Stop RenderError, Error RenderError,
       Stop TmuxError, Error TmuxError, Error Text, Race, Async, Test,
       Fail, Error TestError, Hedgehog IO, Error Failure, Embed IO,
       Resource, Final IO]
     a
forall err (r :: EffectRow) a.
Member (Error err) r =>
Sem (Stop err : r) a -> Sem r a
stopToError (Sem
   '[Stop CodecError, Error CodecError, Stop RenderError,
     Error RenderError, Stop TmuxError, Error TmuxError, Error Text,
     Race, Async, Test, Fail, Error TestError, Hedgehog IO,
     Error Failure, Embed IO, Resource, Final IO]
   a
 -> Sem
      '[Error CodecError, Stop RenderError, Error RenderError,
        Stop TmuxError, Error TmuxError, Error Text, Race, Async, Test,
        Fail, Error TestError, Hedgehog IO, Error Failure, Embed IO,
        Resource, Final IO]
      a)
-> Sem
     '[Stop CodecError, Error CodecError, Stop RenderError,
       Error RenderError, Stop TmuxError, Error TmuxError, Error Text,
       Race, Async, Test, Fail, Error TestError, Hedgehog IO,
       Error Failure, Embed IO, Resource, Final IO]
     a
-> Sem
     '[Error CodecError, Stop RenderError, Error RenderError,
       Stop TmuxError, Error TmuxError, Error Text, Race, Async, Test,
       Fail, Error TestError, Hedgehog IO, Error Failure, Embed IO,
       Resource, Final IO]
     a
forall a b. (a -> b) -> a -> b
$
  Maybe Severity
-> InterpreterFor
     Log
     '[Stop CodecError, Error CodecError, Stop RenderError,
       Error RenderError, Stop TmuxError, Error TmuxError, Error Text,
       Race, Async, Test, Fail, Error TestError, Hedgehog IO,
       Error Failure, Embed IO, Resource, Final IO]
forall (r :: EffectRow).
Members '[Resource, Async, Race, Embed IO] r =>
Maybe Severity -> InterpreterFor Log r
interpretLogStdoutLevelConc (Severity -> Maybe Severity
forall a. a -> Maybe a
Just (TmuxTestConfig -> Severity
TmuxTestConfig.logLevel TmuxTestConfig
conf)) (Sem
   '[Log, Stop CodecError, Error CodecError, Stop RenderError,
     Error RenderError, Stop TmuxError, Error TmuxError, Error Text,
     Race, Async, Test, Fail, Error TestError, Hedgehog IO,
     Error Failure, Embed IO, Resource, Final IO]
   a
 -> Sem
      '[Stop CodecError, Error CodecError, Stop RenderError,
        Error RenderError, Stop TmuxError, Error TmuxError, Error Text,
        Race, Async, Test, Fail, Error TestError, Hedgehog IO,
        Error Failure, Embed IO, Resource, Final IO]
      a)
-> Sem
     '[Log, Stop CodecError, Error CodecError, Stop RenderError,
       Error RenderError, Stop TmuxError, Error TmuxError, Error Text,
       Race, Async, Test, Fail, Error TestError, Hedgehog IO,
       Error Failure, Embed IO, Resource, Final IO]
     a
-> Sem
     '[Stop CodecError, Error CodecError, Stop RenderError,
       Error RenderError, Stop TmuxError, Error TmuxError, Error Text,
       Race, Async, Test, Fail, Error TestError, Hedgehog IO,
       Error Failure, Embed IO, Resource, Final IO]
     a
forall a b. (a -> b) -> a -> b
$
  Sem
  '[ChronosTime, Log, Stop CodecError, Error CodecError,
    Stop RenderError, Error RenderError, Stop TmuxError,
    Error TmuxError, Error Text, Race, Async, Test, Fail,
    Error TestError, Hedgehog IO, Error Failure, Embed IO, Resource,
    Final IO]
  a
-> Sem
     '[Log, Stop CodecError, Error CodecError, Stop RenderError,
       Error RenderError, Stop TmuxError, Error TmuxError, Error Text,
       Race, Async, Test, Fail, Error TestError, Hedgehog IO,
       Error Failure, Embed IO, Resource, Final IO]
     a
forall (r :: EffectRow).
Member (Embed IO) r =>
InterpreterFor ChronosTime r
interpretTimeChronos do
    (Path Abs Dir
 -> Sem
      '[ChronosTime, Log, Stop CodecError, Error CodecError,
        Stop RenderError, Error RenderError, Stop TmuxError,
        Error TmuxError, Error Text, Race, Async, Test, Fail,
        Error TestError, Hedgehog IO, Error Failure, Embed IO, Resource,
        Final IO]
      a)
-> Sem
     '[ChronosTime, Log, Stop CodecError, Error CodecError,
       Stop RenderError, Error RenderError, Stop TmuxError,
       Error TmuxError, Error Text, Race, Async, Test, Fail,
       Error TestError, Hedgehog IO, Error Failure, Embed IO, Resource,
       Final IO]
     a
forall (r :: EffectRow) a.
Members '[Resource, Embed IO] r =>
(Path Abs Dir -> Sem r a) -> Sem r a
withSystemTempDir (TmuxTestConfig
-> Sem TestStack a
-> Path Abs Dir
-> Sem
     '[ChronosTime, Log, Stop CodecError, Error CodecError,
       Stop RenderError, Error RenderError, Stop TmuxError,
       Error TmuxError, Error Text, Race, Async, Test, Fail,
       Error TestError, Hedgehog IO, Error Failure, Embed IO, Resource,
       Final IO]
     a
forall t d (r :: EffectRow) a.
Members
  '[Test, Time t d, Log, Resource, Stop TmuxError, Error Text, Race,
    Async, Embed IO]
  r =>
TmuxTestConfig
-> Sem (TestTmuxEffects ++ r) a -> Path Abs Dir -> Sem r a
withTestTmux TmuxTestConfig
conf Sem TestStack a
thunk)

tmuxTest ::
  Sem TestStack a ->
  TestT IO a
tmuxTest :: forall a. Sem TestStack a -> TestT IO a
tmuxTest =
  TmuxTestConfig -> Sem TestStack a -> TestT IO a
forall a. TmuxTestConfig -> Sem TestStack a -> TestT IO a
runTmuxTest TmuxTestConfig
forall a. Default a => a
def

tmuxTestTrace ::
  Sem TestStack a ->
  TestT IO a
tmuxTestTrace :: forall a. Sem TestStack a -> TestT IO a
tmuxTestTrace =
  TmuxTestConfig -> Sem TestStack a -> TestT IO a
forall a. TmuxTestConfig -> Sem TestStack a -> TestT IO a
runTmuxTest TmuxTestConfig
forall a. Default a => a
def { $sel:logLevel:TmuxTestConfig :: Severity
TmuxTestConfig.logLevel = Severity
Trace }

tmuxGuiTest ::
  Sem TestStack a ->
  TestT IO a
tmuxGuiTest :: forall a. Sem TestStack a -> TestT IO a
tmuxGuiTest =
  TmuxTestConfig -> Sem TestStack a -> TestT IO a
forall a. TmuxTestConfig -> Sem TestStack a -> TestT IO a
runTmuxTest TmuxTestConfig
forall a. Default a => a
def { $sel:gui:TmuxTestConfig :: Bool
TmuxTestConfig.gui = Bool
True }

tmuxGuiTestTrace ::
  Sem TestStack a ->
  TestT IO a
tmuxGuiTestTrace :: forall a. Sem TestStack a -> TestT IO a
tmuxGuiTestTrace =
  TmuxTestConfig -> Sem TestStack a -> TestT IO a
forall a. TmuxTestConfig -> Sem TestStack a -> TestT IO a
runTmuxTest TmuxTestConfig
forall a. Default a => a
def { $sel:gui:TmuxTestConfig :: Bool
TmuxTestConfig.gui = Bool
True, $sel:logLevel:TmuxTestConfig :: Severity
TmuxTestConfig.logLevel = Severity
Trace  }