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 }