chiasma 0.1.0.0 → 0.2.0.0
raw patch · 91 files changed
+4271/−558 lines, 91 filesdep +aesondep +attoparsecdep +compositiondep −HTFdep −data-default-classdep ~basedep ~eitherdep ~freesetup-changedPVP ok
version bump matches the API change (PVP)
Dependencies added: aeson, attoparsec, composition, composition-extra, conduit, conduit-extra, containers, cornea, data-default, deepseq, exceptions, hedgehog, parsers, prettyprinter, prettyprinter-ansi-terminal, random, relude, stm-chans, stm-conduit, tasty, tasty-hedgehog, text, unliftio-core, uuid
Dependencies removed: HTF, data-default-class
Dependency ranges changed: base, either, free, lens, posix-pty, process, resourcet, split, typed-process, unliftio
API changes (from Hackage documentation)
- Chiasma.Api.Class: class DecodeTmuxResponse a
- Chiasma.Api.Class: decode :: DecodeTmuxResponse a => String -> Either TmuxError a
- Chiasma.Codec: [unQ] :: TmuxQuery -> String
- Chiasma.Codec.Decode: instance (Chiasma.Codec.Decode.TmuxDataDecode f, Chiasma.Codec.Decode.TmuxDataDecode g) => Chiasma.Codec.Decode.TmuxDataDecode (f GHC.Generics.:*: g)
- Chiasma.Codec.Decode: instance Chiasma.Codec.Decode.TmuxDataDecode f => Chiasma.Codec.Decode.TmuxDataDecode (GHC.Generics.M1 i c f)
- Chiasma.Data.Pane: Pane :: PaneId -> Int -> Int -> Pane
- Chiasma.Data.Pane: PaneId :: Int -> PaneId
- Chiasma.Data.Pane: [paneHeight] :: Pane -> Int
- Chiasma.Data.Pane: [paneId] :: Pane -> PaneId
- Chiasma.Data.Pane: [paneWidth] :: Pane -> Int
- Chiasma.Data.Pane: data Pane
- Chiasma.Data.Pane: instance Chiasma.Codec.Decode.TmuxPrimDecode Chiasma.Data.Pane.PaneId
- Chiasma.Data.Pane: instance Chiasma.Codec.TmuxCodec Chiasma.Data.Pane.Pane
- Chiasma.Data.Pane: instance GHC.Classes.Eq Chiasma.Data.Pane.Pane
- Chiasma.Data.Pane: instance GHC.Classes.Eq Chiasma.Data.Pane.PaneId
- Chiasma.Data.Pane: instance GHC.Generics.Generic Chiasma.Data.Pane.Pane
- Chiasma.Data.Pane: instance GHC.Show.Show Chiasma.Data.Pane.Pane
- Chiasma.Data.Pane: instance GHC.Show.Show Chiasma.Data.Pane.PaneId
- Chiasma.Data.Pane: newtype PaneId
- Chiasma.Data.TmuxThunk: Cmd :: CmdName -> CmdArgs -> Cmd
- Chiasma.Data.TmuxThunk: CmdArgs :: [String] -> CmdArgs
- Chiasma.Data.TmuxThunk: CmdName :: String -> CmdName
- Chiasma.Data.TmuxThunk: Cmds :: [Cmd] -> Cmds
- Chiasma.Data.TmuxThunk: DecodingFailed :: Cmds -> String -> TmuxDecodeError -> TmuxError
- Chiasma.Data.TmuxThunk: NoOutput :: Cmds -> TmuxError
- Chiasma.Data.TmuxThunk: OutputParsingFailed :: Cmds -> [String] -> ParseError -> TmuxError
- Chiasma.Data.TmuxThunk: ProcessFailed :: Cmds -> String -> TmuxError
- Chiasma.Data.TmuxThunk: cmd :: String -> [String] -> Cmd
- Chiasma.Data.TmuxThunk: data Cmd
- Chiasma.Data.TmuxThunk: data TmuxError
- Chiasma.Data.TmuxThunk: instance GHC.Classes.Eq Chiasma.Data.TmuxThunk.Cmd
- Chiasma.Data.TmuxThunk: instance GHC.Classes.Eq Chiasma.Data.TmuxThunk.CmdArgs
- Chiasma.Data.TmuxThunk: instance GHC.Classes.Eq Chiasma.Data.TmuxThunk.CmdName
- Chiasma.Data.TmuxThunk: instance GHC.Classes.Eq Chiasma.Data.TmuxThunk.Cmds
- Chiasma.Data.TmuxThunk: instance GHC.Classes.Eq Chiasma.Data.TmuxThunk.TmuxError
- Chiasma.Data.TmuxThunk: instance GHC.Show.Show Chiasma.Data.TmuxThunk.Cmd
- Chiasma.Data.TmuxThunk: instance GHC.Show.Show Chiasma.Data.TmuxThunk.CmdArgs
- Chiasma.Data.TmuxThunk: instance GHC.Show.Show Chiasma.Data.TmuxThunk.CmdName
- Chiasma.Data.TmuxThunk: instance GHC.Show.Show Chiasma.Data.TmuxThunk.Cmds
- Chiasma.Data.TmuxThunk: instance GHC.Show.Show Chiasma.Data.TmuxThunk.TmuxError
- Chiasma.Data.TmuxThunk: newtype CmdArgs
- Chiasma.Data.TmuxThunk: newtype CmdName
- Chiasma.Data.TmuxThunk: newtype Cmds
- Chiasma.Data.Window: Window :: WindowId -> Int -> Int -> Window
- Chiasma.Data.Window: WindowId :: Int -> WindowId
- Chiasma.Data.Window: [windowHeight] :: Window -> Int
- Chiasma.Data.Window: [windowId] :: Window -> WindowId
- Chiasma.Data.Window: [windowWidth] :: Window -> Int
- Chiasma.Data.Window: data Window
- Chiasma.Data.Window: instance Chiasma.Codec.Decode.TmuxPrimDecode Chiasma.Data.Window.WindowId
- Chiasma.Data.Window: instance Chiasma.Codec.TmuxCodec Chiasma.Data.Window.Window
- Chiasma.Data.Window: instance GHC.Classes.Eq Chiasma.Data.Window.Window
- Chiasma.Data.Window: instance GHC.Classes.Eq Chiasma.Data.Window.WindowId
- Chiasma.Data.Window: instance GHC.Generics.Generic Chiasma.Data.Window.Window
- Chiasma.Data.Window: instance GHC.Show.Show Chiasma.Data.Window.Window
- Chiasma.Data.Window: instance GHC.Show.Show Chiasma.Data.Window.WindowId
- Chiasma.Data.Window: newtype WindowId
- Chiasma.Monad.Buffered: instance Data.Default.Class.Default Chiasma.Monad.Buffered.TmuxState
- Chiasma.Monad.Buffered: runTmux :: (MonadIO m, TmuxApi api) => api -> TmuxProg b -> m (Either TmuxError b)
- Chiasma.Monad.Tmux: type TmuxProg = Free TmuxThunk
- Chiasma.Native.Api: class TmuxApi a
- Chiasma.Native.Api: instance Chiasma.Api.Class.TmuxApi Chiasma.Native.Api.TmuxNative
- Chiasma.Native.Api: runCommands :: (TmuxApi a, MonadIO m) => a -> ([String] -> Either TmuxDecodeError b) -> Cmds -> ExceptT TmuxError m [b]
+ Chiasma.Api.Class: withTmux :: TmuxApi m a => a -> (ConduitT (Flush Cmd) Void m () -> ConduitT () TmuxOutputBlock m () -> m b) -> m b
+ Chiasma.Codec: [$sel:unQ:TmuxQuery] :: TmuxQuery -> Text
+ Chiasma.Codec: genDecode :: (Generic a, TmuxDataDecode (Rep a)) => Text -> Either TmuxDecodeError a
+ Chiasma.Codec: instance Chiasma.Codec.TmuxCodec Chiasma.Data.TmuxId.PaneId
+ Chiasma.Codec: instance Chiasma.Codec.TmuxCodec Chiasma.Data.TmuxId.SessionId
+ Chiasma.Codec: instance Chiasma.Codec.TmuxCodec Chiasma.Data.TmuxId.WindowId
+ Chiasma.Codec.Data: Pane :: PaneId -> Int -> Int -> Pane
+ Chiasma.Codec.Data: Session :: SessionId -> Session
+ Chiasma.Codec.Data: Window :: WindowId -> Int -> Int -> Window
+ Chiasma.Codec.Data: [$sel:paneHeight:Pane] :: Pane -> Int
+ Chiasma.Codec.Data: [$sel:paneId:Pane] :: Pane -> PaneId
+ Chiasma.Codec.Data: [$sel:paneWidth:Pane] :: Pane -> Int
+ Chiasma.Codec.Data: [$sel:sessionId:Session] :: Session -> SessionId
+ Chiasma.Codec.Data: [$sel:windowHeight:Window] :: Window -> Int
+ Chiasma.Codec.Data: [$sel:windowId:Window] :: Window -> WindowId
+ Chiasma.Codec.Data: [$sel:windowWidth:Window] :: Window -> Int
+ Chiasma.Codec.Data: data Pane
+ Chiasma.Codec.Data: data Session
+ Chiasma.Codec.Data: data Window
+ Chiasma.Codec.Data.Pane: Pane :: PaneId -> Int -> Int -> Pane
+ Chiasma.Codec.Data.Pane: [$sel:paneHeight:Pane] :: Pane -> Int
+ Chiasma.Codec.Data.Pane: [$sel:paneId:Pane] :: Pane -> PaneId
+ Chiasma.Codec.Data.Pane: [$sel:paneWidth:Pane] :: Pane -> Int
+ Chiasma.Codec.Data.Pane: data Pane
+ Chiasma.Codec.Data.Pane: instance Chiasma.Codec.TmuxCodec Chiasma.Codec.Data.Pane.Pane
+ Chiasma.Codec.Data.Pane: instance Chiasma.Data.TmuxId.HasPaneId Chiasma.Codec.Data.Pane.Pane
+ Chiasma.Codec.Data.Pane: instance GHC.Classes.Eq Chiasma.Codec.Data.Pane.Pane
+ Chiasma.Codec.Data.Pane: instance GHC.Generics.Generic Chiasma.Codec.Data.Pane.Pane
+ Chiasma.Codec.Data.Pane: instance GHC.Show.Show Chiasma.Codec.Data.Pane.Pane
+ Chiasma.Codec.Data.PaneCoords: PaneCoords :: SessionId -> WindowId -> PaneId -> PaneCoords
+ Chiasma.Codec.Data.PaneCoords: [$sel:paneId:PaneCoords] :: PaneCoords -> PaneId
+ Chiasma.Codec.Data.PaneCoords: [$sel:sessionId:PaneCoords] :: PaneCoords -> SessionId
+ Chiasma.Codec.Data.PaneCoords: [$sel:windowId:PaneCoords] :: PaneCoords -> WindowId
+ Chiasma.Codec.Data.PaneCoords: data PaneCoords
+ Chiasma.Codec.Data.PaneCoords: instance Chiasma.Codec.TmuxCodec Chiasma.Codec.Data.PaneCoords.PaneCoords
+ Chiasma.Codec.Data.PaneCoords: instance Chiasma.Data.TmuxId.HasPaneId Chiasma.Codec.Data.PaneCoords.PaneCoords
+ Chiasma.Codec.Data.PaneCoords: instance GHC.Classes.Eq Chiasma.Codec.Data.PaneCoords.PaneCoords
+ Chiasma.Codec.Data.PaneCoords: instance GHC.Generics.Generic Chiasma.Codec.Data.PaneCoords.PaneCoords
+ Chiasma.Codec.Data.PaneCoords: instance GHC.Show.Show Chiasma.Codec.Data.PaneCoords.PaneCoords
+ Chiasma.Codec.Data.PaneDetail: PaneDetail :: PaneId -> Int -> Int -> Int -> Int -> PaneDetail
+ Chiasma.Codec.Data.PaneDetail: [$sel:paneHeight:PaneDetail] :: PaneDetail -> Int
+ Chiasma.Codec.Data.PaneDetail: [$sel:paneId:PaneDetail] :: PaneDetail -> PaneId
+ Chiasma.Codec.Data.PaneDetail: [$sel:paneLeft:PaneDetail] :: PaneDetail -> Int
+ Chiasma.Codec.Data.PaneDetail: [$sel:paneTop:PaneDetail] :: PaneDetail -> Int
+ Chiasma.Codec.Data.PaneDetail: [$sel:paneWidth:PaneDetail] :: PaneDetail -> Int
+ Chiasma.Codec.Data.PaneDetail: data PaneDetail
+ Chiasma.Codec.Data.PaneDetail: instance Chiasma.Codec.TmuxCodec Chiasma.Codec.Data.PaneDetail.PaneDetail
+ Chiasma.Codec.Data.PaneDetail: instance Chiasma.Data.TmuxId.HasPaneId Chiasma.Codec.Data.PaneDetail.PaneDetail
+ Chiasma.Codec.Data.PaneDetail: instance GHC.Classes.Eq Chiasma.Codec.Data.PaneDetail.PaneDetail
+ Chiasma.Codec.Data.PaneDetail: instance GHC.Generics.Generic Chiasma.Codec.Data.PaneDetail.PaneDetail
+ Chiasma.Codec.Data.PaneDetail: instance GHC.Show.Show Chiasma.Codec.Data.PaneDetail.PaneDetail
+ Chiasma.Codec.Data.PaneMode: PaneMode :: PaneId -> Text -> PaneMode
+ Chiasma.Codec.Data.PaneMode: [$sel:paneId:PaneMode] :: PaneMode -> PaneId
+ Chiasma.Codec.Data.PaneMode: [$sel:paneMode:PaneMode] :: PaneMode -> Text
+ Chiasma.Codec.Data.PaneMode: data PaneMode
+ Chiasma.Codec.Data.PaneMode: instance Chiasma.Codec.TmuxCodec Chiasma.Codec.Data.PaneMode.PaneMode
+ Chiasma.Codec.Data.PaneMode: instance Chiasma.Data.TmuxId.HasPaneId Chiasma.Codec.Data.PaneMode.PaneMode
+ Chiasma.Codec.Data.PaneMode: instance GHC.Classes.Eq Chiasma.Codec.Data.PaneMode.PaneMode
+ Chiasma.Codec.Data.PaneMode: instance GHC.Generics.Generic Chiasma.Codec.Data.PaneMode.PaneMode
+ Chiasma.Codec.Data.PaneMode: instance GHC.Show.Show Chiasma.Codec.Data.PaneMode.PaneMode
+ Chiasma.Codec.Data.PanePid: PanePid :: PaneId -> Int -> PanePid
+ Chiasma.Codec.Data.PanePid: [$sel:paneId:PanePid] :: PanePid -> PaneId
+ Chiasma.Codec.Data.PanePid: [$sel:panePid:PanePid] :: PanePid -> Int
+ Chiasma.Codec.Data.PanePid: data PanePid
+ Chiasma.Codec.Data.PanePid: instance Chiasma.Codec.TmuxCodec Chiasma.Codec.Data.PanePid.PanePid
+ Chiasma.Codec.Data.PanePid: instance Chiasma.Data.TmuxId.HasPaneId Chiasma.Codec.Data.PanePid.PanePid
+ Chiasma.Codec.Data.PanePid: instance GHC.Classes.Eq Chiasma.Codec.Data.PanePid.PanePid
+ Chiasma.Codec.Data.PanePid: instance GHC.Generics.Generic Chiasma.Codec.Data.PanePid.PanePid
+ Chiasma.Codec.Data.PanePid: instance GHC.Show.Show Chiasma.Codec.Data.PanePid.PanePid
+ Chiasma.Codec.Data.Session: Session :: SessionId -> Session
+ Chiasma.Codec.Data.Session: [$sel:sessionId:Session] :: Session -> SessionId
+ Chiasma.Codec.Data.Session: data Session
+ Chiasma.Codec.Data.Session: instance Chiasma.Codec.TmuxCodec Chiasma.Codec.Data.Session.Session
+ Chiasma.Codec.Data.Session: instance GHC.Classes.Eq Chiasma.Codec.Data.Session.Session
+ Chiasma.Codec.Data.Session: instance GHC.Generics.Generic Chiasma.Codec.Data.Session.Session
+ Chiasma.Codec.Data.Session: instance GHC.Show.Show Chiasma.Codec.Data.Session.Session
+ Chiasma.Codec.Data.Window: Window :: WindowId -> Int -> Int -> Window
+ Chiasma.Codec.Data.Window: [$sel:windowHeight:Window] :: Window -> Int
+ Chiasma.Codec.Data.Window: [$sel:windowId:Window] :: Window -> WindowId
+ Chiasma.Codec.Data.Window: [$sel:windowWidth:Window] :: Window -> Int
+ Chiasma.Codec.Data.Window: data Window
+ Chiasma.Codec.Data.Window: instance Chiasma.Codec.TmuxCodec Chiasma.Codec.Data.Window.Window
+ Chiasma.Codec.Data.Window: instance GHC.Classes.Eq Chiasma.Codec.Data.Window.Window
+ Chiasma.Codec.Data.Window: instance GHC.Generics.Generic Chiasma.Codec.Data.Window.Window
+ Chiasma.Codec.Data.Window: instance GHC.Show.Show Chiasma.Codec.Data.Window.Window
+ Chiasma.Codec.Decode: BoolParsingFailure :: Text -> TmuxDecodeError
+ Chiasma.Codec.Decode: instance Chiasma.Codec.Decode.TmuxPrimDecode Chiasma.Data.TmuxId.PaneId
+ Chiasma.Codec.Decode: instance Chiasma.Codec.Decode.TmuxPrimDecode Chiasma.Data.TmuxId.SessionId
+ Chiasma.Codec.Decode: instance Chiasma.Codec.Decode.TmuxPrimDecode Chiasma.Data.TmuxId.WindowId
+ Chiasma.Codec.Decode: instance Chiasma.Codec.Decode.TmuxPrimDecode Data.Text.Internal.Text
+ Chiasma.Codec.Decode: instance Chiasma.Codec.Decode.TmuxPrimDecode GHC.Types.Bool
+ Chiasma.Codec.Decode: instance Chiasma.Codec.Decode.TmuxPrimDecode [GHC.Types.Char]
+ Chiasma.Codec.Decode: instance forall k (f :: k -> *) (g :: k -> *). (Chiasma.Codec.Decode.TmuxDataDecode f, Chiasma.Codec.Decode.TmuxDataDecode g) => Chiasma.Codec.Decode.TmuxDataDecode (f GHC.Generics.:*: g)
+ Chiasma.Codec.Decode: instance forall k (f :: k -> *) i (c :: GHC.Generics.Meta). Chiasma.Codec.Decode.TmuxDataDecode f => Chiasma.Codec.Decode.TmuxDataDecode (GHC.Generics.M1 i c f)
+ Chiasma.Codec.Query: formatQuery :: Text -> Text
+ Chiasma.Codec.Query: snakeCase :: Text -> Text
+ Chiasma.Codec.Query: trans :: Char -> Text
+ Chiasma.Command.Pane: capturePane :: MonadFree TmuxThunk m => PaneId -> m [Text]
+ Chiasma.Command.Pane: closePane :: MonadFree TmuxThunk m => PaneId -> m ()
+ Chiasma.Command.Pane: copyMode :: MonadFree TmuxThunk m => PaneId -> m ()
+ Chiasma.Command.Pane: firstWindowPane :: MonadFree TmuxThunk m => WindowId -> m Pane
+ Chiasma.Command.Pane: formatLine :: Text -> [Text]
+ Chiasma.Command.Pane: isPaneIdOpen :: MonadFree TmuxThunk m => PaneId -> m Bool
+ Chiasma.Command.Pane: isPaneOpen :: MonadFree TmuxThunk m => View PaneId -> m Bool
+ Chiasma.Command.Pane: movePane :: MonadFree TmuxThunk m => PaneId -> PaneId -> Bool -> m ()
+ Chiasma.Command.Pane: pane :: (MonadFree TmuxThunk m, TmuxCodec a, HasPaneId a) => PaneId -> m (Maybe a)
+ Chiasma.Command.Pane: paneCoords :: MonadFree TmuxThunk m => PaneId -> m (Maybe PaneCoords)
+ Chiasma.Command.Pane: paneMode :: MonadFree TmuxThunk m => PaneId -> m (Maybe PaneMode)
+ Chiasma.Command.Pane: panePid :: MonadFree TmuxThunk m => PaneId -> m (Maybe PanePid)
+ Chiasma.Command.Pane: panePids :: MonadFree TmuxThunk m => m [PanePid]
+ Chiasma.Command.Pane: paneTarget :: PaneId -> [Text]
+ Chiasma.Command.Pane: panes :: MonadFree TmuxThunk m => m [Pane]
+ Chiasma.Command.Pane: panesAs :: (MonadFree TmuxThunk m, TmuxCodec a) => m [a]
+ Chiasma.Command.Pane: pipePane :: MonadFree TmuxThunk m => PaneId -> Text -> m ()
+ Chiasma.Command.Pane: quitCopyMode :: MonadFree TmuxThunk m => PaneId -> m ()
+ Chiasma.Command.Pane: resizePane :: MonadFree TmuxThunk m => PaneId -> Bool -> Int -> m ()
+ Chiasma.Command.Pane: sameId :: HasPaneId a => PaneId -> a -> Bool
+ Chiasma.Command.Pane: selectPane :: MonadFree TmuxThunk m => PaneId -> m ()
+ Chiasma.Command.Pane: sendKeys :: MonadFree TmuxThunk m => PaneId -> [Text] -> m ()
+ Chiasma.Command.Pane: windowPanes :: MonadFree TmuxThunk m => WindowId -> m [Pane]
+ Chiasma.Command.Pane: windowPanesAs :: (MonadFree TmuxThunk m, TmuxCodec a) => WindowId -> m [a]
+ Chiasma.Command.Session: activateSession :: MonadFree TmuxThunk m => Int -> m ()
+ Chiasma.Command.Session: doesSessionExist :: MonadFree TmuxThunk m => SessionId -> m Bool
+ Chiasma.Command.Session: existingSessionId :: MonadFree TmuxThunk m => SessionId -> m (Maybe SessionId)
+ Chiasma.Command.Session: newSession :: MonadFree TmuxThunk m => Ident -> m Session
+ Chiasma.Command.Session: sameId :: SessionId -> Session -> Bool
+ Chiasma.Command.Session: sessions :: MonadFree TmuxThunk m => m [Session]
+ Chiasma.Command.Window: doesWindowExist :: MonadFree TmuxThunk m => WindowId -> m Bool
+ Chiasma.Command.Window: newSessionWindow :: MonadFree TmuxThunk m => SessionId -> m Window
+ Chiasma.Command.Window: newWindow :: MonadFree TmuxThunk m => SessionId -> Ident -> m Window
+ Chiasma.Command.Window: sameId :: WindowId -> Window -> Bool
+ Chiasma.Command.Window: sessionWindows :: MonadFree TmuxThunk m => SessionId -> m [Window]
+ Chiasma.Command.Window: splitWindow :: MonadFree TmuxThunk m => FilePath -> WindowId -> m Pane
+ Chiasma.Command.Window: splitWindowAs :: (MonadFree TmuxThunk m, TmuxCodec a) => FilePath -> WindowId -> m a
+ Chiasma.Command.Window: window :: MonadFree TmuxThunk m => WindowId -> m (Maybe Window)
+ Chiasma.Command.Window: windows :: MonadFree TmuxThunk m => m [Window]
+ Chiasma.Control.IO.Unsafe: unsafeLog :: Show a => a -> b -> b
+ Chiasma.Data.Cmd: Cmd :: CmdName -> CmdArgs -> Cmd
+ Chiasma.Data.Cmd: CmdArgs :: [Text] -> CmdArgs
+ Chiasma.Data.Cmd: CmdName :: Text -> CmdName
+ Chiasma.Data.Cmd: Cmds :: [Cmd] -> Cmds
+ Chiasma.Data.Cmd: cmd :: Text -> [Text] -> Cmd
+ Chiasma.Data.Cmd: data Cmd
+ Chiasma.Data.Cmd: instance GHC.Classes.Eq Chiasma.Data.Cmd.Cmd
+ Chiasma.Data.Cmd: instance GHC.Classes.Eq Chiasma.Data.Cmd.CmdArgs
+ Chiasma.Data.Cmd: instance GHC.Classes.Eq Chiasma.Data.Cmd.CmdName
+ Chiasma.Data.Cmd: instance GHC.Classes.Eq Chiasma.Data.Cmd.Cmds
+ Chiasma.Data.Cmd: instance GHC.Show.Show Chiasma.Data.Cmd.Cmd
+ Chiasma.Data.Cmd: instance GHC.Show.Show Chiasma.Data.Cmd.CmdArgs
+ Chiasma.Data.Cmd: instance GHC.Show.Show Chiasma.Data.Cmd.CmdName
+ Chiasma.Data.Cmd: instance GHC.Show.Show Chiasma.Data.Cmd.Cmds
+ Chiasma.Data.Cmd: newtype CmdArgs
+ Chiasma.Data.Cmd: newtype CmdName
+ Chiasma.Data.Cmd: newtype Cmds
+ Chiasma.Data.Conduit: createSinkFlush :: MonadIO m => StreamSpec 'STInput (ConduitT (Flush ByteString) o m ())
+ Chiasma.Data.Ident: Str :: Text -> Ident
+ Chiasma.Data.Ident: Uuid :: UUID -> Ident
+ Chiasma.Data.Ident: class Identifiable a
+ Chiasma.Data.Ident: data Ident
+ Chiasma.Data.Ident: generateIdent :: MonadIO m => m Ident
+ Chiasma.Data.Ident: identText :: Ident -> Text
+ Chiasma.Data.Ident: identify :: Identifiable a => a -> Ident
+ Chiasma.Data.Ident: instance Chiasma.Data.Ident.Identifiable Chiasma.Data.Ident.Ident
+ Chiasma.Data.Ident: instance Control.DeepSeq.NFData Chiasma.Data.Ident.Ident
+ Chiasma.Data.Ident: instance Data.Aeson.Types.FromJSON.FromJSON Chiasma.Data.Ident.Ident
+ Chiasma.Data.Ident: instance Data.Aeson.Types.ToJSON.ToJSON Chiasma.Data.Ident.Ident
+ Chiasma.Data.Ident: instance Data.Data.Data Chiasma.Data.Ident.Ident
+ Chiasma.Data.Ident: instance Data.Default.Class.Default Chiasma.Data.Ident.Ident
+ Chiasma.Data.Ident: instance Data.String.IsString Chiasma.Data.Ident.Ident
+ Chiasma.Data.Ident: instance GHC.Classes.Eq Chiasma.Data.Ident.Ident
+ Chiasma.Data.Ident: instance GHC.Classes.Ord Chiasma.Data.Ident.Ident
+ Chiasma.Data.Ident: instance GHC.Generics.Generic Chiasma.Data.Ident.Ident
+ Chiasma.Data.Ident: instance GHC.Show.Show Chiasma.Data.Ident.Ident
+ Chiasma.Data.Ident: instance Prettyprinter.Internal.Pretty Chiasma.Data.Ident.Ident
+ Chiasma.Data.Ident: parseIdent :: Text -> Ident
+ Chiasma.Data.Ident: sameIdent :: Identifiable a => Identifiable b => a -> b -> Bool
+ Chiasma.Data.List: head' :: [a] -> Maybe a
+ Chiasma.Data.List: last' :: [a] -> Maybe a
+ Chiasma.Data.List: tail' :: [a] -> Maybe [a]
+ Chiasma.Data.Maybe: findMaybe :: (a -> Maybe b) -> [a] -> Maybe b
+ Chiasma.Data.Maybe: maybeExcept :: MonadError e m => e -> Maybe a -> m a
+ Chiasma.Data.Maybe: orElse :: Maybe a -> Maybe a -> Maybe a
+ Chiasma.Data.RenderError: Fatal :: TmuxError -> RenderError
+ Chiasma.Data.RenderError: NoPrincipal :: Ident -> RenderError
+ Chiasma.Data.RenderError: Pack :: Text -> RenderError
+ Chiasma.Data.RenderError: Views :: ViewsError -> RenderError
+ Chiasma.Data.RenderError: _Fatal :: AsRenderError r_a10xW => Prism' r_a10xW TmuxError
+ Chiasma.Data.RenderError: _NoPrincipal :: AsRenderError r_a10xW => Prism' r_a10xW Ident
+ Chiasma.Data.RenderError: _Pack :: AsRenderError r_a10xW => Prism' r_a10xW Text
+ Chiasma.Data.RenderError: _RenderError :: AsRenderError r_a10xW => Prism' r_a10xW RenderError
+ Chiasma.Data.RenderError: _Views :: AsRenderError r_a10xW => Prism' r_a10xW ViewsError
+ Chiasma.Data.RenderError: class AsRenderError r_a10xW
+ Chiasma.Data.RenderError: data RenderError
+ Chiasma.Data.RenderError: instance Chiasma.Data.RenderError.AsRenderError Chiasma.Data.RenderError.RenderError
+ Chiasma.Data.RenderError: instance Data.DeepPrisms.DeepPrisms Chiasma.Data.RenderError.RenderError Chiasma.Data.RenderError.RenderError
+ Chiasma.Data.RenderError: instance Data.DeepPrisms.DeepPrisms Chiasma.Data.RenderError.RenderError Chiasma.Data.TmuxError.TmuxError
+ Chiasma.Data.RenderError: instance Data.DeepPrisms.DeepPrisms Chiasma.Data.RenderError.RenderError Chiasma.Data.Views.ViewsError
+ Chiasma.Data.RenderError: instance GHC.Classes.Eq Chiasma.Data.RenderError.RenderError
+ Chiasma.Data.RenderError: instance GHC.Show.Show Chiasma.Data.RenderError.RenderError
+ Chiasma.Data.TmuxError: CommandFailed :: Cmds -> [Text] -> TmuxError
+ Chiasma.Data.TmuxError: DecodingFailed :: Cmds -> Text -> TmuxDecodeError -> TmuxError
+ Chiasma.Data.TmuxError: InvalidOutput :: Text -> Text -> TmuxError
+ Chiasma.Data.TmuxError: NoOutput :: Cmds -> TmuxError
+ Chiasma.Data.TmuxError: OutputParsingFailed :: Cmds -> [Text] -> ParseError -> TmuxError
+ Chiasma.Data.TmuxError: ProcessFailed :: Cmds -> Text -> TmuxError
+ Chiasma.Data.TmuxError: [$sel:commandFailedCmds:ProcessFailed] :: TmuxError -> Cmds
+ Chiasma.Data.TmuxError: [$sel:commandFailedError:ProcessFailed] :: TmuxError -> [Text]
+ Chiasma.Data.TmuxError: [$sel:decodingFailedCmds:ProcessFailed] :: TmuxError -> Cmds
+ Chiasma.Data.TmuxError: [$sel:decodingFailedError:ProcessFailed] :: TmuxError -> TmuxDecodeError
+ Chiasma.Data.TmuxError: [$sel:decodingFailedOutput:ProcessFailed] :: TmuxError -> Text
+ Chiasma.Data.TmuxError: [$sel:invalidOutputCommand:ProcessFailed] :: TmuxError -> Text
+ Chiasma.Data.TmuxError: [$sel:invalidOutputReason:ProcessFailed] :: TmuxError -> Text
+ Chiasma.Data.TmuxError: [$sel:parsingFailedCmds:ProcessFailed] :: TmuxError -> Cmds
+ Chiasma.Data.TmuxError: [$sel:parsingFailedError:ProcessFailed] :: TmuxError -> ParseError
+ Chiasma.Data.TmuxError: [$sel:parsingFailedOutput:ProcessFailed] :: TmuxError -> [Text]
+ Chiasma.Data.TmuxError: [$sel:processFailedCmds:ProcessFailed] :: TmuxError -> Cmds
+ Chiasma.Data.TmuxError: [$sel:processFailedReason:ProcessFailed] :: TmuxError -> Text
+ Chiasma.Data.TmuxError: data TmuxError
+ Chiasma.Data.TmuxError: instance Data.DeepPrisms.DeepPrisms Chiasma.Data.TmuxError.TmuxError Chiasma.Data.TmuxError.TmuxError
+ Chiasma.Data.TmuxError: instance GHC.Classes.Eq Chiasma.Data.TmuxError.TmuxError
+ Chiasma.Data.TmuxError: instance GHC.Show.Show Chiasma.Data.TmuxError.TmuxError
+ Chiasma.Data.TmuxId: PaneId :: Int -> PaneId
+ Chiasma.Data.TmuxId: SessionId :: Int -> SessionId
+ Chiasma.Data.TmuxId: TmuxIdPrefix :: Char -> TmuxIdPrefix a
+ Chiasma.Data.TmuxId: WindowId :: Int -> WindowId
+ Chiasma.Data.TmuxId: class HasPaneId a
+ Chiasma.Data.TmuxId: class TmuxId a
+ Chiasma.Data.TmuxId: formatId :: TmuxId a => a -> Text
+ Chiasma.Data.TmuxId: instance Chiasma.Data.TmuxId.TmuxId Chiasma.Data.TmuxId.PaneId
+ Chiasma.Data.TmuxId: instance Chiasma.Data.TmuxId.TmuxId Chiasma.Data.TmuxId.SessionId
+ Chiasma.Data.TmuxId: instance Chiasma.Data.TmuxId.TmuxId Chiasma.Data.TmuxId.WindowId
+ Chiasma.Data.TmuxId: instance GHC.Classes.Eq Chiasma.Data.TmuxId.PaneId
+ Chiasma.Data.TmuxId: instance GHC.Classes.Eq Chiasma.Data.TmuxId.SessionId
+ Chiasma.Data.TmuxId: instance GHC.Classes.Eq Chiasma.Data.TmuxId.WindowId
+ Chiasma.Data.TmuxId: instance GHC.Classes.Ord Chiasma.Data.TmuxId.PaneId
+ Chiasma.Data.TmuxId: instance GHC.Classes.Ord Chiasma.Data.TmuxId.SessionId
+ Chiasma.Data.TmuxId: instance GHC.Classes.Ord Chiasma.Data.TmuxId.WindowId
+ Chiasma.Data.TmuxId: instance GHC.Generics.Generic Chiasma.Data.TmuxId.PaneId
+ Chiasma.Data.TmuxId: instance GHC.Generics.Generic Chiasma.Data.TmuxId.SessionId
+ Chiasma.Data.TmuxId: instance GHC.Generics.Generic Chiasma.Data.TmuxId.WindowId
+ Chiasma.Data.TmuxId: instance GHC.Num.Num Chiasma.Data.TmuxId.PaneId
+ Chiasma.Data.TmuxId: instance GHC.Num.Num Chiasma.Data.TmuxId.SessionId
+ Chiasma.Data.TmuxId: instance GHC.Num.Num Chiasma.Data.TmuxId.WindowId
+ Chiasma.Data.TmuxId: instance GHC.Show.Show Chiasma.Data.TmuxId.PaneId
+ Chiasma.Data.TmuxId: instance GHC.Show.Show Chiasma.Data.TmuxId.SessionId
+ Chiasma.Data.TmuxId: instance GHC.Show.Show Chiasma.Data.TmuxId.WindowId
+ Chiasma.Data.TmuxId: instance Prettyprinter.Internal.Pretty Chiasma.Data.TmuxId.PaneId
+ Chiasma.Data.TmuxId: instance Prettyprinter.Internal.Pretty Chiasma.Data.TmuxId.SessionId
+ Chiasma.Data.TmuxId: instance Prettyprinter.Internal.Pretty Chiasma.Data.TmuxId.WindowId
+ Chiasma.Data.TmuxId: newtype PaneId
+ Chiasma.Data.TmuxId: newtype SessionId
+ Chiasma.Data.TmuxId: newtype TmuxIdPrefix a
+ Chiasma.Data.TmuxId: newtype WindowId
+ Chiasma.Data.TmuxId: number :: TmuxId a => a -> Int
+ Chiasma.Data.TmuxId: paneId :: HasPaneId a => a -> PaneId
+ Chiasma.Data.TmuxId: panePrefix :: Char
+ Chiasma.Data.TmuxId: prefix :: TmuxId a => TmuxIdPrefix a
+ Chiasma.Data.TmuxId: sessionPrefix :: Char
+ Chiasma.Data.TmuxId: windowPrefix :: Char
+ Chiasma.Data.TmuxThunk: Flush :: (() -> next) -> TmuxThunk next
+ Chiasma.Data.View: View :: Ident -> Maybe a -> View a
+ Chiasma.Data.View: [$sel:viewId:View] :: View a -> Maybe a
+ Chiasma.Data.View: [$sel:viewIdent:View] :: View a -> Ident
+ Chiasma.Data.View: _viewId :: HasView c_aRzy a_aRx7 => Lens' c_aRzy (Maybe a_aRx7)
+ Chiasma.Data.View: _viewIdent :: HasView c_aRzy a_aRx7 => Lens' c_aRzy Ident
+ Chiasma.Data.View: class HasView c_aRzy a_aRx7 | c_aRzy -> a_aRx7
+ Chiasma.Data.View: data View a
+ Chiasma.Data.View: instance Chiasma.Data.Ident.Identifiable (Chiasma.Data.View.View a)
+ Chiasma.Data.View: instance Chiasma.Data.View.HasView (Chiasma.Data.View.View a) a
+ Chiasma.Data.View: instance GHC.Classes.Eq a => GHC.Classes.Eq (Chiasma.Data.View.View a)
+ Chiasma.Data.View: instance GHC.Show.Show a => GHC.Show.Show (Chiasma.Data.View.View a)
+ Chiasma.Data.View: setViewId :: a -> View a -> View a
+ Chiasma.Data.View: view :: HasView c_aRzy a_aRx7 => Lens' c_aRzy (View a_aRx7)
+ Chiasma.Data.Views: NoPaneId :: Ident -> ViewsError
+ Chiasma.Data.Views: NoSuchPane :: Ident -> ViewsError
+ Chiasma.Data.Views: NoSuchSession :: Ident -> ViewsError
+ Chiasma.Data.Views: NoSuchWindow :: Ident -> ViewsError
+ Chiasma.Data.Views: Views :: [View SessionId] -> [View WindowId] -> [View PaneId] -> [Doc AnsiStyle] -> Views
+ Chiasma.Data.Views: [$sel:_log:Views] :: Views -> [Doc AnsiStyle]
+ Chiasma.Data.Views: [$sel:_panes:Views] :: Views -> [View PaneId]
+ Chiasma.Data.Views: [$sel:_sessions:Views] :: Views -> [View SessionId]
+ Chiasma.Data.Views: [$sel:_windows:Views] :: Views -> [View WindowId]
+ Chiasma.Data.Views: _NoPaneId :: AsViewsError r_aScM => Prism' r_aScM Ident
+ Chiasma.Data.Views: _NoSuchPane :: AsViewsError r_aScM => Prism' r_aScM Ident
+ Chiasma.Data.Views: _NoSuchSession :: AsViewsError r_aScM => Prism' r_aScM Ident
+ Chiasma.Data.Views: _NoSuchWindow :: AsViewsError r_aScM => Prism' r_aScM Ident
+ Chiasma.Data.Views: _ViewsError :: AsViewsError r_aScM => Prism' r_aScM ViewsError
+ Chiasma.Data.Views: class AsViewsError r_aScM
+ Chiasma.Data.Views: class HasViews c_aStQ
+ Chiasma.Data.Views: data Views
+ Chiasma.Data.Views: data ViewsError
+ Chiasma.Data.Views: instance Chiasma.Data.Views.AsViewsError Chiasma.Data.Views.ViewsError
+ Chiasma.Data.Views: instance Chiasma.Data.Views.HasViews Chiasma.Data.Views.Views
+ Chiasma.Data.Views: instance Data.DeepLenses.DeepLenses Chiasma.Data.Views.Views Chiasma.Data.Views.Views
+ Chiasma.Data.Views: instance Data.DeepPrisms.DeepPrisms Chiasma.Data.Views.ViewsError Chiasma.Data.Views.ViewsError
+ Chiasma.Data.Views: instance Data.Default.Class.Default Chiasma.Data.Views.Views
+ Chiasma.Data.Views: instance GHC.Classes.Eq Chiasma.Data.Views.Views
+ Chiasma.Data.Views: instance GHC.Classes.Eq Chiasma.Data.Views.ViewsError
+ Chiasma.Data.Views: instance GHC.Generics.Generic Chiasma.Data.Views.Views
+ Chiasma.Data.Views: instance GHC.Show.Show Chiasma.Data.Views.Views
+ Chiasma.Data.Views: instance GHC.Show.Show Chiasma.Data.Views.ViewsError
+ Chiasma.Data.Views: log :: HasViews c_aStQ => Lens' c_aStQ [Doc AnsiStyle]
+ Chiasma.Data.Views: panes :: HasViews c_aStQ => Lens' c_aStQ [View PaneId]
+ Chiasma.Data.Views: sessions :: HasViews c_aStQ => Lens' c_aStQ [View SessionId]
+ Chiasma.Data.Views: views :: HasViews c_aStQ => Lens' c_aStQ Views
+ Chiasma.Data.Views: windows :: HasViews c_aStQ => Lens' c_aStQ [View WindowId]
+ Chiasma.Data.WindowState: WindowState :: Window -> Pane -> Ident -> RenderableTree -> PaneId -> WindowState
+ Chiasma.Data.WindowState: [$sel:wsLayout:WindowState] :: WindowState -> RenderableTree
+ Chiasma.Data.WindowState: [$sel:wsNativeRefPane:WindowState] :: WindowState -> Pane
+ Chiasma.Data.WindowState: [$sel:wsNativeWindow:WindowState] :: WindowState -> Window
+ Chiasma.Data.WindowState: [$sel:wsReferencePane:WindowState] :: WindowState -> PaneId
+ Chiasma.Data.WindowState: [$sel:wsWindowIdent:WindowState] :: WindowState -> Ident
+ Chiasma.Data.WindowState: data WindowState
+ Chiasma.Data.WindowState: instance GHC.Classes.Eq Chiasma.Data.WindowState.WindowState
+ Chiasma.Data.WindowState: instance GHC.Show.Show Chiasma.Data.WindowState.WindowState
+ Chiasma.Lens.Tree: LeafIndexTree :: Tree l p -> LeafIndexTree l p
+ Chiasma.Lens.Tree: NodeIndexTree :: Tree l p -> NodeIndexTree l p
+ Chiasma.Lens.Tree: [$sel:litTree:LeafIndexTree] :: LeafIndexTree l p -> Tree l p
+ Chiasma.Lens.Tree: [$sel:nitTree:NodeIndexTree] :: NodeIndexTree l p -> Tree l p
+ Chiasma.Lens.Tree: _litTree :: HasLeafIndexTree c_aMwG l_aMrh p_aMri => Lens' c_aMwG (Tree l_aMrh p_aMri)
+ Chiasma.Lens.Tree: _nitTree :: HasNodeIndexTree c_aMr9 l_aMnF p_aMnG => Lens' c_aMr9 (Tree l_aMnF p_aMnG)
+ Chiasma.Lens.Tree: class HasLeafIndexTree c_aMwG l_aMrh p_aMri | c_aMwG -> l_aMrh p_aMri
+ Chiasma.Lens.Tree: class HasNodeIndexTree c_aMr9 l_aMnF p_aMnG | c_aMr9 -> l_aMnF p_aMnG
+ Chiasma.Lens.Tree: instance (Data.Data.Data l, Data.Data.Data p) => Control.Lens.Plated.Plated (Chiasma.Lens.Tree.LeafIndexTree l p)
+ Chiasma.Lens.Tree: instance (Data.Data.Data l, Data.Data.Data p) => Control.Lens.Plated.Plated (Chiasma.Lens.Tree.NodeIndexTree l p)
+ Chiasma.Lens.Tree: instance (GHC.Classes.Eq l, GHC.Classes.Eq p) => GHC.Classes.Eq (Chiasma.Lens.Tree.LeafIndexTree l p)
+ Chiasma.Lens.Tree: instance (GHC.Classes.Eq l, GHC.Classes.Eq p) => GHC.Classes.Eq (Chiasma.Lens.Tree.NodeIndexTree l p)
+ Chiasma.Lens.Tree: instance (GHC.Show.Show l, GHC.Show.Show p) => GHC.Show.Show (Chiasma.Lens.Tree.LeafIndexTree l p)
+ Chiasma.Lens.Tree: instance (GHC.Show.Show l, GHC.Show.Show p) => GHC.Show.Show (Chiasma.Lens.Tree.NodeIndexTree l p)
+ Chiasma.Lens.Tree: instance Chiasma.Data.Ident.Identifiable p => Control.Lens.At.Ixed (Chiasma.Lens.Tree.LeafIndexTree l p)
+ Chiasma.Lens.Tree: instance Chiasma.Lens.Tree.HasLeafIndexTree (Chiasma.Lens.Tree.LeafIndexTree l p) l p
+ Chiasma.Lens.Tree: instance Chiasma.Lens.Tree.HasNodeIndexTree (Chiasma.Lens.Tree.NodeIndexTree l p) l p
+ Chiasma.Lens.Tree: leafByIdent :: (Identifiable p, Data l, Data p) => Ident -> Tree l p -> Maybe p
+ Chiasma.Lens.Tree: leafByIdentTraversal :: Identifiable p => Ident -> Traversal' (Tree l p) p
+ Chiasma.Lens.Tree: leafDataTraversal :: Traversal' (Tree l p) p
+ Chiasma.Lens.Tree: leafIndexTree :: HasLeafIndexTree c_aMwG l_aMrh p_aMri => Lens' c_aMwG (LeafIndexTree l_aMrh p_aMri)
+ Chiasma.Lens.Tree: leavesByIdent :: (Identifiable p, Data l, Data p) => Ident -> Tree l p -> [p]
+ Chiasma.Lens.Tree: leavesByIdentRecursive :: (Identifiable p, Data l, Data p) => Ident -> Fold (LeafIndexTree l p) p
+ Chiasma.Lens.Tree: modifyLeafByIdent :: (Identifiable p, Data l, Data p) => Ident -> (p -> p) -> Tree l p -> Tree l p
+ Chiasma.Lens.Tree: newtype LeafIndexTree l p
+ Chiasma.Lens.Tree: newtype NodeIndexTree l p
+ Chiasma.Lens.Tree: nodeIndexTree :: HasNodeIndexTree c_aMr9 l_aMnF p_aMnG => Lens' c_aMr9 (NodeIndexTree l_aMnF p_aMnG)
+ Chiasma.Lens.Tree: plateWrap :: (Data l, Data p) => (Tree l p -> t l p) -> (t l p -> Tree l p) -> Traversal' (t l p) (t l p)
+ Chiasma.Lens.Tree: subtrees :: forall l p m. Monad m => (TreeSub l p -> m (TreeSub l p)) -> Tree l p -> m (Tree l p)
+ Chiasma.Lens.Tree: subtreesWithLayout :: forall l p m. Monad m => ((l, TreeSub l p) -> m (l, TreeSub l p)) -> Tree l p -> m (Tree l p)
+ Chiasma.Lens.Tree: treesAndSubs :: Monad m => (Tree l p -> m (Tree l p)) -> (TreeSub l p -> m (TreeSub l p)) -> Tree l p -> m (Tree l p)
+ Chiasma.Lens.Tree: type LayoutIndexTree = NodeIndexTree LayoutView PaneView
+ Chiasma.Lens.Tree: type PaneIndexTree = LeafIndexTree LayoutView PaneView
+ Chiasma.Lens.Where: where1 :: (Applicative f, Traversable t) => (a -> Bool) -> Over (->) f (t a) (t a) a a
+ Chiasma.Monad.EvalFreeT: CmdBuffer :: [Cmd] -> CmdBuffer
+ Chiasma.Monad.EvalFreeT: evalFreeF :: Monad m => CommandExec m -> CmdBuffer -> FreeF TmuxThunk a (FreeT TmuxThunk m a) -> m (Either TmuxError a)
+ Chiasma.Monad.EvalFreeT: evalFreeT :: Monad m => CommandExec m -> CmdBuffer -> FreeT TmuxThunk m a -> m (Either TmuxError a)
+ Chiasma.Monad.EvalFreeT: instance Data.Default.Class.Default Chiasma.Monad.EvalFreeT.CmdBuffer
+ Chiasma.Monad.EvalFreeT: newtype CmdBuffer
+ Chiasma.Monad.EvalFreeT: type CommandExec m = (forall b. (Text -> Either TmuxDecodeError b) -> Cmds -> m (Either TmuxError [b]))
+ Chiasma.Monad.IndividualProcess: TmuxState :: [Cmd] -> TmuxState
+ Chiasma.Monad.IndividualProcess: instance Data.Default.Class.Default Chiasma.Monad.IndividualProcess.TmuxState
+ Chiasma.Monad.IndividualProcess: interpret :: (TmuxApi m api, MonadDeepError e TmuxError m) => TmuxState -> api -> TmuxProg a -> m a
+ Chiasma.Monad.IndividualProcess: newtype TmuxState
+ Chiasma.Monad.IndividualProcess: runTmux :: (TmuxApi m api, MonadDeepError e TmuxError m) => api -> TmuxProg a -> m a
+ Chiasma.Monad.IndividualProcess: type TmuxProg = Free TmuxThunk
+ Chiasma.Monad.Stream: executeCommands :: MonadIO m => WriteCmd m -> ReadOutput m -> (Text -> Either TmuxDecodeError a) -> Cmds -> m (Either TmuxError [a])
+ Chiasma.Monad.Stream: handleProcessOutput :: Cmds -> (Text -> Either TmuxDecodeError a) -> [TmuxOutputBlock] -> Either TmuxError [a]
+ Chiasma.Monad.Stream: runTmux :: (MonadIO m, MonadDeepError e TmuxError m, TmuxApi m api) => api -> TmuxProg m a -> m a
+ Chiasma.Monad.Stream: runTmuxE :: (MonadIO m, TmuxApi m api) => api -> TmuxProg m a -> m (Either TmuxError a)
+ Chiasma.Monad.Stream: runTmuxProg :: MonadIO m => TmuxProg m a -> WriteCmd m -> ReadOutput m -> m (Either TmuxError a)
+ Chiasma.Monad.Stream: type ReadOutput m = ConduitT () TmuxOutputBlock m ()
+ Chiasma.Monad.Stream: type TmuxProg = FreeT TmuxThunk
+ Chiasma.Monad.Stream: type WriteCmd m = ConduitT (Flush Cmd) Void m ()
+ Chiasma.Monad.Tmux: flush :: MonadFree TmuxThunk m => m ()
+ Chiasma.Monad.Tmux: readFirst :: forall a m. (TmuxCodec a, MonadFree TmuxThunk m) => Text -> [Text] -> m (Maybe a)
+ Chiasma.Monad.Tmux: readRaw :: forall m. MonadFree TmuxThunk m => Text -> [Text] -> m [Text]
+ Chiasma.Monad.Tmux: unsafeReadFirst :: forall a m. (TmuxCodec a, MonadFree TmuxThunk m) => Text -> [Text] -> m a
+ Chiasma.Monad.Tmux: unsafeReadOne :: forall a m. (TmuxCodec a, MonadFree TmuxThunk m) => Text -> [Text] -> m a
+ Chiasma.Native.Api: [$sel:tmuxServerSocket:TmuxNative] :: TmuxNative -> Maybe FilePath
+ Chiasma.Native.Api: formatCmd :: Cmd -> ByteString
+ Chiasma.Native.Api: instance (Control.Monad.IO.Class.MonadIO m, Control.Monad.DeepError.MonadDeepError e Chiasma.Data.TmuxError.TmuxError m, Control.Monad.Catch.MonadMask m) => Chiasma.Api.Class.TmuxApi m Chiasma.Native.Api.TmuxNative
+ Chiasma.Native.Api: instance GHC.Show.Show Chiasma.Native.Api.TmuxNative
+ Chiasma.Native.Api: tmuxProcessConfig :: MonadIO m => Maybe FilePath -> ProcessConfig (ConduitT (Flush ByteString) Void m ()) (ConduitT () ByteString m ()) ()
+ Chiasma.Native.Api: withProcess :: (MonadIO m, MonadMask m) => ProcessConfig stdin stdout stderr -> (Process stdin stdout stderr -> m a) -> m a
+ Chiasma.Native.Parse: beginLine :: GenParser st Text
+ Chiasma.Native.Parse: endLine :: GenParser st Text
+ Chiasma.Native.Parse: parseBlock :: GenParser st [Text]
+ Chiasma.Native.Parse: tillEol :: GenParser st Text
+ Chiasma.Native.Process: cmdBytes :: [Text] -> ByteString
+ Chiasma.Native.Process: formatCmd :: Cmd -> Text
+ Chiasma.Native.Process: handleProcessOutput :: Cmds -> ExitCode -> (Text -> Either TmuxDecodeError a) -> Text -> Either TmuxError [a]
+ Chiasma.Native.Process: socketArg :: Maybe FilePath -> [Text]
+ Chiasma.Native.StreamParse: Error :: [Text] -> TmuxOutputBlock
+ Chiasma.Native.StreamParse: Success :: [Text] -> TmuxOutputBlock
+ Chiasma.Native.StreamParse: data TmuxOutputBlock
+ Chiasma.Native.StreamParse: instance GHC.Classes.Eq Chiasma.Native.StreamParse.End
+ Chiasma.Native.StreamParse: instance GHC.Classes.Eq Chiasma.Native.StreamParse.TmuxOutputBlock
+ Chiasma.Native.StreamParse: instance GHC.Show.Show Chiasma.Native.StreamParse.End
+ Chiasma.Native.StreamParse: instance GHC.Show.Show Chiasma.Native.StreamParse.TmuxOutputBlock
+ Chiasma.Native.StreamParse: parseBlocks :: (Alternative m, CharParsing m, Monad m, LookAheadParsing m) => m [TmuxOutputBlock]
+ Chiasma.Native.StreamParse: parseConduit :: MonadThrow m => ConduitT ByteString TmuxOutputBlock m ()
+ Chiasma.Pack: describeVertical :: Bool -> Doc a
+ Chiasma.Pack: needPositioning :: NonEmpty MeasureTreeSub -> Bool
+ Chiasma.Pack: packPane :: (MonadDeepState s Views m, MonadFree TmuxThunk m) => PaneId -> Bool -> PaneId -> m ()
+ Chiasma.Pack: packTree :: (MonadDeepState s Views m, MonadFree TmuxThunk m) => MeasureTree -> m ()
+ Chiasma.Pack: packWindow :: (MonadDeepState s Views m, MonadFree TmuxThunk m) => WindowState -> m ()
+ Chiasma.Pack: positionView :: (MonadDeepState s Views m, MonadFree TmuxThunk m) => Bool -> PaneId -> MeasureTreeSub -> m ()
+ Chiasma.Pack: resizeView :: MonadDeepState s Views m => MonadFree TmuxThunk m => Bool -> MeasureTreeSub -> m ()
+ Chiasma.Pane: addPane :: MonadDeepState s Views m => Ident -> m (View PaneId)
+ Chiasma.Prelude: (!!?) :: [a] -> Int -> Maybe a
+ Chiasma.Prelude: ($!!) :: NFData a => (a -> b) -> a -> b
+ Chiasma.Prelude: ($!) :: forall (r :: RuntimeRep) a (b :: TYPE r). (a -> b) -> a -> b
+ Chiasma.Prelude: ($) :: forall (r :: RuntimeRep) a (b :: TYPE r). (a -> b) -> a -> b
+ Chiasma.Prelude: ($<) :: Contravariant f => f b -> b -> f a
+ Chiasma.Prelude: ($>) :: Functor f => f a -> b -> f b
+ Chiasma.Prelude: (&&&) :: Arrow a => a b c -> a b c' -> a b (c, c')
+ Chiasma.Prelude: (&&) :: Bool -> Bool -> Bool
+ Chiasma.Prelude: (&&^) :: Monad m => m Bool -> m Bool -> m Bool
+ Chiasma.Prelude: (&) :: a -> (a -> b) -> b
+ Chiasma.Prelude: (*) :: Num a => a -> a -> a
+ Chiasma.Prelude: (**) :: Floating a => a -> a -> a
+ Chiasma.Prelude: (*>) :: Applicative f => f a -> f b -> f b
+ Chiasma.Prelude: (+) :: Num a => a -> a -> a
+ Chiasma.Prelude: (++) :: [a] -> [a] -> [a]
+ Chiasma.Prelude: (-) :: Num a => a -> a -> a
+ Chiasma.Prelude: (.) :: (b -> c) -> (a -> b) -> a -> c
+ Chiasma.Prelude: (/) :: Fractional a => a -> a -> a
+ Chiasma.Prelude: (/=) :: Eq a => a -> a -> Bool
+ Chiasma.Prelude: (:|) :: a -> [a] -> NonEmpty a
+ Chiasma.Prelude: (<$!>) :: Monad m => (a -> b) -> m a -> m b
+ Chiasma.Prelude: (<$$>) :: (Functor f0, Functor f1) => (a -> b) -> f1 (f0 a) -> f1 (f0 b)
+ Chiasma.Prelude: (<$) :: Functor f => a -> f b -> f a
+ Chiasma.Prelude: (<$>) :: Functor f => (a -> b) -> f a -> f b
+ Chiasma.Prelude: (<&>) :: Functor f => f a -> (a -> b) -> f b
+ Chiasma.Prelude: (<) :: Ord a => a -> a -> Bool
+ Chiasma.Prelude: (<*) :: Applicative f => f a -> f b -> f a
+ Chiasma.Prelude: (<**>) :: Applicative f => f a -> f (a -> b) -> f b
+ Chiasma.Prelude: (<*>) :: Applicative f => f (a -> b) -> f a -> f b
+ Chiasma.Prelude: (<<$>>) :: (Functor f, Functor g) => (a -> b) -> f (g a) -> f (g b)
+ Chiasma.Prelude: (<<<) :: forall k cat (b :: k) (c :: k) (a :: k). Category cat => cat b c -> cat a b -> cat a c
+ Chiasma.Prelude: (<=) :: Ord a => a -> a -> Bool
+ Chiasma.Prelude: (<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
+ Chiasma.Prelude: (<>) :: Semigroup a => a -> a -> a
+ Chiasma.Prelude: (<|>) :: Alternative f => f a -> f a -> f a
+ Chiasma.Prelude: (=<<) :: Monad m => (a -> m b) -> m a -> m b
+ Chiasma.Prelude: (==) :: Eq a => a -> a -> Bool
+ Chiasma.Prelude: (>$$<) :: Contravariant f => f b -> (a -> b) -> f a
+ Chiasma.Prelude: (>$) :: Contravariant f => b -> f b -> f a
+ Chiasma.Prelude: (>$<) :: Contravariant f => (a -> b) -> f b -> f a
+ Chiasma.Prelude: (>) :: Ord a => a -> a -> Bool
+ Chiasma.Prelude: (>=) :: Ord a => a -> a -> Bool
+ Chiasma.Prelude: (>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
+ Chiasma.Prelude: (>>) :: Monad m => m a -> m b -> m b
+ Chiasma.Prelude: (>>=) :: Monad m => m a -> (a -> m b) -> m b
+ Chiasma.Prelude: (>>>) :: forall k cat (a :: k) (b :: k) (c :: k). Category cat => cat a b -> cat b c -> cat a c
+ Chiasma.Prelude: (?:) :: Maybe a -> a -> a
+ Chiasma.Prelude: (??) :: Functor f => f (a -> b) -> a -> f b
+ Chiasma.Prelude: (^) :: (Num a, Integral b) => a -> b -> a
+ Chiasma.Prelude: (^^) :: (Fractional a, Integral b) => a -> b -> a
+ Chiasma.Prelude: (||) :: Bool -> Bool -> Bool
+ Chiasma.Prelude: (||^) :: Monad m => m Bool -> m Bool -> m Bool
+ Chiasma.Prelude: -- | Type of single element of the structure.
+ Chiasma.Prelude: All :: Bool -> All
+ Chiasma.Prelude: Alt :: f a -> Alt (f :: k -> Type) (a :: k)
+ Chiasma.Prelude: Any :: Bool -> Any
+ Chiasma.Prelude: Ap :: f a -> Ap (f :: k -> Type) (a :: k)
+ Chiasma.Prelude: AppendMode :: IOMode
+ Chiasma.Prelude: Bug :: SomeException -> CallStack -> Bug
+ Chiasma.Prelude: Comparison :: (a -> a -> Ordering) -> Comparison a
+ Chiasma.Prelude: Compose :: f (g a) -> Compose (f :: k -> Type) (g :: k1 -> k) (a :: k1)
+ Chiasma.Prelude: Const :: a -> Const a (b :: k)
+ Chiasma.Prelude: D# :: Double# -> Double
+ Chiasma.Prelude: Down :: a -> Down a
+ Chiasma.Prelude: Dual :: a -> Dual a
+ Chiasma.Prelude: EQ :: Ordering
+ Chiasma.Prelude: Endo :: (a -> a) -> Endo a
+ Chiasma.Prelude: Equivalence :: (a -> a -> Bool) -> Equivalence a
+ Chiasma.Prelude: ExceptT :: m (Either e a) -> ExceptT e (m :: Type -> Type) a
+ Chiasma.Prelude: F# :: Float# -> Float
+ Chiasma.Prelude: False :: Bool
+ Chiasma.Prelude: First :: Maybe a -> First a
+ Chiasma.Prelude: GT :: Ordering
+ Chiasma.Prelude: Identity :: a -> Identity a
+ Chiasma.Prelude: Just :: a -> Maybe a
+ Chiasma.Prelude: LT :: Ordering
+ Chiasma.Prelude: Last :: Maybe a -> Last a
+ Chiasma.Prelude: Left :: a -> Either a b
+ Chiasma.Prelude: MaybeT :: m (Maybe a) -> MaybeT (m :: Type -> Type) a
+ Chiasma.Prelude: Nothing :: Maybe a
+ Chiasma.Prelude: Op :: (b -> a) -> Op a b
+ Chiasma.Prelude: Option :: Maybe a -> Option a
+ Chiasma.Prelude: Predicate :: (a -> Bool) -> Predicate a
+ Chiasma.Prelude: Product :: a -> Product a
+ Chiasma.Prelude: Proxy :: Proxy (t :: k)
+ Chiasma.Prelude: ReadMode :: IOMode
+ Chiasma.Prelude: ReadWriteMode :: IOMode
+ Chiasma.Prelude: ReaderT :: (r -> m a) -> ReaderT r (m :: Type -> Type) a
+ Chiasma.Prelude: Right :: b -> Either a b
+ Chiasma.Prelude: SomeException :: e -> SomeException
+ Chiasma.Prelude: SomeNat :: Proxy n -> SomeNat
+ Chiasma.Prelude: StateT :: (s -> m (a, s)) -> StateT s (m :: Type -> Type) a
+ Chiasma.Prelude: Sum :: a -> Sum a
+ Chiasma.Prelude: True :: Bool
+ Chiasma.Prelude: Undefined :: Undefined
+ Chiasma.Prelude: WriteMode :: IOMode
+ Chiasma.Prelude: ZipList :: [a] -> ZipList a
+ Chiasma.Prelude: [appEndo] :: Endo a -> a -> a
+ Chiasma.Prelude: [getAll] :: All -> Bool
+ Chiasma.Prelude: [getAlt] :: Alt (f :: k -> Type) (a :: k) -> f a
+ Chiasma.Prelude: [getAny] :: Any -> Bool
+ Chiasma.Prelude: [getAp] :: Ap (f :: k -> Type) (a :: k) -> f a
+ Chiasma.Prelude: [getComparison] :: Comparison a -> a -> a -> Ordering
+ Chiasma.Prelude: [getCompose] :: Compose (f :: k -> Type) (g :: k1 -> k) (a :: k1) -> f (g a)
+ Chiasma.Prelude: [getConst] :: Const a (b :: k) -> a
+ Chiasma.Prelude: [getDown] :: Down a -> a
+ Chiasma.Prelude: [getDual] :: Dual a -> a
+ Chiasma.Prelude: [getEquivalence] :: Equivalence a -> a -> a -> Bool
+ Chiasma.Prelude: [getFirst] :: First a -> Maybe a
+ Chiasma.Prelude: [getLast] :: Last a -> Maybe a
+ Chiasma.Prelude: [getOp] :: Op a b -> b -> a
+ Chiasma.Prelude: [getOption] :: Option a -> Maybe a
+ Chiasma.Prelude: [getPredicate] :: Predicate a -> a -> Bool
+ Chiasma.Prelude: [getProduct] :: Product a -> a
+ Chiasma.Prelude: [getSum] :: Sum a -> a
+ Chiasma.Prelude: [getZipList] :: ZipList a -> [a]
+ Chiasma.Prelude: [runIdentity] :: Identity a -> a
+ Chiasma.Prelude: [runMaybeT] :: MaybeT (m :: Type -> Type) a -> m (Maybe a)
+ Chiasma.Prelude: [runReaderT] :: ReaderT r (m :: Type -> Type) a -> r -> m a
+ Chiasma.Prelude: [runStateT] :: StateT s (m :: Type -> Type) a -> s -> m (a, s)
+ Chiasma.Prelude: abs :: Num a => a -> a
+ Chiasma.Prelude: absurd :: Void -> a
+ Chiasma.Prelude: acos :: Floating a => a -> a
+ Chiasma.Prelude: acosh :: Floating a => a -> a
+ Chiasma.Prelude: all :: Foldable t => (a -> Bool) -> t a -> Bool
+ Chiasma.Prelude: allM :: (Foldable f, Monad m) => (a -> m Bool) -> f a -> m Bool
+ Chiasma.Prelude: and :: Foldable t => t Bool -> Bool
+ Chiasma.Prelude: andM :: (Foldable f, Monad m) => f (m Bool) -> m Bool
+ Chiasma.Prelude: any :: Foldable t => (a -> Bool) -> t a -> Bool
+ Chiasma.Prelude: anyM :: (Foldable f, Monad m) => (a -> m Bool) -> f a -> m Bool
+ Chiasma.Prelude: appendFile :: MonadIO m => FilePath -> String -> m ()
+ Chiasma.Prelude: appendFileBS :: MonadIO m => FilePath -> ByteString -> m ()
+ Chiasma.Prelude: appendFileLBS :: MonadIO m => FilePath -> LByteString -> m ()
+ Chiasma.Prelude: appendFileLText :: MonadIO m => FilePath -> LText -> m ()
+ Chiasma.Prelude: appendFileText :: MonadIO m => FilePath -> Text -> m ()
+ Chiasma.Prelude: appliedTo :: Applicative f => f a -> f (a -> b) -> f b
+ Chiasma.Prelude: asTypeOf :: a -> a -> a
+ Chiasma.Prelude: asin :: Floating a => a -> a
+ Chiasma.Prelude: asinh :: Floating a => a -> a
+ Chiasma.Prelude: asum :: (Foldable t, Alternative f) => t (f a) -> f a
+ Chiasma.Prelude: asumMap :: forall b m f a. (Foldable f, Alternative m) => (a -> m b) -> f a -> m b
+ Chiasma.Prelude: atan :: Floating a => a -> a
+ Chiasma.Prelude: atan2 :: RealFloat a => a -> a -> a
+ Chiasma.Prelude: atanh :: Floating a => a -> a
+ Chiasma.Prelude: atomicModifyIORef :: MonadIO m => IORef a -> (a -> (a, b)) -> m b
+ Chiasma.Prelude: atomicModifyIORef' :: MonadIO m => IORef a -> (a -> (a, b)) -> m b
+ Chiasma.Prelude: atomicModifyIORef'_ :: MonadIO m => IORef a -> (a -> a) -> m ()
+ Chiasma.Prelude: atomicModifyIORef_ :: MonadIO m => IORef a -> (a -> a) -> m ()
+ Chiasma.Prelude: atomicWriteIORef :: MonadIO m => IORef a -> a -> m ()
+ Chiasma.Prelude: atomically :: MonadIO m => STM a -> m a
+ Chiasma.Prelude: biList :: Bifoldable t => t a a -> [a]
+ Chiasma.Prelude: biall :: Bifoldable t => (a -> Bool) -> (b -> Bool) -> t a b -> Bool
+ Chiasma.Prelude: biand :: Bifoldable t => t Bool Bool -> Bool
+ Chiasma.Prelude: biany :: Bifoldable t => (a -> Bool) -> (b -> Bool) -> t a b -> Bool
+ Chiasma.Prelude: biasum :: (Bifoldable t, Alternative f) => t (f a) (f a) -> f a
+ Chiasma.Prelude: bielem :: (Bifoldable t, Eq a) => a -> t a a -> Bool
+ Chiasma.Prelude: bifind :: Bifoldable t => (a -> Bool) -> t a a -> Maybe a
+ Chiasma.Prelude: bifold :: (Bifoldable p, Monoid m) => p m m -> m
+ Chiasma.Prelude: bifoldMap :: (Bifoldable p, Monoid m) => (a -> m) -> (b -> m) -> p a b -> m
+ Chiasma.Prelude: bifoldMapDefault :: (Bitraversable t, Monoid m) => (a -> m) -> (b -> m) -> t a b -> m
+ Chiasma.Prelude: bifoldl :: Bifoldable p => (c -> a -> c) -> (c -> b -> c) -> c -> p a b -> c
+ Chiasma.Prelude: bifoldl' :: Bifoldable t => (a -> b -> a) -> (a -> c -> a) -> a -> t b c -> a
+ Chiasma.Prelude: bifoldlM :: (Bifoldable t, Monad m) => (a -> b -> m a) -> (a -> c -> m a) -> a -> t b c -> m a
+ Chiasma.Prelude: bifoldr :: Bifoldable p => (a -> c -> c) -> (b -> c -> c) -> c -> p a b -> c
+ Chiasma.Prelude: bifoldr' :: Bifoldable t => (a -> c -> c) -> (b -> c -> c) -> c -> t a b -> c
+ Chiasma.Prelude: bifoldrM :: (Bifoldable t, Monad m) => (a -> c -> m c) -> (b -> c -> m c) -> c -> t a b -> m c
+ Chiasma.Prelude: bifor :: (Bitraversable t, Applicative f) => t a b -> (a -> f c) -> (b -> f d) -> f (t c d)
+ Chiasma.Prelude: bifor_ :: (Bifoldable t, Applicative f) => t a b -> (a -> f c) -> (b -> f d) -> f ()
+ Chiasma.Prelude: bilength :: Bifoldable t => t a b -> Int
+ Chiasma.Prelude: bimap :: Bifunctor p => (a -> b) -> (c -> d) -> p a c -> p b d
+ Chiasma.Prelude: bimapDefault :: Bitraversable t => (a -> b) -> (c -> d) -> t a c -> t b d
+ Chiasma.Prelude: binull :: Bifoldable t => t a b -> Bool
+ Chiasma.Prelude: bior :: Bifoldable t => t Bool Bool -> Bool
+ Chiasma.Prelude: bisequence :: (Bitraversable t, Applicative f) => t (f a) (f b) -> f (t a b)
+ Chiasma.Prelude: bisequence_ :: (Bifoldable t, Applicative f) => t (f a) (f b) -> f ()
+ Chiasma.Prelude: bitraverse :: (Bitraversable t, Applicative f) => (a -> f c) -> (b -> f d) -> t a b -> f (t c d)
+ Chiasma.Prelude: bitraverse_ :: (Bifoldable t, Applicative f) => (a -> f c) -> (b -> f d) -> t a b -> f ()
+ Chiasma.Prelude: bool :: a -> a -> Bool -> a
+ Chiasma.Prelude: boundedEnumFrom :: (Enum a, Bounded a) => a -> [a]
+ Chiasma.Prelude: boundedEnumFromThen :: (Enum a, Bounded a) => a -> a -> [a]
+ Chiasma.Prelude: break :: (a -> Bool) -> [a] -> ([a], [a])
+ Chiasma.Prelude: bug :: (HasCallStack, Exception e) => e -> a
+ Chiasma.Prelude: byteSwap16 :: Word16 -> Word16
+ Chiasma.Prelude: byteSwap32 :: Word32 -> Word32
+ Chiasma.Prelude: byteSwap64 :: Word64 -> Word64
+ Chiasma.Prelude: callStack :: HasCallStack => CallStack
+ Chiasma.Prelude: catMaybes :: [Maybe a] -> [a]
+ Chiasma.Prelude: catchSTM :: Exception e => STM a -> (e -> STM a) -> STM a
+ Chiasma.Prelude: ceiling :: (RealFrac a, Integral b) => a -> b
+ Chiasma.Prelude: chainedTo :: Monad m => (a -> m b) -> m a -> m b
+ Chiasma.Prelude: chr :: Int -> Char
+ Chiasma.Prelude: class Applicative f => Alternative (f :: Type -> Type)
+ Chiasma.Prelude: class Functor f => Applicative (f :: Type -> Type)
+ Chiasma.Prelude: class Bifoldable (p :: Type -> Type -> Type)
+ Chiasma.Prelude: class Bifunctor (p :: Type -> Type -> Type)
+ Chiasma.Prelude: class (Bifunctor t, Bifoldable t) => Bitraversable (t :: Type -> Type -> Type)
+ Chiasma.Prelude: class Bounded a
+ Chiasma.Prelude: class a ~R# b => Coercible (a :: k) (b :: k)
+ Chiasma.Prelude: class Contravariant (f :: Type -> Type)
+ Chiasma.Prelude: class ConvertUtf8 a b
+ Chiasma.Prelude: class Default a
+ Chiasma.Prelude: class Enum a
+ Chiasma.Prelude: class Eq a
+ Chiasma.Prelude: class (Typeable e, Show e) => Exception e
+ Chiasma.Prelude: class Fractional a => Floating a
+ Chiasma.Prelude: class Foldable (t :: Type -> Type)
+ Chiasma.Prelude: class Num a => Fractional a
+ Chiasma.Prelude: class Functor (f :: Type -> Type)
+ Chiasma.Prelude: class Generic a
+ Chiasma.Prelude: class Hashable a
+ Chiasma.Prelude: class (Real a, Enum a) => Integral a
+ Chiasma.Prelude: class IsLabel (x :: Symbol) a
+ Chiasma.Prelude: class IsList l
+ Chiasma.Prelude: class IsString a
+ Chiasma.Prelude: class KnownNat (n :: Nat)
+ Chiasma.Prelude: class LazyStrict l s | l -> s, s -> l
+ Chiasma.Prelude: class Applicative m => Monad (m :: Type -> Type)
+ Chiasma.Prelude: class Monad m => MonadFail (m :: Type -> Type)
+ Chiasma.Prelude: class Monad m => MonadIO (m :: Type -> Type)
+ Chiasma.Prelude: class (Alternative m, Monad m) => MonadPlus (m :: Type -> Type)
+ Chiasma.Prelude: class Monad m => MonadReader r (m :: Type -> Type) | m -> r
+ Chiasma.Prelude: class Monad m => MonadState s (m :: Type -> Type) | m -> s
+ Chiasma.Prelude: class MonadTrans (t :: Type -> Type -> Type -> Type)
+ Chiasma.Prelude: class Semigroup a => Monoid a
+ Chiasma.Prelude: class NFData a
+ Chiasma.Prelude: class Num a
+ Chiasma.Prelude: class One x where {
+ Chiasma.Prelude: class Eq a => Ord a
+ Chiasma.Prelude: class Read a
+ Chiasma.Prelude: class (Num a, Ord a) => Real a
+ Chiasma.Prelude: class (RealFrac a, Floating a) => RealFloat a
+ Chiasma.Prelude: class (Real a, Fractional a) => RealFrac a
+ Chiasma.Prelude: class Semigroup a
+ Chiasma.Prelude: class Show a
+ Chiasma.Prelude: class ToLText a
+ Chiasma.Prelude: class ToString a
+ Chiasma.Prelude: class ToText a
+ Chiasma.Prelude: class (Functor t, Foldable t) => Traversable (t :: Type -> Type)
+ Chiasma.Prelude: class Typeable (a :: k)
+ Chiasma.Prelude: coerce :: forall (k :: RuntimeRep) (a :: TYPE k) (b :: TYPE k). Coercible a b => a -> b
+ Chiasma.Prelude: compare :: Ord a => a -> a -> Ordering
+ Chiasma.Prelude: comparing :: Ord a => (b -> a) -> b -> b -> Ordering
+ Chiasma.Prelude: comparisonEquivalence :: Comparison a -> Equivalence a
+ Chiasma.Prelude: concat :: Foldable t => t [a] -> [a]
+ Chiasma.Prelude: concatMap :: Foldable t => (a -> [b]) -> t a -> [b]
+ Chiasma.Prelude: const :: a -> b -> a
+ Chiasma.Prelude: contramap :: Contravariant f => (a -> b) -> f b -> f a
+ Chiasma.Prelude: cos :: Floating a => a -> a
+ Chiasma.Prelude: cosh :: Floating a => a -> a
+ Chiasma.Prelude: currentCallStack :: IO [String]
+ Chiasma.Prelude: curry :: ((a, b) -> c) -> a -> b -> c
+ Chiasma.Prelude: cycle :: [a] -> [a]
+ Chiasma.Prelude: cycle1 :: Semigroup m => m -> m
+ Chiasma.Prelude: data Bool
+ Chiasma.Prelude: data Bug
+ Chiasma.Prelude: data ByteString
+ Chiasma.Prelude: data CallStack
+ Chiasma.Prelude: data Char
+ Chiasma.Prelude: data Constraint
+ Chiasma.Prelude: data Double
+ Chiasma.Prelude: data Either a b
+ Chiasma.Prelude: data Float
+ Chiasma.Prelude: data Handle
+ Chiasma.Prelude: data HashMap k v
+ Chiasma.Prelude: data HashSet a
+ Chiasma.Prelude: data IO a
+ Chiasma.Prelude: data IOMode
+ Chiasma.Prelude: data IORef a
+ Chiasma.Prelude: data IdentityT (f :: k -> Type) (a :: k)
+ Chiasma.Prelude: data Int
+ Chiasma.Prelude: data Int16
+ Chiasma.Prelude: data Int32
+ Chiasma.Prelude: data Int64
+ Chiasma.Prelude: data Int8
+ Chiasma.Prelude: data IntMap a
+ Chiasma.Prelude: data IntSet
+ Chiasma.Prelude: data Integer
+ Chiasma.Prelude: data MVar a
+ Chiasma.Prelude: data Map k a
+ Chiasma.Prelude: data Maybe a
+ Chiasma.Prelude: data Nat
+ Chiasma.Prelude: data Natural
+ Chiasma.Prelude: data NonEmpty a
+ Chiasma.Prelude: data Ordering
+ Chiasma.Prelude: data Proxy (t :: k)
+ Chiasma.Prelude: data Ratio a
+ Chiasma.Prelude: data STM a
+ Chiasma.Prelude: data Seq a
+ Chiasma.Prelude: data Set a
+ Chiasma.Prelude: data ShortByteString
+ Chiasma.Prelude: data SomeException
+ Chiasma.Prelude: data SomeNat
+ Chiasma.Prelude: data TMVar a
+ Chiasma.Prelude: data TVar a
+ Chiasma.Prelude: data Text
+ Chiasma.Prelude: data Undefined
+ Chiasma.Prelude: data UnicodeException
+ Chiasma.Prelude: data Void
+ Chiasma.Prelude: data Word
+ Chiasma.Prelude: data Word16
+ Chiasma.Prelude: data Word32
+ Chiasma.Prelude: data Word64
+ Chiasma.Prelude: data Word8
+ Chiasma.Prelude: data WrappedMonoid m
+ Chiasma.Prelude: dbg :: Monad m => Text -> m ()
+ Chiasma.Prelude: dbgm :: Monad m => Show a => m a -> m a
+ Chiasma.Prelude: dbgs :: Monad m => Show a => a -> m ()
+ Chiasma.Prelude: decodeFloat :: RealFloat a => a -> (Integer, Int)
+ Chiasma.Prelude: decodeUtf8 :: ConvertUtf8 a b => b -> a
+ Chiasma.Prelude: decodeUtf8' :: ByteString -> Either UnicodeException Text
+ Chiasma.Prelude: decodeUtf8Strict :: ConvertUtf8 a b => b -> Either UnicodeException a
+ Chiasma.Prelude: decodeUtf8With :: OnDecodeError -> ByteString -> Text
+ Chiasma.Prelude: deepseq :: NFData a => a -> b -> b
+ Chiasma.Prelude: def :: Default a => a
+ Chiasma.Prelude: defaultComparison :: Ord a => Comparison a
+ Chiasma.Prelude: defaultEquivalence :: Eq a => Equivalence a
+ Chiasma.Prelude: denominator :: Ratio a -> a
+ Chiasma.Prelude: die :: MonadIO m => String -> m a
+ Chiasma.Prelude: displayException :: Exception e => e -> String
+ Chiasma.Prelude: div :: Integral a => a -> a -> a
+ Chiasma.Prelude: divMod :: Integral a => a -> a -> (a, a)
+ Chiasma.Prelude: drop :: Int -> [a] -> [a]
+ Chiasma.Prelude: dropWhile :: (a -> Bool) -> [a] -> [a]
+ Chiasma.Prelude: either :: (a -> c) -> (b -> c) -> Either a b -> c
+ Chiasma.Prelude: elem :: (Foldable f, DisallowElem f, Eq a) => a -> f a -> Bool
+ Chiasma.Prelude: empty :: Alternative f => f a
+ Chiasma.Prelude: encodeFloat :: RealFloat a => Integer -> Int -> a
+ Chiasma.Prelude: encodeUtf8 :: ConvertUtf8 a b => a -> b
+ Chiasma.Prelude: enumFrom :: Enum a => a -> [a]
+ Chiasma.Prelude: enumFromThen :: Enum a => a -> a -> [a]
+ Chiasma.Prelude: enumFromThenTo :: Enum a => a -> a -> a -> [a]
+ Chiasma.Prelude: enumFromTo :: Enum a => a -> a -> [a]
+ Chiasma.Prelude: error :: forall (r :: RuntimeRep) (a :: TYPE r) t. (HasCallStack, IsText t) => t -> a
+ Chiasma.Prelude: etaReaderT :: forall r (m :: Type -> Type) a. ReaderT r m a -> ReaderT r m a
+ Chiasma.Prelude: evalState :: State s a -> s -> a
+ Chiasma.Prelude: evalStateT :: Monad m => StateT s m a -> s -> m a
+ Chiasma.Prelude: evaluateNF :: (NFData a, MonadIO m) => a -> m a
+ Chiasma.Prelude: evaluateNF_ :: (NFData a, MonadIO m) => a -> m ()
+ Chiasma.Prelude: evaluateWHNF :: MonadIO m => a -> m a
+ Chiasma.Prelude: evaluateWHNF_ :: MonadIO m => a -> m ()
+ Chiasma.Prelude: evaluatingState :: s -> State s a -> a
+ Chiasma.Prelude: evaluatingStateT :: Functor f => s -> StateT s f a -> f a
+ Chiasma.Prelude: even :: Integral a => a -> Bool
+ Chiasma.Prelude: exceptToMaybeT :: forall (m :: Type -> Type) e a. Functor m => ExceptT e m a -> MaybeT m a
+ Chiasma.Prelude: execState :: State s a -> s -> s
+ Chiasma.Prelude: execStateT :: Monad m => StateT s m a -> s -> m s
+ Chiasma.Prelude: executingState :: s -> State s a -> s
+ Chiasma.Prelude: executingStateT :: Functor f => s -> StateT s f a -> f s
+ Chiasma.Prelude: exitFailure :: MonadIO m => m a
+ Chiasma.Prelude: exitSuccess :: MonadIO m => m a
+ Chiasma.Prelude: exitWith :: MonadIO m => ExitCode -> m a
+ Chiasma.Prelude: exp :: Floating a => a -> a
+ Chiasma.Prelude: fail :: MonadFail m => String -> m a
+ Chiasma.Prelude: filter :: (a -> Bool) -> [a] -> [a]
+ Chiasma.Prelude: filterM :: Applicative m => (a -> m Bool) -> [a] -> m [a]
+ Chiasma.Prelude: find :: Foldable t => (a -> Bool) -> t a -> Maybe a
+ Chiasma.Prelude: first :: Bifunctor p => (a -> b) -> p a c -> p b c
+ Chiasma.Prelude: fix :: (a -> a) -> a
+ Chiasma.Prelude: flap :: Functor f => f (a -> b) -> a -> f b
+ Chiasma.Prelude: flip :: (a -> b -> c) -> b -> a -> c
+ Chiasma.Prelude: flipfoldl' :: Foldable f => (a -> b -> b) -> b -> f a -> b
+ Chiasma.Prelude: floatDigits :: RealFloat a => a -> Int
+ Chiasma.Prelude: floatRadix :: RealFloat a => a -> Integer
+ Chiasma.Prelude: floatRange :: RealFloat a => a -> (Int, Int)
+ Chiasma.Prelude: floor :: (RealFrac a, Integral b) => a -> b
+ Chiasma.Prelude: fmap :: Functor f => (a -> b) -> f a -> f b
+ Chiasma.Prelude: fold :: (Foldable t, Monoid m) => t m -> m
+ Chiasma.Prelude: foldMap :: (Foldable t, Monoid m) => (a -> m) -> t a -> m
+ Chiasma.Prelude: foldMap' :: (Foldable t, Monoid m) => (a -> m) -> t a -> m
+ Chiasma.Prelude: foldMapA :: (Semigroup b, Monoid b, Applicative m, Foldable f) => (a -> m b) -> f a -> m b
+ Chiasma.Prelude: foldMapM :: (Monoid b, Monad m, Foldable f) => (a -> m b) -> f a -> m b
+ Chiasma.Prelude: foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b
+ Chiasma.Prelude: foldl' :: Foldable t => (b -> a -> b) -> b -> t a -> b
+ Chiasma.Prelude: foldlM :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b
+ Chiasma.Prelude: foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
+ Chiasma.Prelude: forM :: (Traversable t, Monad m) => t a -> (a -> m b) -> m (t b)
+ Chiasma.Prelude: forM_ :: (Foldable t, Monad m) => t a -> (a -> m b) -> m ()
+ Chiasma.Prelude: for_ :: (Foldable t, Applicative f) => t a -> (a -> f b) -> f ()
+ Chiasma.Prelude: force :: NFData a => a -> a
+ Chiasma.Prelude: forever :: Applicative f => f a -> f b
+ Chiasma.Prelude: fromEnum :: Enum a => a -> Int
+ Chiasma.Prelude: fromException :: Exception e => SomeException -> Maybe e
+ Chiasma.Prelude: fromInteger :: Num a => Integer -> a
+ Chiasma.Prelude: fromIntegral :: (Integral a, Num b) => a -> b
+ Chiasma.Prelude: fromLabel :: IsLabel x a => a
+ Chiasma.Prelude: fromLazy :: LazyStrict l s => l -> s
+ Chiasma.Prelude: fromLeft :: a -> Either a b -> a
+ Chiasma.Prelude: fromList :: IsList l => [Item l] -> l
+ Chiasma.Prelude: fromListN :: IsList l => Int -> [Item l] -> l
+ Chiasma.Prelude: fromMaybe :: a -> Maybe a -> a
+ Chiasma.Prelude: fromRational :: Fractional a => Rational -> a
+ Chiasma.Prelude: fromRight :: b -> Either a b -> b
+ Chiasma.Prelude: fromShort :: ShortByteString -> ByteString
+ Chiasma.Prelude: fromStrict :: LazyStrict l s => s -> l
+ Chiasma.Prelude: fromString :: IsString a => String -> a
+ Chiasma.Prelude: fst :: (a, b) -> a
+ Chiasma.Prelude: gcd :: Integral a => a -> a -> a
+ Chiasma.Prelude: genericDrop :: Integral i => i -> [a] -> [a]
+ Chiasma.Prelude: genericLength :: Num i => [a] -> i
+ Chiasma.Prelude: genericReplicate :: Integral i => i -> a -> [a]
+ Chiasma.Prelude: genericSplitAt :: Integral i => i -> [a] -> ([a], [a])
+ Chiasma.Prelude: genericTake :: Integral i => i -> [a] -> [a]
+ Chiasma.Prelude: getCallStack :: CallStack -> [([Char], SrcLoc)]
+ Chiasma.Prelude: getLine :: MonadIO m => m Text
+ Chiasma.Prelude: getStackTrace :: IO (Maybe [Location])
+ Chiasma.Prelude: group :: Eq a => [a] -> [[a]]
+ Chiasma.Prelude: guard :: Alternative f => Bool -> f ()
+ Chiasma.Prelude: guardM :: MonadPlus m => m Bool -> m ()
+ Chiasma.Prelude: guarded :: Alternative f => (a -> Bool) -> a -> f a
+ Chiasma.Prelude: hashNub :: (Eq a, Hashable a) => [a] -> [a]
+ Chiasma.Prelude: hashWithSalt :: Hashable a => Int -> a -> Int
+ Chiasma.Prelude: head :: IsNonEmpty f a a "head" => f a -> a
+ Chiasma.Prelude: id :: a -> a
+ Chiasma.Prelude: identity :: a -> a
+ Chiasma.Prelude: ifM :: Monad m => m Bool -> m a -> m a -> m a
+ Chiasma.Prelude: infix 4 >=
+ Chiasma.Prelude: infix 9 !!?
+ Chiasma.Prelude: infixl 0 `on`
+ Chiasma.Prelude: infixl 1 <&>
+ Chiasma.Prelude: infixl 3 <|>
+ Chiasma.Prelude: infixl 4 <<$>>
+ Chiasma.Prelude: infixl 6 `xor`
+ Chiasma.Prelude: infixl 7 *
+ Chiasma.Prelude: infixr 0 ?:
+ Chiasma.Prelude: infixr 1 =<<
+ Chiasma.Prelude: infixr 2 ||
+ Chiasma.Prelude: infixr 3 &&
+ Chiasma.Prelude: infixr 5 :|
+ Chiasma.Prelude: infixr 6 <>
+ Chiasma.Prelude: infixr 8 <$$>
+ Chiasma.Prelude: infixr 9 `Compose`
+ Chiasma.Prelude: init :: IsNonEmpty f a [a] "init" => f a -> [a]
+ Chiasma.Prelude: inits :: [a] -> [[a]]
+ Chiasma.Prelude: integerToBounded :: (Integral a, Bounded a) => Integer -> Maybe a
+ Chiasma.Prelude: integerToNatural :: Integer -> Maybe Natural
+ Chiasma.Prelude: intercalate :: [a] -> [[a]] -> [a]
+ Chiasma.Prelude: intersperse :: a -> [a] -> [a]
+ Chiasma.Prelude: isDenormalized :: RealFloat a => a -> Bool
+ Chiasma.Prelude: isEmptyTMVar :: TMVar a -> STM Bool
+ Chiasma.Prelude: isIEEE :: RealFloat a => a -> Bool
+ Chiasma.Prelude: isInfinite :: RealFloat a => a -> Bool
+ Chiasma.Prelude: isJust :: Maybe a -> Bool
+ Chiasma.Prelude: isLeft :: Either a b -> Bool
+ Chiasma.Prelude: isNaN :: RealFloat a => a -> Bool
+ Chiasma.Prelude: isNegativeZero :: RealFloat a => a -> Bool
+ Chiasma.Prelude: isNothing :: Maybe a -> Bool
+ Chiasma.Prelude: isPrefixOf :: Eq a => [a] -> [a] -> Bool
+ Chiasma.Prelude: isRight :: Either a b -> Bool
+ Chiasma.Prelude: iterate :: (a -> a) -> a -> [a]
+ Chiasma.Prelude: join :: Monad m => m (m a) -> m a
+ Chiasma.Prelude: last :: IsNonEmpty f a a "last" => f a -> a
+ Chiasma.Prelude: lcm :: Integral a => a -> a -> a
+ Chiasma.Prelude: leftToMaybe :: Either l r -> Maybe l
+ Chiasma.Prelude: lefts :: [Either a b] -> [a]
+ Chiasma.Prelude: length :: Foldable t => t a -> Int
+ Chiasma.Prelude: lenientDecode :: OnDecodeError
+ Chiasma.Prelude: lift :: (MonadTrans t, Monad m) => m a -> t m a
+ Chiasma.Prelude: liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c
+ Chiasma.Prelude: liftA3 :: Applicative f => (a -> b -> c -> d) -> f a -> f b -> f c -> f d
+ Chiasma.Prelude: liftIO :: MonadIO m => IO a -> m a
+ Chiasma.Prelude: lines :: IsText t "lines" => t -> [t]
+ Chiasma.Prelude: listToMaybe :: [a] -> Maybe a
+ Chiasma.Prelude: logBase :: Floating a => a -> a -> a
+ Chiasma.Prelude: makeClassy :: Name -> DecsQ
+ Chiasma.Prelude: many :: Alternative f => f a -> f [a]
+ Chiasma.Prelude: map :: (a -> b) -> [a] -> [b]
+ Chiasma.Prelude: mapAccumL :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)
+ Chiasma.Prelude: mapAccumR :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)
+ Chiasma.Prelude: mapAndUnzipM :: Applicative m => (a -> m (b, c)) -> [a] -> m ([b], [c])
+ Chiasma.Prelude: mapLeft :: (a -> c) -> Either a b -> Either c b
+ Chiasma.Prelude: mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)
+ Chiasma.Prelude: mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()
+ Chiasma.Prelude: mapMaybe :: (a -> Maybe b) -> [a] -> [b]
+ Chiasma.Prelude: mapMaybeM :: Monad m => (a -> m (Maybe b)) -> [a] -> m [b]
+ Chiasma.Prelude: mappend :: Monoid a => a -> a -> a
+ Chiasma.Prelude: max :: Ord a => a -> a -> a
+ Chiasma.Prelude: maxBound :: Bounded a => a
+ Chiasma.Prelude: maxInt :: Int
+ Chiasma.Prelude: maybe :: b -> (a -> b) -> Maybe a -> b
+ Chiasma.Prelude: maybeToExceptT :: forall (m :: Type -> Type) e a. Functor m => e -> MaybeT m a -> ExceptT e m a
+ Chiasma.Prelude: maybeToLeft :: r -> Maybe l -> Either l r
+ Chiasma.Prelude: maybeToList :: Maybe a -> [a]
+ Chiasma.Prelude: maybeToMonoid :: Monoid m => Maybe m -> m
+ Chiasma.Prelude: maybeToRight :: l -> Maybe r -> Either l r
+ Chiasma.Prelude: mconcat :: Monoid a => [a] -> a
+ Chiasma.Prelude: mempty :: Monoid a => a
+ Chiasma.Prelude: memptyIfFalse :: Monoid m => Bool -> m -> m
+ Chiasma.Prelude: memptyIfTrue :: Monoid m => Bool -> m -> m
+ Chiasma.Prelude: mfilter :: MonadPlus m => (a -> Bool) -> m a -> m a
+ Chiasma.Prelude: min :: Ord a => a -> a -> a
+ Chiasma.Prelude: minBound :: Bounded a => a
+ Chiasma.Prelude: minInt :: Int
+ Chiasma.Prelude: mkWeakTMVar :: TMVar a -> IO () -> IO (Weak (TMVar a))
+ Chiasma.Prelude: mod :: Integral a => a -> a -> a
+ Chiasma.Prelude: modify' :: MonadState s m => (s -> s) -> m ()
+ Chiasma.Prelude: modifyIORef :: MonadIO m => IORef a -> (a -> a) -> m ()
+ Chiasma.Prelude: modifyIORef' :: MonadIO m => IORef a -> (a -> a) -> m ()
+ Chiasma.Prelude: modifyTVar' :: TVar a -> (a -> a) -> STM ()
+ Chiasma.Prelude: mplus :: MonadPlus m => m a -> m a -> m a
+ Chiasma.Prelude: mtimesDefault :: (Integral b, Monoid a) => b -> a -> a
+ Chiasma.Prelude: mzero :: MonadPlus m => m a
+ Chiasma.Prelude: natVal :: forall (n :: Nat) proxy. KnownNat n => proxy n -> Natural
+ Chiasma.Prelude: negate :: Num a => a -> a
+ Chiasma.Prelude: newEmptyMVar :: MonadIO m => m (MVar a)
+ Chiasma.Prelude: newEmptyTMVar :: STM (TMVar a)
+ Chiasma.Prelude: newEmptyTMVarIO :: MonadIO m => m (TMVar a)
+ Chiasma.Prelude: newIORef :: MonadIO m => a -> m (IORef a)
+ Chiasma.Prelude: newMVar :: MonadIO m => a -> m (MVar a)
+ Chiasma.Prelude: newTMVar :: a -> STM (TMVar a)
+ Chiasma.Prelude: newTMVarIO :: MonadIO m => a -> m (TMVar a)
+ Chiasma.Prelude: newTVar :: a -> STM (TVar a)
+ Chiasma.Prelude: newTVarIO :: MonadIO m => a -> m (TVar a)
+ Chiasma.Prelude: newtype All
+ Chiasma.Prelude: newtype Alt (f :: k -> Type) (a :: k)
+ Chiasma.Prelude: newtype Any
+ Chiasma.Prelude: newtype Ap (f :: k -> Type) (a :: k)
+ Chiasma.Prelude: newtype Comparison a
+ Chiasma.Prelude: newtype Compose (f :: k -> Type) (g :: k1 -> k) (a :: k1)
+ Chiasma.Prelude: newtype Const a (b :: k)
+ Chiasma.Prelude: newtype Down a
+ Chiasma.Prelude: newtype Dual a
+ Chiasma.Prelude: newtype Endo a
+ Chiasma.Prelude: newtype Equivalence a
+ Chiasma.Prelude: newtype ExceptT e (m :: Type -> Type) a
+ Chiasma.Prelude: newtype First a
+ Chiasma.Prelude: newtype Identity a
+ Chiasma.Prelude: newtype Last a
+ Chiasma.Prelude: newtype MaybeT (m :: Type -> Type) a
+ Chiasma.Prelude: newtype Op a b
+ Chiasma.Prelude: newtype Option a
+ Chiasma.Prelude: newtype Predicate a
+ Chiasma.Prelude: newtype Product a
+ Chiasma.Prelude: newtype ReaderT r (m :: Type -> Type) a
+ Chiasma.Prelude: newtype StateT s (m :: Type -> Type) a
+ Chiasma.Prelude: newtype Sum a
+ Chiasma.Prelude: newtype ZipList a
+ Chiasma.Prelude: nonEmpty :: [a] -> Maybe (NonEmpty a)
+ Chiasma.Prelude: not :: Bool -> Bool
+ Chiasma.Prelude: notElem :: (Foldable f, DisallowElem f, Eq a) => a -> f a -> Bool
+ Chiasma.Prelude: null :: Foldable t => t a -> Bool
+ Chiasma.Prelude: numerator :: Ratio a -> a
+ Chiasma.Prelude: odd :: Integral a => a -> Bool
+ Chiasma.Prelude: on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
+ Chiasma.Prelude: one :: One x => OneItem x -> x
+ Chiasma.Prelude: optional :: Alternative f => f a -> f (Maybe a)
+ Chiasma.Prelude: or :: Foldable t => t Bool -> Bool
+ Chiasma.Prelude: orM :: (Foldable f, Monad m) => f (m Bool) -> m Bool
+ Chiasma.Prelude: ord :: Char -> Int
+ Chiasma.Prelude: ordNub :: Ord a => [a] -> [a]
+ Chiasma.Prelude: otherwise :: Bool
+ Chiasma.Prelude: partitionEithers :: [Either a b] -> ([a], [b])
+ Chiasma.Prelude: pass :: Applicative f => f ()
+ Chiasma.Prelude: pattern Exc :: Exception e => e -> SomeException
+ Chiasma.Prelude: permutations :: [a] -> [[a]]
+ Chiasma.Prelude: phantom :: (Functor f, Contravariant f) => f a -> f b
+ Chiasma.Prelude: pi :: Floating a => a
+ Chiasma.Prelude: pred :: Enum a => a -> a
+ Chiasma.Prelude: prettyCallStack :: CallStack -> String
+ Chiasma.Prelude: prettySrcLoc :: SrcLoc -> String
+ Chiasma.Prelude: print :: forall a m. (MonadIO m, Show a) => a -> m ()
+ Chiasma.Prelude: product :: forall a f. (Foldable f, Num a) => f a -> a
+ Chiasma.Prelude: properFraction :: (RealFrac a, Integral b) => a -> (b, a)
+ Chiasma.Prelude: pure :: Applicative f => a -> f a
+ Chiasma.Prelude: putBS :: MonadIO m => ByteString -> m ()
+ Chiasma.Prelude: putBSLn :: MonadIO m => ByteString -> m ()
+ Chiasma.Prelude: putLBS :: MonadIO m => LByteString -> m ()
+ Chiasma.Prelude: putLBSLn :: MonadIO m => LByteString -> m ()
+ Chiasma.Prelude: putLText :: MonadIO m => LText -> m ()
+ Chiasma.Prelude: putLTextLn :: MonadIO m => LText -> m ()
+ Chiasma.Prelude: putMVar :: MonadIO m => MVar a -> a -> m ()
+ Chiasma.Prelude: putStr :: MonadIO m => String -> m ()
+ Chiasma.Prelude: putStrLn :: MonadIO m => String -> m ()
+ Chiasma.Prelude: putTMVar :: TMVar a -> a -> STM ()
+ Chiasma.Prelude: putText :: MonadIO m => Text -> m ()
+ Chiasma.Prelude: putTextLn :: MonadIO m => Text -> m ()
+ Chiasma.Prelude: quot :: Integral a => a -> a -> a
+ Chiasma.Prelude: quotRem :: Integral a => a -> a -> (a, a)
+ Chiasma.Prelude: readEither :: Read a => String -> Either Text a
+ Chiasma.Prelude: readFile :: MonadIO m => FilePath -> m String
+ Chiasma.Prelude: readFileBS :: MonadIO m => FilePath -> m ByteString
+ Chiasma.Prelude: readFileLBS :: MonadIO m => FilePath -> m LByteString
+ Chiasma.Prelude: readFileLText :: MonadIO m => FilePath -> m LText
+ Chiasma.Prelude: readFileText :: MonadIO m => FilePath -> m Text
+ Chiasma.Prelude: readIORef :: MonadIO m => IORef a -> m a
+ Chiasma.Prelude: readMVar :: MonadIO m => MVar a -> m a
+ Chiasma.Prelude: readMaybe :: Read a => String -> Maybe a
+ Chiasma.Prelude: readTMVar :: TMVar a -> STM a
+ Chiasma.Prelude: readTVar :: TVar a -> STM a
+ Chiasma.Prelude: readTVarIO :: MonadIO m => TVar a -> m a
+ Chiasma.Prelude: reader :: MonadReader r m => (r -> a) -> m a
+ Chiasma.Prelude: reads :: Read a => ReadS a
+ Chiasma.Prelude: realToFrac :: (Real a, Fractional b) => a -> b
+ Chiasma.Prelude: recip :: Fractional a => a -> a
+ Chiasma.Prelude: rem :: Integral a => a -> a -> a
+ Chiasma.Prelude: repeat :: a -> [a]
+ Chiasma.Prelude: replicate :: Int -> a -> [a]
+ Chiasma.Prelude: replicateM :: Applicative m => Int -> m a -> m [a]
+ Chiasma.Prelude: replicateM_ :: Applicative m => Int -> m a -> m ()
+ Chiasma.Prelude: return :: Monad m => a -> m a
+ Chiasma.Prelude: reverse :: [a] -> [a]
+ Chiasma.Prelude: rightToMaybe :: Either l r -> Maybe r
+ Chiasma.Prelude: rights :: [Either a b] -> [b]
+ Chiasma.Prelude: rnf :: NFData a => a -> ()
+ Chiasma.Prelude: round :: (RealFrac a, Integral b) => a -> b
+ Chiasma.Prelude: runExceptT :: ExceptT e m a -> m (Either e a)
+ Chiasma.Prelude: runReader :: Reader r a -> r -> a
+ Chiasma.Prelude: runState :: State s a -> s -> (a, s)
+ Chiasma.Prelude: scanl :: (b -> a -> b) -> b -> [a] -> [b]
+ Chiasma.Prelude: scanl' :: (b -> a -> b) -> b -> [a] -> [b]
+ Chiasma.Prelude: scanl1 :: (a -> a -> a) -> [a] -> [a]
+ Chiasma.Prelude: scanr :: (a -> b -> b) -> b -> [a] -> [b]
+ Chiasma.Prelude: scanr1 :: (a -> a -> a) -> [a] -> [a]
+ Chiasma.Prelude: sconcat :: Semigroup a => NonEmpty a -> a
+ Chiasma.Prelude: second :: Bifunctor p => (b -> c) -> p a b -> p a c
+ Chiasma.Prelude: seq :: forall (r :: RuntimeRep) a (b :: TYPE r). a -> b -> b
+ Chiasma.Prelude: sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)
+ Chiasma.Prelude: sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)
+ Chiasma.Prelude: sequenceA_ :: (Foldable t, Applicative f) => t (f a) -> f ()
+ Chiasma.Prelude: sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()
+ Chiasma.Prelude: show :: forall b a. (Show a, IsString b) => a -> b
+ Chiasma.Prelude: showStackTrace :: IO (Maybe String)
+ Chiasma.Prelude: signum :: Num a => a -> a
+ Chiasma.Prelude: sin :: Floating a => a -> a
+ Chiasma.Prelude: sinh :: Floating a => a -> a
+ Chiasma.Prelude: snd :: (a, b) -> b
+ Chiasma.Prelude: some :: Alternative f => f a -> f [a]
+ Chiasma.Prelude: someNatVal :: Natural -> SomeNat
+ Chiasma.Prelude: sort :: Ord a => [a] -> [a]
+ Chiasma.Prelude: sortBy :: (a -> a -> Ordering) -> [a] -> [a]
+ Chiasma.Prelude: sortNub :: Ord a => [a] -> [a]
+ Chiasma.Prelude: sortOn :: Ord b => (a -> b) -> [a] -> [a]
+ Chiasma.Prelude: sortWith :: Ord b => (a -> b) -> [a] -> [a]
+ Chiasma.Prelude: splitAt :: Int -> [a] -> ([a], [a])
+ Chiasma.Prelude: sqrt :: Floating a => a -> a
+ Chiasma.Prelude: stderr :: Handle
+ Chiasma.Prelude: stdin :: Handle
+ Chiasma.Prelude: stdout :: Handle
+ Chiasma.Prelude: stimes :: (Semigroup a, Integral b) => b -> a -> a
+ Chiasma.Prelude: stimesIdempotent :: Integral b => b -> a -> a
+ Chiasma.Prelude: stimesIdempotentMonoid :: (Integral b, Monoid a) => b -> a -> a
+ Chiasma.Prelude: stimesMonoid :: (Integral b, Monoid a) => b -> a -> a
+ Chiasma.Prelude: strictDecode :: OnDecodeError
+ Chiasma.Prelude: subsequences :: [a] -> [[a]]
+ Chiasma.Prelude: subtract :: Num a => a -> a -> a
+ Chiasma.Prelude: succ :: Enum a => a -> a
+ Chiasma.Prelude: sum :: forall a f. (Foldable f, Num a) => f a -> a
+ Chiasma.Prelude: swap :: (a, b) -> (b, a)
+ Chiasma.Prelude: swapMVar :: MonadIO m => MVar a -> a -> m a
+ Chiasma.Prelude: swapTMVar :: TMVar a -> a -> STM a
+ Chiasma.Prelude: tail :: IsNonEmpty f a [a] "tail" => f a -> [a]
+ Chiasma.Prelude: tails :: [a] -> [[a]]
+ Chiasma.Prelude: take :: Int -> [a] -> [a]
+ Chiasma.Prelude: takeMVar :: MonadIO m => MVar a -> m a
+ Chiasma.Prelude: takeTMVar :: TMVar a -> STM a
+ Chiasma.Prelude: takeWhile :: (a -> Bool) -> [a] -> [a]
+ Chiasma.Prelude: tan :: Floating a => a -> a
+ Chiasma.Prelude: tanh :: Floating a => a -> a
+ Chiasma.Prelude: throwSTM :: Exception e => e -> STM a
+ Chiasma.Prelude: toEnum :: Enum a => Int -> a
+ Chiasma.Prelude: toException :: Exception e => e -> SomeException
+ Chiasma.Prelude: toInteger :: Integral a => a -> Integer
+ Chiasma.Prelude: toIntegralSized :: (Integral a, Integral b, Bits a, Bits b) => a -> Maybe b
+ Chiasma.Prelude: toLText :: ToLText a => a -> LText
+ Chiasma.Prelude: toLazy :: LazyStrict l s => s -> l
+ Chiasma.Prelude: toList :: Foldable t => t a -> [a]
+ Chiasma.Prelude: toRational :: Real a => a -> Rational
+ Chiasma.Prelude: toShort :: ByteString -> ShortByteString
+ Chiasma.Prelude: toStrict :: LazyStrict l s => l -> s
+ Chiasma.Prelude: toString :: ToString a => a -> String
+ Chiasma.Prelude: toText :: ToText a => a -> Text
+ Chiasma.Prelude: trace :: String -> a -> a
+ Chiasma.Prelude: traceId :: String -> String
+ Chiasma.Prelude: traceM :: Applicative f => String -> f ()
+ Chiasma.Prelude: traceShow :: Show a => a -> b -> b
+ Chiasma.Prelude: traceShowId :: Show a => a -> a
+ Chiasma.Prelude: traceShowM :: (Show a, Applicative f) => a -> f ()
+ Chiasma.Prelude: transpose :: [[a]] -> [[a]]
+ Chiasma.Prelude: traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)
+ Chiasma.Prelude: traverse_ :: (Foldable t, Applicative f) => (a -> f b) -> t a -> f ()
+ Chiasma.Prelude: truncate :: (RealFrac a, Integral b) => a -> b
+ Chiasma.Prelude: tryPutMVar :: MonadIO m => MVar a -> a -> m Bool
+ Chiasma.Prelude: tryPutTMVar :: TMVar a -> a -> STM Bool
+ Chiasma.Prelude: tryReadMVar :: MonadIO m => MVar a -> m (Maybe a)
+ Chiasma.Prelude: tryReadTMVar :: TMVar a -> STM (Maybe a)
+ Chiasma.Prelude: tryTakeMVar :: MonadIO m => MVar a -> m (Maybe a)
+ Chiasma.Prelude: tryTakeTMVar :: TMVar a -> STM (Maybe a)
+ Chiasma.Prelude: tuple :: Applicative f => f a -> f b -> f (a, b)
+ Chiasma.Prelude: type FilePath = String
+ Chiasma.Prelude: type HasCallStack = ?callStack :: CallStack
+ Chiasma.Prelude: type LByteString = ByteString
+ Chiasma.Prelude: type LText = Text
+ Chiasma.Prelude: type OnDecodeError = OnError Word8 Char
+ Chiasma.Prelude: type OnError a b = String -> Maybe a -> Maybe b
+ Chiasma.Prelude: type Rational = Ratio Integer
+ Chiasma.Prelude: type Reader r = ReaderT r Identity
+ Chiasma.Prelude: type State s = StateT s Identity
+ Chiasma.Prelude: type String = [Char]
+ Chiasma.Prelude: type family OneItem x;
+ Chiasma.Prelude: uncons :: [a] -> Maybe (a, [a])
+ Chiasma.Prelude: uncurry :: (a -> b -> c) -> (a, b) -> c
+ Chiasma.Prelude: undefined :: forall (r :: RuntimeRep) (a :: TYPE r). HasCallStack => a
+ Chiasma.Prelude: unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
+ Chiasma.Prelude: unit :: Applicative f => f ()
+ Chiasma.Prelude: unless :: Applicative f => Bool -> f () -> f ()
+ Chiasma.Prelude: unlessM :: Monad m => m Bool -> m () -> m ()
+ Chiasma.Prelude: unlines :: IsText t "unlines" => [t] -> t
+ Chiasma.Prelude: unsafeLogAnd :: Text -> b -> b
+ Chiasma.Prelude: unsafeLogS :: Show a => a -> a
+ Chiasma.Prelude: unsafeLogSAnd :: Show a => a -> b -> b
+ Chiasma.Prelude: unstableNub :: (Eq a, Hashable a) => [a] -> [a]
+ Chiasma.Prelude: unwords :: IsText t "unwords" => [t] -> t
+ Chiasma.Prelude: unzip :: [(a, b)] -> ([a], [b])
+ Chiasma.Prelude: unzip3 :: [(a, b, c)] -> ([a], [b], [c])
+ Chiasma.Prelude: usingReader :: r -> Reader r a -> a
+ Chiasma.Prelude: usingReaderT :: r -> ReaderT r m a -> m a
+ Chiasma.Prelude: usingState :: s -> State s a -> (a, s)
+ Chiasma.Prelude: usingStateT :: s -> StateT s m a -> m (a, s)
+ Chiasma.Prelude: vacuous :: Functor f => f Void -> f a
+ Chiasma.Prelude: viaNonEmpty :: (NonEmpty a -> b) -> [a] -> Maybe b
+ Chiasma.Prelude: void :: Functor f => f a -> f ()
+ Chiasma.Prelude: when :: Applicative f => Bool -> f () -> f ()
+ Chiasma.Prelude: whenJust :: Applicative f => Maybe a -> (a -> f ()) -> f ()
+ Chiasma.Prelude: whenJustM :: Monad m => m (Maybe a) -> (a -> m ()) -> m ()
+ Chiasma.Prelude: whenLeft :: Applicative f => a -> Either l r -> (l -> f a) -> f a
+ Chiasma.Prelude: whenLeftM :: Monad m => a -> m (Either l r) -> (l -> m a) -> m a
+ Chiasma.Prelude: whenLeftM_ :: Monad m => m (Either l r) -> (l -> m ()) -> m ()
+ Chiasma.Prelude: whenLeft_ :: Applicative f => Either l r -> (l -> f ()) -> f ()
+ Chiasma.Prelude: whenM :: Monad m => m Bool -> m () -> m ()
+ Chiasma.Prelude: whenNotNull :: Applicative f => [a] -> (NonEmpty a -> f ()) -> f ()
+ Chiasma.Prelude: whenNotNullM :: Monad m => m [a] -> (NonEmpty a -> m ()) -> m ()
+ Chiasma.Prelude: whenNothing :: Applicative f => Maybe a -> f a -> f a
+ Chiasma.Prelude: whenNothingM :: Monad m => m (Maybe a) -> m a -> m a
+ Chiasma.Prelude: whenNothingM_ :: Monad m => m (Maybe a) -> m () -> m ()
+ Chiasma.Prelude: whenNothing_ :: Applicative f => Maybe a -> f () -> f ()
+ Chiasma.Prelude: whenRight :: Applicative f => a -> Either l r -> (r -> f a) -> f a
+ Chiasma.Prelude: whenRightM :: Monad m => a -> m (Either l r) -> (r -> m a) -> m a
+ Chiasma.Prelude: whenRightM_ :: Monad m => m (Either l r) -> (r -> m ()) -> m ()
+ Chiasma.Prelude: whenRight_ :: Applicative f => Either l r -> (r -> f ()) -> f ()
+ Chiasma.Prelude: withFile :: FilePath -> IOMode -> (Handle -> IO r) -> IO r
+ Chiasma.Prelude: withFrozenCallStack :: HasCallStack => (HasCallStack => a) -> a
+ Chiasma.Prelude: withReader :: (r' -> r) -> Reader r a -> Reader r' a
+ Chiasma.Prelude: withReaderT :: forall r' r (m :: Type -> Type) a. (r' -> r) -> ReaderT r m a -> ReaderT r' m a
+ Chiasma.Prelude: withState :: (s -> s) -> State s a -> State s a
+ Chiasma.Prelude: words :: IsText t "words" => t -> [t]
+ Chiasma.Prelude: writeFile :: MonadIO m => FilePath -> String -> m ()
+ Chiasma.Prelude: writeFileBS :: MonadIO m => FilePath -> ByteString -> m ()
+ Chiasma.Prelude: writeFileLBS :: MonadIO m => FilePath -> LByteString -> m ()
+ Chiasma.Prelude: writeFileLText :: MonadIO m => FilePath -> LText -> m ()
+ Chiasma.Prelude: writeFileText :: MonadIO m => FilePath -> Text -> m ()
+ Chiasma.Prelude: writeIORef :: MonadIO m => IORef a -> a -> m ()
+ Chiasma.Prelude: writeTVar :: TVar a -> a -> STM ()
+ Chiasma.Prelude: xor :: Bits a => a -> a -> a
+ Chiasma.Prelude: zip :: [a] -> [b] -> [(a, b)]
+ Chiasma.Prelude: zip3 :: [a] -> [b] -> [c] -> [(a, b, c)]
+ Chiasma.Prelude: zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
+ Chiasma.Prelude: zipWithM :: Applicative m => (a -> b -> m c) -> [a] -> [b] -> m [c]
+ Chiasma.Prelude: zipWithM_ :: Applicative m => (a -> b -> m c) -> [a] -> [b] -> m ()
+ Chiasma.Prelude: }
+ Chiasma.Render: render :: (MonadDeepState s Views m, MonadFree TmuxThunk m, MonadError RenderError m) => FilePath -> Ident -> Ident -> ViewTree -> m ()
+ Chiasma.Render: renderTree :: (MonadDeepState s Views m, MonadFree TmuxThunk m) => Ident -> Window -> RenderableTree -> m ()
+ Chiasma.Session: ensureSession :: MonadDeepState s Views m => MonadFree TmuxThunk m => View SessionId -> View WindowId -> m (SessionId, Maybe WindowId)
+ Chiasma.Session: findOrCreateSession :: MonadDeepState s Views m => Ident -> m (View SessionId)
+ Chiasma.Session: spawnSession :: MonadDeepState s Views m => MonadFree TmuxThunk m => View SessionId -> View WindowId -> m (SessionId, WindowId)
+ Chiasma.Test.Screenshot: loadScreenshot :: MonadIO m => FilePath -> m (Maybe Text)
+ Chiasma.Test.Screenshot: recordScreenshot :: MonadFree TmuxThunk m => MonadIO m => FilePath -> Int -> m ()
+ Chiasma.Test.Screenshot: screenshot :: MonadFree TmuxThunk m => MonadIO m => Bool -> FilePath -> Text -> Int -> m (Maybe ([Text], [Text]))
+ Chiasma.Test.Screenshot: storeScreenshot :: MonadIO m => FilePath -> [Text] -> m ()
+ Chiasma.Test.Screenshot: takeScreenshot :: MonadFree TmuxThunk m => MonadIO m => Int -> m [Text]
+ Chiasma.Test.Screenshot: testScreenshot :: MonadFree TmuxThunk m => MonadIO m => FilePath -> Int -> m (Maybe ([Text], [Text]))
+ Chiasma.Test.Tmux: Terminal :: Handle -> Pty -> Terminal
+ Chiasma.Test.Tmux: TmuxTestConf :: Int -> Int -> Int -> Bool -> TmuxTestConf
+ Chiasma.Test.Tmux: [$sel:ttcFontSize:TmuxTestConf] :: TmuxTestConf -> Int
+ Chiasma.Test.Tmux: [$sel:ttcGui:TmuxTestConf] :: TmuxTestConf -> Bool
+ Chiasma.Test.Tmux: [$sel:ttcHeight:TmuxTestConf] :: TmuxTestConf -> Int
+ Chiasma.Test.Tmux: [$sel:ttcWidth:TmuxTestConf] :: TmuxTestConf -> Int
+ Chiasma.Test.Tmux: data Terminal
+ Chiasma.Test.Tmux: data TmuxTestConf
+ Chiasma.Test.Tmux: instance Data.Default.Class.Default Chiasma.Test.Tmux.TmuxTestConf
+ Chiasma.Test.Tmux: instance GHC.Classes.Eq Chiasma.Test.Tmux.TmuxTestConf
+ Chiasma.Test.Tmux: instance GHC.Show.Show Chiasma.Test.Tmux.TmuxTestConf
+ Chiasma.Test.Tmux: killPid :: Integral a => a -> IO ()
+ Chiasma.Test.Tmux: killProcess :: TmuxNative -> Process () () () -> IO ()
+ Chiasma.Test.Tmux: runAndKillTmux :: (TmuxNative -> IO a) -> TmuxNative -> Process () () () -> IO a
+ Chiasma.Test.Tmux: sleep :: MonadIO f => Double -> f ()
+ Chiasma.Test.Tmux: testTmuxProcessConfig :: TmuxTestConf -> FilePath -> FilePath -> Terminal -> IO (ProcessConfig () () ())
+ Chiasma.Test.Tmux: tmuxGuiSpec :: (TmuxNative -> IO a) -> IO a
+ Chiasma.Test.Tmux: tmuxSpec' :: TmuxTestConf -> (TmuxNative -> IO a) -> IO a
+ Chiasma.Test.Tmux: unsafeTerminal :: IO Terminal
+ Chiasma.Test.Tmux: urxvtArgs :: Int -> Int -> Int -> [Text]
+ Chiasma.Test.Tmux: usleep :: MonadIO f => Double -> f ()
+ Chiasma.Ui.Data.Measure: MLayout :: PaneId -> Int -> Int -> Bool -> MLayout
+ Chiasma.Ui.Data.Measure: MPane :: PaneId -> Int -> Int -> MPane
+ Chiasma.Ui.Data.Measure: Measured :: Int -> a -> Measured a
+ Chiasma.Ui.Data.Measure: [$sel:_lMainPosition:MLayout] :: MLayout -> Int
+ Chiasma.Ui.Data.Measure: [$sel:_lOffPosition:MLayout] :: MLayout -> Int
+ Chiasma.Ui.Data.Measure: [$sel:_mainPosition:MPane] :: MPane -> Int
+ Chiasma.Ui.Data.Measure: [$sel:_offPosition:MPane] :: MPane -> Int
+ Chiasma.Ui.Data.Measure: [$sel:_paneId:MPane] :: MPane -> PaneId
+ Chiasma.Ui.Data.Measure: [$sel:_reference:MLayout] :: MLayout -> PaneId
+ Chiasma.Ui.Data.Measure: [$sel:_size:Measured] :: Measured a -> Int
+ Chiasma.Ui.Data.Measure: [$sel:_vertical:MLayout] :: MLayout -> Bool
+ Chiasma.Ui.Data.Measure: [$sel:_view:Measured] :: Measured a -> a
+ Chiasma.Ui.Data.Measure: class HasMLayout c_avMv
+ Chiasma.Ui.Data.Measure: class HasMPane c_avGZ
+ Chiasma.Ui.Data.Measure: class HasMeasured c_avSQ a_avN4 | c_avSQ -> a_avN4
+ Chiasma.Ui.Data.Measure: data MLayout
+ Chiasma.Ui.Data.Measure: data MPane
+ Chiasma.Ui.Data.Measure: data Measured a
+ Chiasma.Ui.Data.Measure: instance Chiasma.Ui.Data.Measure.HasMLayout Chiasma.Ui.Data.Measure.MLayout
+ Chiasma.Ui.Data.Measure: instance Chiasma.Ui.Data.Measure.HasMPane Chiasma.Ui.Data.Measure.MPane
+ Chiasma.Ui.Data.Measure: instance Chiasma.Ui.Data.Measure.HasMeasured (Chiasma.Ui.Data.Measure.Measured a) a
+ Chiasma.Ui.Data.Measure: instance GHC.Classes.Eq Chiasma.Ui.Data.Measure.MLayout
+ Chiasma.Ui.Data.Measure: instance GHC.Classes.Eq Chiasma.Ui.Data.Measure.MPane
+ Chiasma.Ui.Data.Measure: instance GHC.Classes.Eq a => GHC.Classes.Eq (Chiasma.Ui.Data.Measure.Measured a)
+ Chiasma.Ui.Data.Measure: instance GHC.Show.Show Chiasma.Ui.Data.Measure.MLayout
+ Chiasma.Ui.Data.Measure: instance GHC.Show.Show Chiasma.Ui.Data.Measure.MPane
+ Chiasma.Ui.Data.Measure: instance GHC.Show.Show a => GHC.Show.Show (Chiasma.Ui.Data.Measure.Measured a)
+ Chiasma.Ui.Data.Measure: instance Prettyprinter.Internal.Pretty Chiasma.Ui.Data.Measure.MLayout
+ Chiasma.Ui.Data.Measure: instance Prettyprinter.Internal.Pretty Chiasma.Ui.Data.Measure.MPane
+ Chiasma.Ui.Data.Measure: instance Prettyprinter.Internal.Pretty a => Prettyprinter.Internal.Pretty (Chiasma.Ui.Data.Measure.Measured a)
+ Chiasma.Ui.Data.Measure: lMainPosition :: HasMLayout c_avMv => Lens' c_avMv Int
+ Chiasma.Ui.Data.Measure: lOffPosition :: HasMLayout c_avMv => Lens' c_avMv Int
+ Chiasma.Ui.Data.Measure: mLayout :: HasMLayout c_avMv => Lens' c_avMv MLayout
+ Chiasma.Ui.Data.Measure: mPane :: HasMPane c_avGZ => Lens' c_avGZ MPane
+ Chiasma.Ui.Data.Measure: mainPosition :: HasMPane c_avGZ => Lens' c_avGZ Int
+ Chiasma.Ui.Data.Measure: measured :: HasMeasured c_avSQ a_avN4 => Lens' c_avSQ (Measured a_avN4)
+ Chiasma.Ui.Data.Measure: offPosition :: HasMPane c_avGZ => Lens' c_avGZ Int
+ Chiasma.Ui.Data.Measure: paneId :: HasMPane c_avGZ => Lens' c_avGZ PaneId
+ Chiasma.Ui.Data.Measure: reference :: HasMLayout c_avMv => Lens' c_avMv PaneId
+ Chiasma.Ui.Data.Measure: size :: HasMeasured c_avSQ a_avN4 => Lens' c_avSQ Int
+ Chiasma.Ui.Data.Measure: type MeasureTree = NTree (Measured MLayout) (Measured MPane)
+ Chiasma.Ui.Data.Measure: type MeasureTreeSub = NNode (Measured MLayout) (Measured MPane)
+ Chiasma.Ui.Data.Measure: vertical :: HasMLayout c_avMv => Lens' c_avMv Bool
+ Chiasma.Ui.Data.Measure: view :: HasMeasured c_avSQ a_avN4 => Lens' c_avSQ a_avN4
+ Chiasma.Ui.Data.RenderableTree: RLayout :: RPane -> Bool -> RLayout
+ Chiasma.Ui.Data.RenderableTree: RPane :: PaneId -> Int -> Int -> RPane
+ Chiasma.Ui.Data.RenderableTree: Renderable :: ViewState -> ViewGeometry -> a -> Renderable a
+ Chiasma.Ui.Data.RenderableTree: [$sel:_geometry:Renderable] :: Renderable a -> ViewGeometry
+ Chiasma.Ui.Data.RenderableTree: [$sel:_id:RPane] :: RPane -> PaneId
+ Chiasma.Ui.Data.RenderableTree: [$sel:_left:RPane] :: RPane -> Int
+ Chiasma.Ui.Data.RenderableTree: [$sel:_ref:RLayout] :: RLayout -> RPane
+ Chiasma.Ui.Data.RenderableTree: [$sel:_state:Renderable] :: Renderable a -> ViewState
+ Chiasma.Ui.Data.RenderableTree: [$sel:_top:RPane] :: RPane -> Int
+ Chiasma.Ui.Data.RenderableTree: [$sel:_vertical:RLayout] :: RLayout -> Bool
+ Chiasma.Ui.Data.RenderableTree: [$sel:_view:Renderable] :: Renderable a -> a
+ Chiasma.Ui.Data.RenderableTree: data RLayout
+ Chiasma.Ui.Data.RenderableTree: data RPane
+ Chiasma.Ui.Data.RenderableTree: data Renderable a
+ Chiasma.Ui.Data.RenderableTree: instance GHC.Classes.Eq Chiasma.Ui.Data.RenderableTree.RLayout
+ Chiasma.Ui.Data.RenderableTree: instance GHC.Classes.Eq Chiasma.Ui.Data.RenderableTree.RPane
+ Chiasma.Ui.Data.RenderableTree: instance GHC.Classes.Eq a => GHC.Classes.Eq (Chiasma.Ui.Data.RenderableTree.Renderable a)
+ Chiasma.Ui.Data.RenderableTree: instance GHC.Show.Show Chiasma.Ui.Data.RenderableTree.RLayout
+ Chiasma.Ui.Data.RenderableTree: instance GHC.Show.Show Chiasma.Ui.Data.RenderableTree.RPane
+ Chiasma.Ui.Data.RenderableTree: instance GHC.Show.Show a => GHC.Show.Show (Chiasma.Ui.Data.RenderableTree.Renderable a)
+ Chiasma.Ui.Data.RenderableTree: instance Prettyprinter.Internal.Pretty Chiasma.Ui.Data.RenderableTree.RLayout
+ Chiasma.Ui.Data.RenderableTree: instance Prettyprinter.Internal.Pretty Chiasma.Ui.Data.RenderableTree.RPane
+ Chiasma.Ui.Data.RenderableTree: instance Prettyprinter.Internal.Pretty a => Prettyprinter.Internal.Pretty (Chiasma.Ui.Data.RenderableTree.Renderable a)
+ Chiasma.Ui.Data.RenderableTree: mayPretty :: Text -> Maybe Float -> Doc a
+ Chiasma.Ui.Data.RenderableTree: type RenderableLayout = Renderable RLayout
+ Chiasma.Ui.Data.RenderableTree: type RenderableNode = NNode RenderableLayout RenderablePane
+ Chiasma.Ui.Data.RenderableTree: type RenderablePane = Renderable RPane
+ Chiasma.Ui.Data.RenderableTree: type RenderableTree = NTree RenderableLayout RenderablePane
+ Chiasma.Ui.Data.Tree: Leaf :: p -> Node f l p
+ Chiasma.Ui.Data.Tree: Sub :: Tree f l p -> Node f l p
+ Chiasma.Ui.Data.Tree: Tree :: l -> f (Node f l p) -> Tree f l p
+ Chiasma.Ui.Data.Tree: [$sel:_forest:Tree] :: Tree f l p -> f (Node f l p)
+ Chiasma.Ui.Data.Tree: [$sel:_leafData:Sub] :: Node f l p -> p
+ Chiasma.Ui.Data.Tree: [$sel:_subTree:Sub] :: Node f l p -> Tree f l p
+ Chiasma.Ui.Data.Tree: [$sel:_treeData:Tree] :: Tree f l p -> l
+ Chiasma.Ui.Data.Tree: class HasNode c_anrU f_anj0 l_anj1 p_anj2 | c_anrU -> f_anj0 l_anj1 p_anj2
+ Chiasma.Ui.Data.Tree: class HasTree c_anoa f_anj3 l_anj4 p_anj5 | c_anoa -> f_anj3 l_anj4 p_anj5
+ Chiasma.Ui.Data.Tree: data Node f l p
+ Chiasma.Ui.Data.Tree: data Tree f l p
+ Chiasma.Ui.Data.Tree: forest :: HasTree c_anoa f_anj3 l_anj4 p_anj5 => Lens' c_anoa (f_anj3 (Node f_anj3 l_anj4 p_anj5))
+ Chiasma.Ui.Data.Tree: instance (Data.Foldable.Foldable f, Prettyprinter.Internal.Pretty l, Prettyprinter.Internal.Pretty p) => Prettyprinter.Internal.Pretty (Chiasma.Ui.Data.Tree.Node f l p)
+ Chiasma.Ui.Data.Tree: instance (Data.Foldable.Foldable f, Prettyprinter.Internal.Pretty l, Prettyprinter.Internal.Pretty p) => Prettyprinter.Internal.Pretty (Chiasma.Ui.Data.Tree.Tree f l p)
+ Chiasma.Ui.Data.Tree: instance (GHC.Classes.Eq l, GHC.Classes.Eq p) => GHC.Classes.Eq (Chiasma.Ui.Data.Tree.Node GHC.Base.NonEmpty l p)
+ Chiasma.Ui.Data.Tree: instance (GHC.Classes.Eq l, GHC.Classes.Eq p) => GHC.Classes.Eq (Chiasma.Ui.Data.Tree.Node [] l p)
+ Chiasma.Ui.Data.Tree: instance (GHC.Classes.Eq l, GHC.Classes.Eq p) => GHC.Classes.Eq (Chiasma.Ui.Data.Tree.Tree GHC.Base.NonEmpty l p)
+ Chiasma.Ui.Data.Tree: instance (GHC.Classes.Eq l, GHC.Classes.Eq p) => GHC.Classes.Eq (Chiasma.Ui.Data.Tree.Tree [] l p)
+ Chiasma.Ui.Data.Tree: instance (GHC.Show.Show l, GHC.Show.Show p) => GHC.Show.Show (Chiasma.Ui.Data.Tree.Node GHC.Base.NonEmpty l p)
+ Chiasma.Ui.Data.Tree: instance (GHC.Show.Show l, GHC.Show.Show p) => GHC.Show.Show (Chiasma.Ui.Data.Tree.Node [] l p)
+ Chiasma.Ui.Data.Tree: instance (GHC.Show.Show l, GHC.Show.Show p) => GHC.Show.Show (Chiasma.Ui.Data.Tree.Tree GHC.Base.NonEmpty l p)
+ Chiasma.Ui.Data.Tree: instance (GHC.Show.Show l, GHC.Show.Show p) => GHC.Show.Show (Chiasma.Ui.Data.Tree.Tree [] l p)
+ Chiasma.Ui.Data.Tree: instance Chiasma.Ui.Data.Tree.HasNode (Chiasma.Ui.Data.Tree.Node f l p) f l p
+ Chiasma.Ui.Data.Tree: instance Chiasma.Ui.Data.Tree.HasTree (Chiasma.Ui.Data.Tree.Tree f l p) f l p
+ Chiasma.Ui.Data.Tree: leafData :: HasNode c_anrU f_anj0 l_anj1 p_anj2 => Traversal' c_anrU p_anj2
+ Chiasma.Ui.Data.Tree: node :: HasNode c_anrU f_anj0 l_anj1 p_anj2 => Lens' c_anrU (Node f_anj0 l_anj1 p_anj2)
+ Chiasma.Ui.Data.Tree: subTree :: HasNode c_anrU f_anj0 l_anj1 p_anj2 => Traversal' c_anrU (Tree f_anj0 l_anj1 p_anj2)
+ Chiasma.Ui.Data.Tree: tree :: HasTree c_anoa f_anj3 l_anj4 p_anj5 => Lens' c_anoa (Tree f_anj3 l_anj4 p_anj5)
+ Chiasma.Ui.Data.Tree: treeData :: HasTree c_anoa f_anj3 l_anj4 p_anj5 => Lens' c_anoa l_anj4
+ Chiasma.Ui.Data.Tree: type LNode l p = Node [] l p
+ Chiasma.Ui.Data.Tree: type LTree l p = Tree [] l p
+ Chiasma.Ui.Data.Tree: type NNode l p = Node NonEmpty l p
+ Chiasma.Ui.Data.Tree: type NTree l p = Tree NonEmpty l p
+ Chiasma.Ui.Data.TreeModError: AmbiguousLayout :: Ident -> Int -> TreeModError
+ Chiasma.Ui.Data.TreeModError: AmbiguousPane :: Ident -> Int -> TreeModError
+ Chiasma.Ui.Data.TreeModError: LayoutExists :: LayoutView -> TreeModError
+ Chiasma.Ui.Data.TreeModError: LayoutMissing :: Ident -> TreeModError
+ Chiasma.Ui.Data.TreeModError: NoTrees :: TreeModError
+ Chiasma.Ui.Data.TreeModError: PaneExists :: PaneView -> TreeModError
+ Chiasma.Ui.Data.TreeModError: PaneMissing :: Ident -> TreeModError
+ Chiasma.Ui.Data.TreeModError: _AmbiguousLayout :: AsTreeModError r_aL47 => Prism' r_aL47 (Ident, Int)
+ Chiasma.Ui.Data.TreeModError: _AmbiguousPane :: AsTreeModError r_aL47 => Prism' r_aL47 (Ident, Int)
+ Chiasma.Ui.Data.TreeModError: _LayoutExists :: AsTreeModError r_aL47 => Prism' r_aL47 LayoutView
+ Chiasma.Ui.Data.TreeModError: _LayoutMissing :: AsTreeModError r_aL47 => Prism' r_aL47 Ident
+ Chiasma.Ui.Data.TreeModError: _NoTrees :: AsTreeModError r_aL47 => Prism' r_aL47 ()
+ Chiasma.Ui.Data.TreeModError: _PaneExists :: AsTreeModError r_aL47 => Prism' r_aL47 PaneView
+ Chiasma.Ui.Data.TreeModError: _PaneMissing :: AsTreeModError r_aL47 => Prism' r_aL47 Ident
+ Chiasma.Ui.Data.TreeModError: _TreeModError :: AsTreeModError r_aL47 => Prism' r_aL47 TreeModError
+ Chiasma.Ui.Data.TreeModError: class AsTreeModError r_aL47
+ Chiasma.Ui.Data.TreeModError: data TreeModError
+ Chiasma.Ui.Data.TreeModError: instance Chiasma.Ui.Data.TreeModError.AsTreeModError Chiasma.Ui.Data.TreeModError.TreeModError
+ Chiasma.Ui.Data.TreeModError: instance Data.DeepPrisms.DeepPrisms Chiasma.Ui.Data.TreeModError.TreeModError Chiasma.Ui.Data.TreeModError.TreeModError
+ Chiasma.Ui.Data.TreeModError: instance GHC.Classes.Eq Chiasma.Ui.Data.TreeModError.TreeModError
+ Chiasma.Ui.Data.TreeModError: instance GHC.Show.Show Chiasma.Ui.Data.TreeModError.TreeModError
+ Chiasma.Ui.Data.View: Layout :: Bool -> Layout
+ Chiasma.Ui.Data.View: Pane :: Bool -> Bool -> Maybe FilePath -> Pane
+ Chiasma.Ui.Data.View: Tree :: l -> [TreeSub l p] -> Tree l p
+ Chiasma.Ui.Data.View: TreeLeaf :: p -> TreeSub l p
+ Chiasma.Ui.Data.View: TreeNode :: Tree l p -> TreeSub l p
+ Chiasma.Ui.Data.View: View :: Ident -> ViewState -> ViewGeometry -> a -> View a
+ Chiasma.Ui.Data.View: [$sel:_cwd:Pane] :: Pane -> Maybe FilePath
+ Chiasma.Ui.Data.View: [$sel:_extra:View] :: View a -> a
+ Chiasma.Ui.Data.View: [$sel:_geometry:View] :: View a -> ViewGeometry
+ Chiasma.Ui.Data.View: [$sel:_ident:View] :: View a -> Ident
+ Chiasma.Ui.Data.View: [$sel:_leafData:TreeNode] :: TreeSub l p -> p
+ Chiasma.Ui.Data.View: [$sel:_open:Pane] :: Pane -> Bool
+ Chiasma.Ui.Data.View: [$sel:_pin:Pane] :: Pane -> Bool
+ Chiasma.Ui.Data.View: [$sel:_state:View] :: View a -> ViewState
+ Chiasma.Ui.Data.View: [$sel:_subTree:TreeNode] :: TreeSub l p -> Tree l p
+ Chiasma.Ui.Data.View: [$sel:treeData:Tree] :: Tree l p -> l
+ Chiasma.Ui.Data.View: [$sel:treeSubs:Tree] :: Tree l p -> [TreeSub l p]
+ Chiasma.Ui.Data.View: [$sel:vertical:Layout] :: Layout -> Bool
+ Chiasma.Ui.Data.View: _treeData :: HasTree c_aEp4 l_aDPI p_aDPJ => Lens' c_aEp4 l_aDPI
+ Chiasma.Ui.Data.View: _treeSubs :: HasTree c_aEp4 l_aDPI p_aDPJ => Lens' c_aEp4 [TreeSub l_aDPI p_aDPJ]
+ Chiasma.Ui.Data.View: _vertical :: HasLayout c_aDkB => Lens' c_aDkB Bool
+ Chiasma.Ui.Data.View: class HasLayout c_aDkB
+ Chiasma.Ui.Data.View: class HasPane c_aDad
+ Chiasma.Ui.Data.View: class HasTree c_aEp4 l_aDPI p_aDPJ | c_aEp4 -> l_aDPI p_aDPJ
+ Chiasma.Ui.Data.View: class HasTreeSub c_aEsb l_aDPG p_aDPH | c_aEsb -> l_aDPG p_aDPH
+ Chiasma.Ui.Data.View: class HasView c_aDOV a_aDkM | c_aDOV -> a_aDkM
+ Chiasma.Ui.Data.View: consLayout :: Ident -> LayoutView
+ Chiasma.Ui.Data.View: consLayoutAs :: Bool -> Ident -> LayoutView
+ Chiasma.Ui.Data.View: consLayoutVertical :: Ident -> LayoutView
+ Chiasma.Ui.Data.View: consPane :: Ident -> PaneView
+ Chiasma.Ui.Data.View: cwd :: HasPane c_aDad => Lens' c_aDad (Maybe FilePath)
+ Chiasma.Ui.Data.View: data Pane
+ Chiasma.Ui.Data.View: data Tree l p
+ Chiasma.Ui.Data.View: data TreeSub l p
+ Chiasma.Ui.Data.View: data View a
+ Chiasma.Ui.Data.View: extra :: HasView c_aDOV a_aDkM => Lens' c_aDOV a_aDkM
+ Chiasma.Ui.Data.View: geometry :: HasView c_aDOV a_aDkM => Lens' c_aDOV ViewGeometry
+ Chiasma.Ui.Data.View: ident :: HasView c_aDOV a_aDkM => Lens' c_aDOV Ident
+ Chiasma.Ui.Data.View: instance (Data.Data.Data l, Data.Data.Data p) => Control.Lens.Plated.Plated (Chiasma.Ui.Data.View.Tree l p)
+ Chiasma.Ui.Data.View: instance (Data.Data.Data l, Data.Data.Data p) => Data.Data.Data (Chiasma.Ui.Data.View.Tree l p)
+ Chiasma.Ui.Data.View: instance (Data.Data.Data l, Data.Data.Data p) => Data.Data.Data (Chiasma.Ui.Data.View.TreeSub l p)
+ Chiasma.Ui.Data.View: instance (GHC.Classes.Eq l, GHC.Classes.Eq p) => GHC.Classes.Eq (Chiasma.Ui.Data.View.Tree l p)
+ Chiasma.Ui.Data.View: instance (GHC.Classes.Eq l, GHC.Classes.Eq p) => GHC.Classes.Eq (Chiasma.Ui.Data.View.TreeSub l p)
+ Chiasma.Ui.Data.View: instance (GHC.Show.Show l, GHC.Show.Show p) => GHC.Show.Show (Chiasma.Ui.Data.View.Tree l p)
+ Chiasma.Ui.Data.View: instance (GHC.Show.Show l, GHC.Show.Show p) => GHC.Show.Show (Chiasma.Ui.Data.View.TreeSub l p)
+ Chiasma.Ui.Data.View: instance (Prettyprinter.Internal.Pretty l, Prettyprinter.Internal.Pretty p) => Prettyprinter.Internal.Pretty (Chiasma.Ui.Data.View.Tree l p)
+ Chiasma.Ui.Data.View: instance (Prettyprinter.Internal.Pretty l, Prettyprinter.Internal.Pretty p) => Prettyprinter.Internal.Pretty (Chiasma.Ui.Data.View.TreeSub l p)
+ Chiasma.Ui.Data.View: instance Chiasma.Data.Ident.Identifiable (Chiasma.Ui.Data.View.View a)
+ Chiasma.Ui.Data.View: instance Chiasma.Data.Ident.Identifiable l => Chiasma.Data.Ident.Identifiable (Chiasma.Ui.Data.View.Tree l p)
+ Chiasma.Ui.Data.View: instance Chiasma.Data.Ident.Identifiable l => Control.Lens.At.Ixed (Chiasma.Ui.Data.View.Tree l p)
+ Chiasma.Ui.Data.View: instance Chiasma.Ui.Data.View.HasLayout Chiasma.Ui.Data.View.Layout
+ Chiasma.Ui.Data.View: instance Chiasma.Ui.Data.View.HasPane Chiasma.Ui.Data.View.Pane
+ Chiasma.Ui.Data.View: instance Chiasma.Ui.Data.View.HasTree (Chiasma.Ui.Data.View.Tree l p) l p
+ Chiasma.Ui.Data.View: instance Chiasma.Ui.Data.View.HasTreeSub (Chiasma.Ui.Data.View.TreeSub l p) l p
+ Chiasma.Ui.Data.View: instance Chiasma.Ui.Data.View.HasView (Chiasma.Ui.Data.View.View a) a
+ Chiasma.Ui.Data.View: instance Data.Bifoldable.Bifoldable Chiasma.Ui.Data.View.Tree
+ Chiasma.Ui.Data.View: instance Data.Bifoldable.Bifoldable Chiasma.Ui.Data.View.TreeSub
+ Chiasma.Ui.Data.View: instance Data.Bifunctor.Bifunctor Chiasma.Ui.Data.View.Tree
+ Chiasma.Ui.Data.View: instance Data.Bifunctor.Bifunctor Chiasma.Ui.Data.View.TreeSub
+ Chiasma.Ui.Data.View: instance Data.Data.Data Chiasma.Ui.Data.View.Layout
+ Chiasma.Ui.Data.View: instance Data.Data.Data Chiasma.Ui.Data.View.Pane
+ Chiasma.Ui.Data.View: instance Data.Data.Data a => Data.Data.Data (Chiasma.Ui.Data.View.View a)
+ Chiasma.Ui.Data.View: instance Data.Default.Class.Default Chiasma.Ui.Data.View.Layout
+ Chiasma.Ui.Data.View: instance Data.Default.Class.Default Chiasma.Ui.Data.View.Pane
+ Chiasma.Ui.Data.View: instance Data.Default.Class.Default a => Data.Default.Class.Default (Chiasma.Ui.Data.View.View a)
+ Chiasma.Ui.Data.View: instance GHC.Classes.Eq Chiasma.Ui.Data.View.Layout
+ Chiasma.Ui.Data.View: instance GHC.Classes.Eq Chiasma.Ui.Data.View.Pane
+ Chiasma.Ui.Data.View: instance GHC.Classes.Eq a => GHC.Classes.Eq (Chiasma.Ui.Data.View.View a)
+ Chiasma.Ui.Data.View: instance GHC.Generics.Generic (Chiasma.Ui.Data.View.Tree l p)
+ Chiasma.Ui.Data.View: instance GHC.Generics.Generic (Chiasma.Ui.Data.View.TreeSub l p)
+ Chiasma.Ui.Data.View: instance GHC.Generics.Generic (Chiasma.Ui.Data.View.View a)
+ Chiasma.Ui.Data.View: instance GHC.Generics.Generic Chiasma.Ui.Data.View.Layout
+ Chiasma.Ui.Data.View: instance GHC.Generics.Generic Chiasma.Ui.Data.View.Pane
+ Chiasma.Ui.Data.View: instance GHC.Show.Show Chiasma.Ui.Data.View.Layout
+ Chiasma.Ui.Data.View: instance GHC.Show.Show Chiasma.Ui.Data.View.Pane
+ Chiasma.Ui.Data.View: instance GHC.Show.Show a => GHC.Show.Show (Chiasma.Ui.Data.View.View a)
+ Chiasma.Ui.Data.View: instance Prettyprinter.Internal.Pretty (Chiasma.Ui.Data.View.View Chiasma.Ui.Data.View.Layout)
+ Chiasma.Ui.Data.View: instance Prettyprinter.Internal.Pretty (Chiasma.Ui.Data.View.View Chiasma.Ui.Data.View.Pane)
+ Chiasma.Ui.Data.View: instance Prettyprinter.Internal.Pretty Chiasma.Ui.Data.View.Layout
+ Chiasma.Ui.Data.View: instance Prettyprinter.Internal.Pretty Chiasma.Ui.Data.View.Pane
+ Chiasma.Ui.Data.View: layout :: HasLayout c_aDkB => Lens' c_aDkB Layout
+ Chiasma.Ui.Data.View: leafData :: HasTreeSub c_aEsb l_aDPG p_aDPH => Traversal' c_aEsb p_aDPH
+ Chiasma.Ui.Data.View: newtype Layout
+ Chiasma.Ui.Data.View: open :: HasPane c_aDad => Lens' c_aDad Bool
+ Chiasma.Ui.Data.View: pane :: HasPane c_aDad => Lens' c_aDad Pane
+ Chiasma.Ui.Data.View: pin :: HasPane c_aDad => Lens' c_aDad Bool
+ Chiasma.Ui.Data.View: prettyView :: Doc a -> Ident -> ViewState -> ViewGeometry -> Doc a
+ Chiasma.Ui.Data.View: state :: HasView c_aDOV a_aDkM => Lens' c_aDOV ViewState
+ Chiasma.Ui.Data.View: subTree :: HasTreeSub c_aEsb l_aDPG p_aDPH => Traversal' c_aEsb (Tree l_aDPG p_aDPH)
+ Chiasma.Ui.Data.View: tree :: HasTree c_aEp4 l_aDPI p_aDPJ => Lens' c_aEp4 (Tree l_aDPI p_aDPJ)
+ Chiasma.Ui.Data.View: treeSub :: HasTreeSub c_aEsb l_aDPG p_aDPH => Lens' c_aEsb (TreeSub l_aDPG p_aDPH)
+ Chiasma.Ui.Data.View: type LayoutView = View Layout
+ Chiasma.Ui.Data.View: type PaneView = View Pane
+ Chiasma.Ui.Data.View: type ViewTree = Tree LayoutView PaneView
+ Chiasma.Ui.Data.View: type ViewTreeSub = TreeSub LayoutView PaneView
+ Chiasma.Ui.Data.View: view :: HasView c_aDOV a_aDkM => Lens' c_aDOV (View a_aDkM)
+ Chiasma.Ui.Data.ViewGeometry: ViewGeometry :: Maybe Float -> Maybe Float -> Maybe Float -> Maybe Float -> Maybe Float -> Maybe Float -> ViewGeometry
+ Chiasma.Ui.Data.ViewGeometry: [$sel:fixedSize:ViewGeometry] :: ViewGeometry -> Maybe Float
+ Chiasma.Ui.Data.ViewGeometry: [$sel:maxSize:ViewGeometry] :: ViewGeometry -> Maybe Float
+ Chiasma.Ui.Data.ViewGeometry: [$sel:minSize:ViewGeometry] :: ViewGeometry -> Maybe Float
+ Chiasma.Ui.Data.ViewGeometry: [$sel:minimizedSize:ViewGeometry] :: ViewGeometry -> Maybe Float
+ Chiasma.Ui.Data.ViewGeometry: [$sel:position:ViewGeometry] :: ViewGeometry -> Maybe Float
+ Chiasma.Ui.Data.ViewGeometry: [$sel:weight:ViewGeometry] :: ViewGeometry -> Maybe Float
+ Chiasma.Ui.Data.ViewGeometry: data ViewGeometry
+ Chiasma.Ui.Data.ViewGeometry: instance Data.Data.Data Chiasma.Ui.Data.ViewGeometry.ViewGeometry
+ Chiasma.Ui.Data.ViewGeometry: instance Data.Default.Class.Default Chiasma.Ui.Data.ViewGeometry.ViewGeometry
+ Chiasma.Ui.Data.ViewGeometry: instance GHC.Classes.Eq Chiasma.Ui.Data.ViewGeometry.ViewGeometry
+ Chiasma.Ui.Data.ViewGeometry: instance GHC.Generics.Generic Chiasma.Ui.Data.ViewGeometry.ViewGeometry
+ Chiasma.Ui.Data.ViewGeometry: instance GHC.Show.Show Chiasma.Ui.Data.ViewGeometry.ViewGeometry
+ Chiasma.Ui.Data.ViewGeometry: instance Prettyprinter.Internal.Pretty Chiasma.Ui.Data.ViewGeometry.ViewGeometry
+ Chiasma.Ui.Data.ViewGeometry: mayPretty :: Text -> Maybe Float -> Doc a
+ Chiasma.Ui.Data.ViewState: ViewState :: Bool -> ViewState
+ Chiasma.Ui.Data.ViewState: [$sel:minimized:ViewState] :: ViewState -> Bool
+ Chiasma.Ui.Data.ViewState: instance Data.Data.Data Chiasma.Ui.Data.ViewState.ViewState
+ Chiasma.Ui.Data.ViewState: instance Data.Default.Class.Default Chiasma.Ui.Data.ViewState.ViewState
+ Chiasma.Ui.Data.ViewState: instance GHC.Classes.Eq Chiasma.Ui.Data.ViewState.ViewState
+ Chiasma.Ui.Data.ViewState: instance GHC.Generics.Generic Chiasma.Ui.Data.ViewState.ViewState
+ Chiasma.Ui.Data.ViewState: instance GHC.Show.Show Chiasma.Ui.Data.ViewState.ViewState
+ Chiasma.Ui.Data.ViewState: newtype ViewState
+ Chiasma.Ui.Lens.Ident: matchIdent :: Identifiable a => Ident -> Traversal' a a
+ Chiasma.Ui.Lens.Ident: matchIdentL :: Identifiable a => Ident -> Traversal' [a] a
+ Chiasma.Ui.Lens.Ident: matchIdentP :: Identifiable a => Ident -> Prism' a a
+ Chiasma.Ui.Measure: actualMaxSizes :: NonEmpty (ViewState, ViewGeometry) -> NonEmpty (Maybe Float)
+ Chiasma.Ui.Measure: actualMinSizes :: NonEmpty (ViewState, ViewGeometry) -> NonEmpty Float
+ Chiasma.Ui.Measure: actualSize :: (ViewGeometry -> Maybe Float) -> ViewState -> ViewGeometry -> Maybe Float
+ Chiasma.Ui.Measure: effectiveFixedSize :: ViewState -> ViewGeometry -> Maybe Float
+ Chiasma.Ui.Measure: isMinimized :: ViewState -> ViewGeometry -> Bool
+ Chiasma.Ui.Measure: measureLayout :: RenderableTree -> Int -> Int -> Bool -> MeasureTree
+ Chiasma.Ui.Measure: measureLayoutViews :: Float -> NonEmpty RenderableNode -> NonEmpty Int
+ Chiasma.Ui.Measure: measureSub :: Int -> Int -> Bool -> RenderableNode -> Int -> MeasureTreeSub
+ Chiasma.Ui.Measure: measureTree :: RenderableTree -> Int -> Int -> MeasureTree
+ Chiasma.Ui.Measure: minimizedSizeOrDefault :: ViewGeometry -> Float
+ Chiasma.Ui.Measure: subMeasureData :: RenderableNode -> (ViewState, ViewGeometry)
+ Chiasma.Ui.Measure.Balance: Balance :: NonEmpty Float -> NonEmpty (Maybe Float) -> NonEmpty Float -> NonEmpty Bool -> Float -> Balance
+ Chiasma.Ui.Measure.Balance: [$sel:balanceMax:Balance] :: Balance -> NonEmpty (Maybe Float)
+ Chiasma.Ui.Measure.Balance: [$sel:balanceMin:Balance] :: Balance -> NonEmpty Float
+ Chiasma.Ui.Measure.Balance: [$sel:balanceMinimized:Balance] :: Balance -> NonEmpty Bool
+ Chiasma.Ui.Measure.Balance: [$sel:balanceTotal:Balance] :: Balance -> Float
+ Chiasma.Ui.Measure.Balance: [$sel:balanceWeights:Balance] :: Balance -> NonEmpty Float
+ Chiasma.Ui.Measure.Balance: balanceSizes :: NonEmpty Float -> NonEmpty (Maybe Float) -> NonEmpty Float -> NonEmpty Bool -> Float -> NonEmpty Int
+ Chiasma.Ui.Measure.Balance: cutSizes :: Balance -> NonEmpty Float
+ Chiasma.Ui.Measure.Balance: data Balance
+ Chiasma.Ui.Measure.Balance: distRest :: Balance -> Float -> NonEmpty Float -> NonEmpty Float -> NonEmpty Float
+ Chiasma.Ui.Measure.Balance: distributeOnAll :: Balance -> NonEmpty Float
+ Chiasma.Ui.Measure.Balance: distributeOnUnbounded :: Balance -> NonEmpty Float
+ Chiasma.Ui.Measure.Balance: distributeSizes :: Balance -> NonEmpty Float
+ Chiasma.Ui.Measure.Balance: ensureMinimum2 :: NonEmpty Float -> NonEmpty Float
+ Chiasma.Ui.Measure.Balance: hasUnbounded :: Balance -> Bool
+ Chiasma.Ui.Measure.Balance: rectifySizes :: NonEmpty Float -> NonEmpty Int
+ Chiasma.Ui.Measure.Balance: reverseWeights :: NonEmpty Float -> NonEmpty Float
+ Chiasma.Ui.Measure.Balance: roundSizes :: NonEmpty Float -> NonEmpty Int
+ Chiasma.Ui.Measure.Balance: saturate :: NonEmpty Float -> NonEmpty Float -> NonEmpty Float -> Float -> NonEmpty Float
+ Chiasma.Ui.Measure.Balance: trimWeights :: NonEmpty Bool -> NonEmpty Float -> NonEmpty Float
+ Chiasma.Ui.Measure.Balance: weightsWithoutMinimized :: Balance -> NonEmpty Float
+ Chiasma.Ui.Measure.Balance: zipWith3NE :: (a -> b -> c -> d) -> NonEmpty a -> NonEmpty b -> NonEmpty c -> NonEmpty d
+ Chiasma.Ui.Measure.Weights: amendAndNormalizeWeights :: NonEmpty (Maybe Float) -> NonEmpty Float
+ Chiasma.Ui.Measure.Weights: normalizeWeights :: NonEmpty Float -> NonEmpty Float
+ Chiasma.Ui.Measure.Weights: viewWeights :: NonEmpty (ViewState, ViewGeometry) -> NonEmpty Float
+ Chiasma.Ui.Pane: paneSetOpen :: PaneView -> PaneView
+ Chiasma.Ui.Pane: paneToggleOpen :: PaneView -> PaneView
+ Chiasma.Ui.ShowTree: formatLayout :: LayoutView -> Text
+ Chiasma.Ui.ShowTree: formatPane :: PaneView -> Text
+ Chiasma.Ui.ShowTree: formatViewTree :: ViewTree -> Tree Text Text
+ Chiasma.Ui.ShowTree: indent :: [Text] -> [Text]
+ Chiasma.Ui.ShowTree: printViewTree :: MonadIO m => ViewTree -> m ()
+ Chiasma.Ui.ShowTree: showTree :: Tree Text Text -> [Text]
+ Chiasma.Ui.ShowTree: showTreeSub :: TreeSub Text Text -> [Text]
+ Chiasma.Ui.ShowTree: showViewTree :: ViewTree -> [Text]
+ Chiasma.Ui.ViewTree: Ambiguous :: Int -> ToggleResult a
+ Chiasma.Ui.ViewTree: Consistent :: ToggleStatus
+ Chiasma.Ui.ViewTree: Minimized :: ToggleStatus
+ Chiasma.Ui.ViewTree: Multiple :: Int -> ToggleStatus
+ Chiasma.Ui.ViewTree: NotFound :: ToggleResult a
+ Chiasma.Ui.ViewTree: Opened :: ToggleStatus
+ Chiasma.Ui.ViewTree: Pristine :: ToggleStatus
+ Chiasma.Ui.ViewTree: Success :: a -> ToggleResult a
+ Chiasma.Ui.ViewTree: checkToggleResult :: ToggleStatus -> a -> ToggleResult a
+ Chiasma.Ui.ViewTree: data ToggleResult a
+ Chiasma.Ui.ViewTree: data ToggleStatus
+ Chiasma.Ui.ViewTree: depthTraverseTree :: forall a. Monoid a => (a -> ViewTree -> (a, ViewTree)) -> (PaneView -> (a, PaneView)) -> ViewTree -> (a, ViewTree)
+ Chiasma.Ui.ViewTree: ensurePaneOpen :: Ident -> ViewTree -> ToggleResult ViewTree
+ Chiasma.Ui.ViewTree: ensurePaneOpenTraversal :: Traversal a (ToggleResult a) ViewTree (ToggleResult ViewTree) -> Ident -> a -> ToggleResult a
+ Chiasma.Ui.ViewTree: ensurePaneOpenTraversal' :: Traversal' a ViewTree -> Ident -> a -> ToggleResult a
+ Chiasma.Ui.ViewTree: ensurePaneViewOpen :: Ident -> PaneView -> (ToggleStatus, PaneView)
+ Chiasma.Ui.ViewTree: hasOpenPanes :: ViewTree -> Bool
+ Chiasma.Ui.ViewTree: instance GHC.Base.Applicative Chiasma.Ui.ViewTree.ToggleResult
+ Chiasma.Ui.ViewTree: instance GHC.Base.Functor Chiasma.Ui.ViewTree.ToggleResult
+ Chiasma.Ui.ViewTree: instance GHC.Base.Monad Chiasma.Ui.ViewTree.ToggleResult
+ Chiasma.Ui.ViewTree: instance GHC.Base.Monoid (Chiasma.Ui.ViewTree.ToggleResult a)
+ Chiasma.Ui.ViewTree: instance GHC.Base.Monoid Chiasma.Ui.ViewTree.ToggleStatus
+ Chiasma.Ui.ViewTree: instance GHC.Base.Semigroup (Chiasma.Ui.ViewTree.ToggleResult a)
+ Chiasma.Ui.ViewTree: instance GHC.Base.Semigroup Chiasma.Ui.ViewTree.ToggleStatus
+ Chiasma.Ui.ViewTree: instance GHC.Classes.Eq Chiasma.Ui.ViewTree.ToggleStatus
+ Chiasma.Ui.ViewTree: instance GHC.Classes.Eq a => GHC.Classes.Eq (Chiasma.Ui.ViewTree.ToggleResult a)
+ Chiasma.Ui.ViewTree: instance GHC.Show.Show Chiasma.Ui.ViewTree.ToggleStatus
+ Chiasma.Ui.ViewTree: instance GHC.Show.Show a => GHC.Show.Show (Chiasma.Ui.ViewTree.ToggleResult a)
+ Chiasma.Ui.ViewTree: isOpenPaneNode :: ViewTreeSub -> Bool
+ Chiasma.Ui.ViewTree: modCounted :: Monad m => (a -> m a) -> a -> WriterT (Sum Int) m a
+ Chiasma.Ui.ViewTree: modifyPane :: (PaneView -> PaneView) -> Ident -> ViewTree -> Either TreeModError ViewTree
+ Chiasma.Ui.ViewTree: modifyPaneUniqueM :: Monad m => (PaneView -> m PaneView) -> Ident -> ViewTree -> ExceptT TreeModError m ViewTree
+ Chiasma.Ui.ViewTree: modifyTreeUniqueM :: Monad m => (ViewTree -> m ViewTree) -> Ident -> ViewTree -> ExceptT TreeModError m ViewTree
+ Chiasma.Ui.ViewTree: openFirstPaneNode :: ViewTreeSub -> (ToggleStatus, ViewTreeSub)
+ Chiasma.Ui.ViewTree: openFirstPinnedPaneNode :: ViewTreeSub -> (ToggleStatus, ViewTreeSub)
+ Chiasma.Ui.ViewTree: openPane :: Ident -> ViewTree -> Either TreeModError ViewTree
+ Chiasma.Ui.ViewTree: openPaneView :: PaneView -> (ToggleStatus, PaneView)
+ Chiasma.Ui.ViewTree: openPinnedPaneView :: PaneView -> (ToggleStatus, PaneView)
+ Chiasma.Ui.ViewTree: openPinnedSubs :: ToggleStatus -> ViewTree -> (ToggleStatus, ViewTree)
+ Chiasma.Ui.ViewTree: skipFold :: Traversable t => (a -> (ToggleStatus, a)) -> ToggleStatus -> t a -> (ToggleStatus, t a)
+ Chiasma.Ui.ViewTree: toggleLayout :: Ident -> ViewTree -> ToggleResult ViewTree
+ Chiasma.Ui.ViewTree: toggleLayout1 :: Ident -> ViewTree -> Either TreeModError ViewTree
+ Chiasma.Ui.ViewTree: toggleLayoutNode :: Ident -> ToggleStatus -> ViewTree -> (ToggleStatus, ViewTree)
+ Chiasma.Ui.ViewTree: toggleLayoutOpenTraversal' :: Traversal' a ViewTree -> Ident -> a -> ToggleResult a
+ Chiasma.Ui.ViewTree: togglePane :: Ident -> ViewTree -> ToggleResult ViewTree
+ Chiasma.Ui.ViewTree: togglePaneNode :: Ident -> ViewTreeSub -> (ToggleStatus, ViewTreeSub)
+ Chiasma.Ui.ViewTree: togglePaneOpenTraversal' :: Traversal' a ViewTree -> Ident -> a -> ToggleResult a
+ Chiasma.Ui.ViewTree: togglePaneView :: Ident -> PaneView -> (ToggleStatus, PaneView)
+ Chiasma.Ui.ViewTree: treeToggleOpen :: ViewTree -> ViewTree
+ Chiasma.View: addView :: MonadDeepState s Views m => Setter a -> Ident -> m (View a)
+ Chiasma.View: findOrCreateView :: MonadDeepState s Views m => Getter a -> Setter a -> Ident -> m (View a)
+ Chiasma.View: insertPane :: View PaneId -> Views -> Views
+ Chiasma.View: insertSession :: View SessionId -> Views -> Views
+ Chiasma.View: insertView :: Lens' Views [View a] -> View a -> Views -> Views
+ Chiasma.View: insertWindow :: View WindowId -> Views -> Views
+ Chiasma.View: pane :: Ident -> Views -> Either ViewsError (View PaneId)
+ Chiasma.View: paneById :: PaneId -> Views -> Maybe (View PaneId)
+ Chiasma.View: paneId :: Ident -> Views -> Either ViewsError PaneId
+ Chiasma.View: sameId :: Eq a => a -> View a -> Bool
+ Chiasma.View: session :: Ident -> Views -> Either ViewsError (View SessionId)
+ Chiasma.View: sessionById :: SessionId -> Views -> Maybe (View SessionId)
+ Chiasma.View: type Getter a = Ident -> Views -> Either ViewsError (View a)
+ Chiasma.View: type Setter a = View a -> Views -> Views
+ Chiasma.View: updatePane :: View PaneId -> Views -> Views
+ Chiasma.View: updateSession :: View SessionId -> Views -> Views
+ Chiasma.View: updateView :: Lens' Views [View a] -> (Ident -> ViewsError) -> View a -> Views -> Views
+ Chiasma.View: updateWindow :: View WindowId -> Views -> Views
+ Chiasma.View: view :: Lens' Views [View a] -> (Ident -> ViewsError) -> Ident -> Views -> Either ViewsError (View a)
+ Chiasma.View: viewById :: Eq a => Lens' Views [View a] -> a -> Views -> Maybe (View a)
+ Chiasma.View: viewsLog :: MonadDeepState s Views m => Doc AnsiStyle -> m ()
+ Chiasma.View: viewsLogS :: MonadDeepState s Views m => Text -> m ()
+ Chiasma.View: window :: Ident -> Views -> Either ViewsError (View WindowId)
+ Chiasma.View: windowById :: WindowId -> Views -> Maybe (View WindowId)
+ Chiasma.View.State: paneId :: (MonadDeepState s Views m, MonadDeepError e ViewsError m) => Ident -> m PaneId
+ Chiasma.Window: ensurePane :: (MonadDeepState s Views m, MonadFree TmuxThunk m) => FilePath -> WindowId -> PaneView -> m (Maybe RenderableNode)
+ Chiasma.Window: ensurePaneClosed :: (MonadDeepState s Views m, MonadFree TmuxThunk m) => Maybe PaneDetail -> m ()
+ Chiasma.Window: ensurePaneOpen :: (MonadDeepState s Views m, MonadFree TmuxThunk m) => FilePath -> Maybe PaneDetail -> WindowId -> m PaneDetail
+ Chiasma.Window: ensureView :: (MonadDeepState s Views m, MonadFree TmuxThunk m) => FilePath -> WindowId -> ViewTree -> m (Maybe RenderableTree)
+ Chiasma.Window: ensureWindow :: (MonadDeepState s Views m, MonadFree TmuxThunk m, MonadError RenderError m) => SessionId -> View WindowId -> Maybe WindowId -> ViewTree -> m Window
+ Chiasma.Window: findOrCreatePane :: MonadDeepState s Views m => Ident -> m (View PaneId)
+ Chiasma.Window: findOrCreateWindow :: MonadDeepState s Views m => Ident -> m (View WindowId)
+ Chiasma.Window: findPrincipal :: ViewTree -> Maybe PaneView
+ Chiasma.Window: findPrincipalSub :: ViewTreeSub -> Maybe PaneView
+ Chiasma.Window: nativePane :: MonadFree TmuxThunk m => WindowId -> View PaneId -> m (Maybe PaneDetail)
+ Chiasma.Window: openPane :: (MonadDeepState s Views m, MonadFree TmuxThunk m) => FilePath -> WindowId -> m PaneDetail
+ Chiasma.Window: principalPane :: (MonadDeepState s Views m, MonadError RenderError m) => ViewTree -> m (PaneView, View PaneId)
+ Chiasma.Window: refPane :: RenderableNode -> RPane
+ Chiasma.Window: registerWindowId :: MonadDeepState s Views m => Ident -> WindowId -> m ()
+ Chiasma.Window: renderableTree :: ViewState -> ViewGeometry -> Bool -> [RenderableNode] -> Maybe RenderableTree
+ Chiasma.Window: spawnWindow :: (MonadDeepState s Views m, MonadFree TmuxThunk m) => SessionId -> Ident -> m Window
+ Chiasma.Window: syncPrincipal :: (MonadDeepState s Views m, MonadFree TmuxThunk m, MonadError RenderError m) => WindowId -> ViewTree -> m ()
+ Chiasma.Window: viewPosition :: ViewTreeSub -> Float
+ Chiasma.Window: windowState :: (MonadDeepState s Views m, MonadFree TmuxThunk m) => Ident -> Window -> RenderableTree -> m WindowState
- Chiasma.Api.Class: class TmuxApi a
+ Chiasma.Api.Class: class TmuxApi m a
- Chiasma.Api.Class: runCommands :: (TmuxApi a, MonadIO m) => a -> ([String] -> Either TmuxDecodeError b) -> Cmds -> ExceptT TmuxError m [b]
+ Chiasma.Api.Class: runCommands :: TmuxApi m a => a -> (Text -> Either TmuxDecodeError b) -> Cmds -> m [b]
- Chiasma.Codec: TmuxQuery :: String -> TmuxQuery
+ Chiasma.Codec: TmuxQuery :: Text -> TmuxQuery
- Chiasma.Codec: decode :: (TmuxCodec a, Generic a, TmuxDataDecode (Rep a)) => [String] -> Either TmuxDecodeError a
+ Chiasma.Codec: decode :: (TmuxCodec a, Generic a, TmuxDataDecode (Rep a)) => Text -> Either TmuxDecodeError a
- Chiasma.Codec: query :: (TmuxCodec a, Generic a, TmuxDataQuery (Rep a)) => TmuxQuery
+ Chiasma.Codec: query :: (TmuxCodec a, TmuxDataQuery (Rep a)) => TmuxQuery
- Chiasma.Codec.Decode: IntParsingFailure :: String -> TmuxDecodeError
+ Chiasma.Codec.Decode: IntParsingFailure :: Text -> TmuxDecodeError
- Chiasma.Codec.Decode: ParseFailure :: String -> ParseError -> TmuxDecodeError
+ Chiasma.Codec.Decode: ParseFailure :: Text -> ParseError -> TmuxDecodeError
- Chiasma.Codec.Decode: TooManyFields :: [String] -> TmuxDecodeError
+ Chiasma.Codec.Decode: TooManyFields :: [Text] -> TmuxDecodeError
- Chiasma.Codec.Decode: decode' :: TmuxDataDecode f => [String] -> Either TmuxDecodeError ([String], f a)
+ Chiasma.Codec.Decode: decode' :: TmuxDataDecode f => [Text] -> Either TmuxDecodeError ([Text], f a)
- Chiasma.Codec.Decode: idParser :: Char -> GenParser Char st String
+ Chiasma.Codec.Decode: idParser :: Char -> GenParser Char st Text
- Chiasma.Codec.Decode: parseId :: (Int -> a) -> Char -> String -> Either TmuxDecodeError a
+ Chiasma.Codec.Decode: parseId :: (Int -> a) -> Char -> Text -> Either TmuxDecodeError a
- Chiasma.Codec.Decode: primDecode :: TmuxPrimDecode a => String -> Either TmuxDecodeError a
+ Chiasma.Codec.Decode: primDecode :: TmuxPrimDecode a => Text -> Either TmuxDecodeError a
- Chiasma.Codec.Decode: readInt :: String -> String -> Either TmuxDecodeError Int
+ Chiasma.Codec.Decode: readInt :: Text -> Text -> Either TmuxDecodeError Int
- Chiasma.Codec.Query: query' :: TmuxDataQuery f => [String]
+ Chiasma.Codec.Query: query' :: TmuxDataQuery f => [Text]
- Chiasma.Data.TmuxThunk: Read :: Cmd -> ([String] -> Either TmuxDecodeError a) -> ([a] -> next) -> TmuxThunk next
+ Chiasma.Data.TmuxThunk: Read :: Cmd -> (Text -> Either TmuxDecodeError a) -> ([a] -> next) -> TmuxThunk next
- Chiasma.Monad.Tmux: read :: forall a. TmuxCodec a => String -> [String] -> TmuxProg [a]
+ Chiasma.Monad.Tmux: read :: forall a m. (TmuxCodec a, MonadFree TmuxThunk m) => Text -> [Text] -> m [a]
- Chiasma.Monad.Tmux: write :: String -> [String] -> TmuxProg ()
+ Chiasma.Monad.Tmux: write :: MonadFree TmuxThunk m => Text -> [Text] -> m ()
- Chiasma.Native.Api: TmuxNative :: FilePath -> TmuxNative
+ Chiasma.Native.Api: TmuxNative :: Maybe FilePath -> TmuxNative
- Chiasma.Native.Parse: resultLines :: String -> Either ParseError [[String]]
+ Chiasma.Native.Parse: resultLines :: Text -> Either ParseError [[Text]]
- Chiasma.Native.Parse: resultParser :: GenParser Char st [[String]]
+ Chiasma.Native.Parse: resultParser :: GenParser st [[Text]]
- Chiasma.Native.Process: nativeTmuxProcess :: MonadIO m => FilePath -> ([String] -> Either TmuxDecodeError a) -> Cmds -> m (Either TmuxError [a])
+ Chiasma.Native.Process: nativeTmuxProcess :: (MonadIO m, MonadDeepError e TmuxError m) => Maybe FilePath -> (Text -> Either TmuxDecodeError a) -> Cmds -> m [a]
- Chiasma.Native.Process: tmuxProcessConfig :: FilePath -> [String] -> ProcessConfig () () ()
+ Chiasma.Native.Process: tmuxProcessConfig :: Maybe FilePath -> [Text] -> ProcessConfig () () ()
- Chiasma.Test.File: fixture :: MonadIO m => String -> FilePath -> m FilePath
+ Chiasma.Test.File: fixture :: MonadIO m => Text -> FilePath -> m FilePath
- Chiasma.Test.File: tempDir :: MonadIO m => String -> FilePath -> m FilePath
+ Chiasma.Test.File: tempDir :: MonadIO m => Text -> FilePath -> m FilePath
- Chiasma.Test.File: tempDirIO :: String -> FilePath -> IO FilePath
+ Chiasma.Test.File: tempDirIO :: Text -> FilePath -> IO FilePath
- Chiasma.Test.Tmux: withTestTmux :: (TmuxNative -> IO a) -> FilePath -> IO a
+ Chiasma.Test.Tmux: withTestTmux :: TmuxTestConf -> (TmuxNative -> IO a) -> FilePath -> IO a
Files
- LICENSE +28/−24
- README.md +0/−3
- Setup.hs +0/−2
- chiasma.cabal +374/−44
- integration/Chiasma/Test/IndividualProcessTest.hs +42/−0
- integration/Chiasma/Test/ProcessTest.hs +42/−0
- integration/Chiasma/Test/RenderTest.hs +216/−0
- integration/Chiasma/Test/TmuxStreamTest.hs +44/−0
- integration/Chiasma/Test/Util.hs +19/−0
- integration/Main.hs +21/−0
- lib/Chiasma/Api/Class.hs +15/−11
- lib/Chiasma/Codec.hs +20/−15
- lib/Chiasma/Codec/Data.hs +9/−0
- lib/Chiasma/Codec/Data/Pane.hs +16/−0
- lib/Chiasma/Codec/Data/PaneCoords.hs +17/−0
- lib/Chiasma/Codec/Data/PaneDetail.hs +18/−0
- lib/Chiasma/Codec/Data/PaneMode.hs +15/−0
- lib/Chiasma/Codec/Data/PanePid.hs +15/−0
- lib/Chiasma/Codec/Data/Session.hs +11/−0
- lib/Chiasma/Codec/Data/Window.hs +12/−0
- lib/Chiasma/Codec/Decode.hs +53/−25
- lib/Chiasma/Codec/Query.hs +18/−20
- lib/Chiasma/Command/Pane.hs +173/−0
- lib/Chiasma/Command/Session.hs +33/−0
- lib/Chiasma/Command/Window.hs +53/−0
- lib/Chiasma/Control/IO/Unsafe.hs +6/−0
- lib/Chiasma/Data/Cmd.hs +26/−0
- lib/Chiasma/Data/Conduit.hs +10/−0
- lib/Chiasma/Data/Ident.hs +59/−0
- lib/Chiasma/Data/List.hs +16/−0
- lib/Chiasma/Data/Maybe.hs +17/−0
- lib/Chiasma/Data/Pane.hs +0/−23
- lib/Chiasma/Data/RenderError.hs +17/−0
- lib/Chiasma/Data/TmuxError.hs +39/−0
- lib/Chiasma/Data/TmuxId.hs +64/−0
- lib/Chiasma/Data/TmuxThunk.hs +6/−43
- lib/Chiasma/Data/View.hs +21/−0
- lib/Chiasma/Data/Views.hs +37/−0
- lib/Chiasma/Data/Window.hs +0/−23
- lib/Chiasma/Data/WindowState.hs +18/−0
- lib/Chiasma/Lens/Tree.hs +127/−0
- lib/Chiasma/Lens/Where.hs +10/−0
- lib/Chiasma/Monad/Buffered.hs +0/−29
- lib/Chiasma/Monad/EvalFreeT.hs +50/−0
- lib/Chiasma/Monad/IndividualProcess.hs +40/−0
- lib/Chiasma/Monad/Simple.hs +0/−38
- lib/Chiasma/Monad/Stream.hs +80/−0
- lib/Chiasma/Monad/Tmux.hs +41/−13
- lib/Chiasma/Native/Api.hs +61/−9
- lib/Chiasma/Native/Parse.hs +18/−26
- lib/Chiasma/Native/Process.hs +37/−25
- lib/Chiasma/Native/StreamParse.hs +65/−0
- lib/Chiasma/Pack.hs +109/−0
- lib/Chiasma/Pane.hs +14/−0
- lib/Chiasma/Prelude.hs +71/−0
- lib/Chiasma/Render.hs +41/−0
- lib/Chiasma/Session.hs +49/−0
- lib/Chiasma/Test/File.hs +5/−6
- lib/Chiasma/Test/Screenshot.hs +67/−0
- lib/Chiasma/Test/Tmux.hs +83/−33
- lib/Chiasma/Ui/Data/Measure.hs +52/−0
- lib/Chiasma/Ui/Data/RenderableTree.hs +54/−0
- lib/Chiasma/Ui/Data/Tree.hs +45/−0
- lib/Chiasma/Ui/Data/TreeModError.hs +22/−0
- lib/Chiasma/Ui/Data/View.hs +151/−0
- lib/Chiasma/Ui/Data/ViewGeometry.hs +27/−0
- lib/Chiasma/Ui/Data/ViewState.hs +12/−0
- lib/Chiasma/Ui/Lens/Ident.hs +23/−0
- lib/Chiasma/Ui/Measure.hs +76/−0
- lib/Chiasma/Ui/Measure/Balance.hs +157/−0
- lib/Chiasma/Ui/Measure/Weights.hs +38/−0
- lib/Chiasma/Ui/Pane.hs +17/−0
- lib/Chiasma/Ui/ShowTree.hs +41/−0
- lib/Chiasma/Ui/ViewTree.hs +314/−0
- lib/Chiasma/View.hs +103/−0
- lib/Chiasma/View/State.hs +17/−0
- lib/Chiasma/Window.hs +225/−0
- lib/Prelude.hs +5/−0
- readme.md +3/−0
- test/Chiasma/Test/CodecTest.hs +24/−0
- test/Chiasma/Test/LensTest.hs +102/−0
- test/Chiasma/Test/OutputParseTest.hs +29/−0
- test/Chiasma/Test/PinTest.hs +98/−0
- test/Chiasma/Test/StreamParseTest.hs +30/−0
- test/Chiasma/Test/Util.hs +14/−0
- test/Main.hs +24/−0
- test/u/BufferedSpec.hs +0/−45
- test/u/CodecSpec.hs +0/−27
- test/u/OutputParseSpec.hs +0/−30
- test/u/SimpleSpec.hs +0/−32
- test/u/SpecMain.hs +0/−12
LICENSE view
@@ -1,30 +1,34 @@-Copyright Torsten Schmits (c) 2018+Copyright (c) 2020 Torsten Schmits -All rights reserved.+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the+following conditions are met: -Redistribution and use in source and binary forms, with or without-modification, are permitted provided that the following conditions are met:+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following+ disclaimer.+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided with the distribution. - * Redistributions of source code must retain the above copyright- notice, this list of conditions and the following disclaimer.+Subject to the terms and conditions of this license, each copyright holder and contributor hereby grants to those+receiving rights under this license a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except+for failure to satisfy the conditions of this license) patent license to make, have made, use, offer to sell, sell,+import, and otherwise transfer this software, where such license applies only to those patent claims, already acquired+or hereafter acquired, licensable by such copyright holder or contributor that are necessarily infringed by: - * Redistributions in binary form must reproduce the above- copyright notice, this list of conditions and the following- disclaimer in the documentation and/or other materials provided- with the distribution.+ (a) their Contribution(s) (the licensed copyrights of copyright holders and non-copyrightable additions of+ contributors, in source or binary form) alone; or+ (b) combination of their Contribution(s) with the work of authorship to which such Contribution(s) was added by such+ copyright holder or contributor, if, at the time the Contribution is added, such addition causes such combination to+ be necessarily infringed. The patent license shall not apply to any other combinations which include the Contribution. - * Neither the name of Torsten Schmits nor the names of other- contributors may be used to endorse or promote products derived- from this software without specific prior written permission.+Except as expressly stated above, no rights or licenses from any copyright holder or contributor is granted under this+license, whether expressly, by implication, estoppel or otherwise. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+DISCLAIMER++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
− README.md
@@ -1,3 +0,0 @@-# Intro--**chiasma** is a tmux api client for Haskell.
− Setup.hs
@@ -1,2 +0,0 @@-import Distribution.Simple-main = defaultMain
chiasma.cabal view
@@ -1,26 +1,24 @@-cabal-version: 1.12+cabal-version: 2.2 --- This file has been generated from package.yaml by hpack version 0.31.1.+-- This file has been generated from package.yaml by hpack version 0.34.4. -- -- see: https://github.com/sol/hpack------ hash: 3809c3d5d4204b2ce3be054873e25b993f46159354efa61c45f34aa594ce9f29 name: chiasma-version: 0.1.0.0+version: 0.2.0.0 synopsis: tmux api-description: Please see the README on GitHub at <https://github.com/tek/chiasma-hs>+description: Please see the README on GitHub at <https://github.com/tek/chiasma> category: Terminal homepage: https://github.com/tek/chiasma-hs#readme bug-reports: https://github.com/tek/chiasma-hs/issues author: Torsten Schmits maintainer: tek@tryp.io-copyright: 2019 Torsten Schmits-license: MIT+copyright: 2021 Torsten Schmits+license: BSD-2-Clause-Patent license-file: LICENSE build-type: Simple extra-source-files:- README.md+ readme.md source-repository head type: git@@ -30,77 +28,409 @@ exposed-modules: Chiasma.Api.Class Chiasma.Codec+ Chiasma.Codec.Data+ Chiasma.Codec.Data.Pane+ Chiasma.Codec.Data.PaneCoords+ Chiasma.Codec.Data.PaneDetail+ Chiasma.Codec.Data.PaneMode+ Chiasma.Codec.Data.PanePid+ Chiasma.Codec.Data.Session+ Chiasma.Codec.Data.Window Chiasma.Codec.Decode Chiasma.Codec.Query- Chiasma.Data.Pane+ Chiasma.Command.Pane+ Chiasma.Command.Session+ Chiasma.Command.Window+ Chiasma.Control.IO.Unsafe+ Chiasma.Data.Cmd+ Chiasma.Data.Conduit+ Chiasma.Data.Ident+ Chiasma.Data.List+ Chiasma.Data.Maybe+ Chiasma.Data.RenderError+ Chiasma.Data.TmuxError+ Chiasma.Data.TmuxId Chiasma.Data.TmuxThunk- Chiasma.Data.Window- Chiasma.Monad.Buffered- Chiasma.Monad.Simple+ Chiasma.Data.View+ Chiasma.Data.Views+ Chiasma.Data.WindowState+ Chiasma.Lens.Tree+ Chiasma.Lens.Where+ Chiasma.Monad.EvalFreeT+ Chiasma.Monad.IndividualProcess+ Chiasma.Monad.Stream Chiasma.Monad.Tmux Chiasma.Native.Api Chiasma.Native.Parse Chiasma.Native.Process+ Chiasma.Native.StreamParse+ Chiasma.Pack+ Chiasma.Pane+ Chiasma.Prelude+ Chiasma.Render+ Chiasma.Session Chiasma.Test.File+ Chiasma.Test.Screenshot Chiasma.Test.Tmux+ Chiasma.Ui.Data.Measure+ Chiasma.Ui.Data.RenderableTree+ Chiasma.Ui.Data.Tree+ Chiasma.Ui.Data.TreeModError+ Chiasma.Ui.Data.View+ Chiasma.Ui.Data.ViewGeometry+ Chiasma.Ui.Data.ViewState+ Chiasma.Ui.Lens.Ident+ Chiasma.Ui.Measure+ Chiasma.Ui.Measure.Balance+ Chiasma.Ui.Measure.Weights+ Chiasma.Ui.Pane+ Chiasma.Ui.ShowTree+ Chiasma.Ui.ViewTree+ Chiasma.View+ Chiasma.View.State+ Chiasma.Window other-modules:+ Prelude Paths_chiasma+ autogen-modules:+ Paths_chiasma hs-source-dirs: lib- default-extensions: ExistentialQuantification UnicodeSyntax TypeApplications ScopedTypeVariables DeriveGeneric DeriveAnyClass+ default-extensions:+ AllowAmbiguousTypes+ ApplicativeDo+ BangPatterns+ BinaryLiterals+ BlockArguments+ ConstraintKinds+ DataKinds+ DefaultSignatures+ DeriveAnyClass+ DeriveDataTypeable+ DeriveFoldable+ DeriveFunctor+ DeriveGeneric+ DeriveTraversable+ DerivingStrategies+ DisambiguateRecordFields+ DoAndIfThenElse+ DuplicateRecordFields+ EmptyDataDecls+ ExistentialQuantification+ FlexibleContexts+ FlexibleInstances+ FunctionalDependencies+ GADTs+ GeneralizedNewtypeDeriving+ InstanceSigs+ KindSignatures+ LambdaCase+ LiberalTypeSynonyms+ MultiParamTypeClasses+ MultiWayIf+ NamedFieldPuns+ OverloadedStrings+ OverloadedLists+ PackageImports+ PartialTypeSignatures+ PatternGuards+ PatternSynonyms+ PolyKinds+ QuantifiedConstraints+ QuasiQuotes+ RankNTypes+ RecordWildCards+ RecursiveDo+ ScopedTypeVariables+ StandaloneDeriving+ TemplateHaskell+ TupleSections+ TypeApplications+ TypeFamilies+ TypeFamilyDependencies+ TypeOperators+ TypeSynonymInstances+ UndecidableInstances+ UnicodeSyntax+ ViewPatterns build-depends:- base >=4.7 && <5+ aeson >=1.4 && <1.6+ , attoparsec ==0.13.*+ , base ==4.* , bytestring- , data-default-class+ , composition ==1.0.*+ , composition-extra ==2.0.*+ , conduit ==1.3.*+ , conduit-extra ==1.3.*+ , containers+ , cornea ==0.4.*+ , data-default ==0.7.*+ , deepseq , directory- , either+ , either >=5.0.1 && <5.1+ , exceptions , filepath- , free- , lens+ , free ==5.1.*+ , lens ==4.* , mtl , parsec- , posix-pty- , process- , resourcet- , split+ , parsers ==0.12.*+ , posix-pty ==0.2.*+ , prettyprinter >=1.6 && <1.8+ , prettyprinter-ansi-terminal ==1.1.*+ , process ==1.6.*+ , random ==1.1.*+ , relude >=0.7 && <1.2+ , resourcet ==1.2.*+ , split ==0.2.*+ , stm-chans ==3.0.*+ , stm-conduit ==4.0.*+ , text , transformers- , typed-process+ , typed-process ==0.2.* , unix- , unliftio+ , unliftio ==0.2.*+ , unliftio-core >=0.1 && <0.3+ , uuid ==1.3.*+ mixins:+ base hiding (Prelude) default-language: Haskell2010 +test-suite chiasma-integration+ type: exitcode-stdio-1.0+ main-is: Main.hs+ other-modules:+ Chiasma.Test.IndividualProcessTest+ Chiasma.Test.ProcessTest+ Chiasma.Test.RenderTest+ Chiasma.Test.TmuxStreamTest+ Chiasma.Test.Util+ Paths_chiasma+ hs-source-dirs:+ integration+ default-extensions:+ AllowAmbiguousTypes+ ApplicativeDo+ BangPatterns+ BinaryLiterals+ BlockArguments+ ConstraintKinds+ DataKinds+ DefaultSignatures+ DeriveAnyClass+ DeriveDataTypeable+ DeriveFoldable+ DeriveFunctor+ DeriveGeneric+ DeriveTraversable+ DerivingStrategies+ DisambiguateRecordFields+ DoAndIfThenElse+ DuplicateRecordFields+ EmptyDataDecls+ ExistentialQuantification+ FlexibleContexts+ FlexibleInstances+ FunctionalDependencies+ GADTs+ GeneralizedNewtypeDeriving+ InstanceSigs+ KindSignatures+ LambdaCase+ LiberalTypeSynonyms+ MultiParamTypeClasses+ MultiWayIf+ NamedFieldPuns+ OverloadedStrings+ OverloadedLists+ PackageImports+ PartialTypeSignatures+ PatternGuards+ PatternSynonyms+ PolyKinds+ QuantifiedConstraints+ QuasiQuotes+ RankNTypes+ RecordWildCards+ RecursiveDo+ ScopedTypeVariables+ StandaloneDeriving+ TemplateHaskell+ TupleSections+ TypeApplications+ TypeFamilies+ TypeFamilyDependencies+ TypeOperators+ TypeSynonymInstances+ UndecidableInstances+ UnicodeSyntax+ ViewPatterns+ ghc-options: -threaded -rtsopts -with-rtsopts=-N+ build-depends:+ aeson >=1.4 && <1.6+ , attoparsec ==0.13.*+ , base ==4.*+ , bytestring+ , chiasma+ , composition ==1.0.*+ , composition-extra ==2.0.*+ , conduit ==1.3.*+ , conduit-extra ==1.3.*+ , containers+ , cornea ==0.4.*+ , data-default ==0.7.*+ , deepseq+ , directory+ , either >=5.0.1 && <5.1+ , exceptions+ , filepath+ , free ==5.1.*+ , hedgehog+ , lens ==4.*+ , mtl+ , parsec+ , parsers ==0.12.*+ , posix-pty ==0.2.*+ , prettyprinter >=1.6 && <1.8+ , prettyprinter-ansi-terminal ==1.1.*+ , process ==1.6.*+ , random ==1.1.*+ , relude >=0.7 && <1.2+ , resourcet ==1.2.*+ , split ==0.2.*+ , stm-chans ==3.0.*+ , stm-conduit ==4.0.*+ , tasty+ , tasty-hedgehog+ , text+ , transformers+ , typed-process ==0.2.*+ , unix+ , unliftio ==0.2.*+ , unliftio-core >=0.1 && <0.3+ , uuid ==1.3.*+ mixins:+ base hiding (Prelude)+ , chiasma (Chiasma.Prelude as Prelude)+ , chiasma hiding (Chiasma.Prelude)+ default-language: Haskell2010+ test-suite chiasma-unit type: exitcode-stdio-1.0- main-is: SpecMain.hs+ main-is: Main.hs other-modules:- BufferedSpec- CodecSpec- OutputParseSpec- SimpleSpec+ Chiasma.Test.CodecTest+ Chiasma.Test.LensTest+ Chiasma.Test.OutputParseTest+ Chiasma.Test.PinTest+ Chiasma.Test.StreamParseTest+ Chiasma.Test.Util Paths_chiasma hs-source-dirs:- test/u- default-extensions: ExistentialQuantification UnicodeSyntax TypeApplications ScopedTypeVariables DeriveGeneric DeriveAnyClass+ test+ default-extensions:+ AllowAmbiguousTypes+ ApplicativeDo+ BangPatterns+ BinaryLiterals+ BlockArguments+ ConstraintKinds+ DataKinds+ DefaultSignatures+ DeriveAnyClass+ DeriveDataTypeable+ DeriveFoldable+ DeriveFunctor+ DeriveGeneric+ DeriveTraversable+ DerivingStrategies+ DisambiguateRecordFields+ DoAndIfThenElse+ DuplicateRecordFields+ EmptyDataDecls+ ExistentialQuantification+ FlexibleContexts+ FlexibleInstances+ FunctionalDependencies+ GADTs+ GeneralizedNewtypeDeriving+ InstanceSigs+ KindSignatures+ LambdaCase+ LiberalTypeSynonyms+ MultiParamTypeClasses+ MultiWayIf+ NamedFieldPuns+ OverloadedStrings+ OverloadedLists+ PackageImports+ PartialTypeSignatures+ PatternGuards+ PatternSynonyms+ PolyKinds+ QuantifiedConstraints+ QuasiQuotes+ RankNTypes+ RecordWildCards+ RecursiveDo+ ScopedTypeVariables+ StandaloneDeriving+ TemplateHaskell+ TupleSections+ TypeApplications+ TypeFamilies+ TypeFamilyDependencies+ TypeOperators+ TypeSynonymInstances+ UndecidableInstances+ UnicodeSyntax+ ViewPatterns ghc-options: -threaded -rtsopts -with-rtsopts=-N build-depends:- HTF- , base >=4.7 && <5+ aeson >=1.4 && <1.6+ , attoparsec ==0.13.*+ , base ==4.* , bytestring , chiasma- , data-default-class+ , composition ==1.0.*+ , composition-extra ==2.0.*+ , conduit ==1.3.*+ , conduit-extra ==1.3.*+ , containers+ , cornea ==0.4.*+ , data-default ==0.7.*+ , deepseq , directory- , either+ , either >=5.0.1 && <5.1+ , exceptions , filepath- , free- , lens+ , free ==5.1.*+ , hedgehog+ , lens ==4.* , mtl , parsec- , posix-pty- , process- , resourcet- , split+ , parsers ==0.12.*+ , posix-pty ==0.2.*+ , prettyprinter >=1.6 && <1.8+ , prettyprinter-ansi-terminal ==1.1.*+ , process ==1.6.*+ , random ==1.1.*+ , relude >=0.7 && <1.2+ , resourcet ==1.2.*+ , split ==0.2.*+ , stm-chans ==3.0.*+ , stm-conduit ==4.0.*+ , tasty+ , tasty-hedgehog+ , text , transformers- , typed-process+ , typed-process ==0.2.* , unix- , unliftio+ , unliftio ==0.2.*+ , unliftio-core >=0.1 && <0.3+ , uuid ==1.3.*+ mixins:+ base hiding (Prelude)+ , chiasma (Chiasma.Prelude as Prelude)+ , chiasma hiding (Chiasma.Prelude) default-language: Haskell2010
+ integration/Chiasma/Test/IndividualProcessTest.hs view
@@ -0,0 +1,42 @@+module Chiasma.Test.IndividualProcessTest where++import Chiasma.Codec.Data (Pane(Pane), Window(Window))+import Chiasma.Data.TmuxError (TmuxError)+import Chiasma.Data.TmuxId (PaneId(..), WindowId(..))+import Chiasma.Monad.IndividualProcess (TmuxProg, runTmux)+import qualified Chiasma.Monad.Tmux as Tmux (read, write)+import Chiasma.Native.Api (TmuxNative(..))+import Hedgehog ((===))++import Chiasma.Test.Tmux (tmuxSpec)+import Chiasma.Test.Util (UnitTest)++prog :: TmuxProg ([Pane], [Pane], [Window])+prog = do+ panes1 <- Tmux.read "list-panes" ["-t", "%0"]+ Tmux.write "new-window" []+ Tmux.write "new-window" []+ wins <- Tmux.read "list-windows" []+ panes <- Tmux.read "list-panes" ["-a"]+ return (panes1, panes, wins)++p :: Int -> Pane+p i = Pane (PaneId i) 240 60++w :: Int -> Window+w i = Window (WindowId i) 240 60++runProg :: TmuxNative -> IO (Either TmuxError ([Pane], [Pane], [Window]))+runProg api = runExceptT $ runTmux api prog++test_individual :: UnitTest+test_individual = do+ result :: Either TmuxError ([Pane], [Pane], [Window]) <- liftIO (tmuxSpec runProg)+ Right ([p0], [p0, p1, p2], [w0, w1, w2]) === result+ where+ p0 = p 0+ p1 = p 1+ p2 = p 2+ w0 = w 0+ w1 = w 1+ w2 = w 2
+ integration/Chiasma/Test/ProcessTest.hs view
@@ -0,0 +1,42 @@+module Chiasma.Test.ProcessTest where++import Chiasma.Data.Conduit (createSinkFlush)+import Chiasma.Native.Api (TmuxNative(..))+import Chiasma.Native.Process (socketArg)+import Conduit (ConduitT, Flush(..), mapC, runConduit, sinkList, yieldMany, (.|))+import Data.ByteString.Internal (packChars)+import qualified Data.Conduit.Combinators as Conduit (concatMap, take)+import Data.Conduit.Process.Typed (+ Process,+ createSource,+ getStdin,+ getStdout,+ proc,+ setStdin,+ setStdout,+ withProcessTerm,+ )+import qualified Data.Text as Text (splitOn)+import Hedgehog (assert)++import Chiasma.Test.Tmux (tmuxSpec)+import Chiasma.Test.Util (UnitTest)++run :: Process (ConduitT (Flush ByteString) Void IO ()) (ConduitT () ByteString IO ()) () -> IO [Text]+run prc = do+ let stdin' = mapC (fmap packChars) .| getStdin prc+ let stdout' = getStdout prc+ runConduit $ yieldMany ([Chunk "list-panes\n"] :: [Flush String]) .| stdin'+ runConduit $ yieldMany ([Flush] :: [Flush String]) .| stdin'+ runConduit $ stdout' .| Conduit.take 2 .| mapC decodeUtf8 .| Conduit.concatMap (Text.splitOn "\n") .| sinkList++test_process :: UnitTest+test_process = do+ out <- liftIO $ tmuxSpec $ \(TmuxNative sock) -> do+ withProcessTerm (pc (args sock)) run+ assert (length out > 3)+ where+ pc =+ setStdin createSinkFlush . setStdout createSource . proc "tmux"+ args sock =+ toString <$> socketArg sock ++ ["-C", "attach"]
+ integration/Chiasma/Test/RenderTest.hs view
@@ -0,0 +1,216 @@+module Chiasma.Test.RenderTest where++import Chiasma.Codec.Data.PaneDetail (PaneDetail(..))+import Chiasma.Command.Pane (panesAs)+import Chiasma.Command.Session (activateSession)+import Chiasma.Data.Ident (Ident(Str))+import Chiasma.Data.TmuxError (TmuxError)+import Chiasma.Data.TmuxId (PaneId(PaneId), SessionId(SessionId), WindowId(WindowId))+import Chiasma.Data.View (viewIdent)+import qualified Chiasma.Data.View as Tmux (View(View))+import Chiasma.Data.Views (Views(Views))+import Chiasma.Monad.Stream (runTmux)+import Chiasma.Native.Api (TmuxNative(..))+import Chiasma.Render (render)+import Chiasma.Ui.Data.View (Tree(..), TreeSub(..), ViewTree, consLayout, consLayoutVertical)+import qualified Chiasma.Ui.Data.View as Ui (Pane(Pane), View(View))+import Chiasma.Ui.Data.ViewGeometry (ViewGeometry(..))+import Chiasma.Ui.Data.ViewState (ViewState(ViewState))+import Chiasma.Ui.ViewTree (togglePane)+import qualified Chiasma.Ui.ViewTree as ToggleResult (ToggleResult(Success))+import Hedgehog (evalEither, (===))+import Test.Tasty (TestTree, testGroup)+import UnliftIO (throwString)+import UnliftIO.Directory (getCurrentDirectory)++import Chiasma.Test.Tmux (sleep, tmuxSpec)+import Chiasma.Test.Util (UnitTest, integrationTest)++id0, id1, id2, id3 :: Ident+id0 = Str "0"+id1 = Str "1"+id2 = Str "2"+id3 = Str "3"++views :: Views+views =+ Views+ [Tmux.View id0 (Just (SessionId 0))]+ [Tmux.View id0 (Just (WindowId 0))]+ [Tmux.View id0 (Just (PaneId 0))]+ []++renderOnce :: ViewTree -> TmuxNative -> FilePath -> Views -> IO Views+renderOnce tree api cwd vs = do+ r <- runExceptT $ runStateT (runTmux api $ render cwd id1 id1 tree) vs+ either (throwString . show) (return . snd) r++safeRender :: Views -> ViewTree -> TmuxNative -> IO Views+safeRender vs tree api = do+ cwd <- getCurrentDirectory+ vs1 <- renderOnce tree api cwd vs+ _ <- runExceptT @TmuxError $ runTmux api $ activateSession 0+ _ <- runExceptT @TmuxError $ runTmux api $ activateSession 1+ sleep 1+ renderOnce tree api cwd vs1++runRender :: ViewTree -> TmuxNative -> IO ([Tmux.View PaneId], Either TmuxError [PaneDetail])+runRender tree api = do+ (Views _ _ vs2 _) <- safeRender views tree api+ sleep 1+ ps <- runExceptT @TmuxError $ runTmux api panesAs+ return (sortOn viewIdent vs2, sortOn paneLeft . drop 1 <$> ps)++renderSpec :: ViewTree -> [PaneDetail] -> UnitTest+renderSpec tree target = do+ (_, pse) <- liftIO $ tmuxSpec $ runRender tree+ ps <- evalEither pse+ target === ps++treeImbalanced :: ViewTree+treeImbalanced =+ Tree (consLayout id0) [+ TreeLeaf (openPane id0 def),+ TreeLeaf (openPane id1 (ViewGeometry Nothing Nothing (Just 150) Nothing Nothing Nothing))+ ]+ where+ openPane i geo = Ui.View i (ViewState False) geo (Ui.Pane True False Nothing)++imbalancedTarget :: [PaneDetail]+imbalancedTarget =+ [+ PaneDetail { paneId = PaneId 1, paneWidth = 89, paneHeight = 60, paneTop = 0, paneLeft = 0 },+ PaneDetail { paneId = PaneId 2, paneWidth = 150, paneHeight = 60, paneTop = 0, paneLeft = 90 }+ ]++test_imbalanced :: UnitTest+test_imbalanced =+ renderSpec treeImbalanced imbalancedTarget++treeNested :: ViewTree+treeNested =+ Tree (consLayoutVertical id0) [+ TreeNode $+ Tree (consLayout id1) [+ TreeLeaf (openPane id0 def),+ TreeNode $+ Tree (consLayoutVertical id2) [+ TreeLeaf (openPane id1 def),+ TreeLeaf (openPane id2 def)+ ]+ ]+ ]+ where+ openPane i geo = Ui.View i (ViewState False) geo (Ui.Pane True False Nothing)++nestedTarget :: [PaneDetail]+nestedTarget =+ [+ PaneDetail { paneId = PaneId 1, paneWidth = 120, paneHeight = 60, paneTop = 0, paneLeft = 0 },+ PaneDetail { paneId = PaneId 2, paneWidth = 119, paneHeight = 30, paneTop = 0, paneLeft = 121 },+ PaneDetail { paneId = PaneId 3, paneWidth = 119, paneHeight = 29, paneTop = 31, paneLeft = 121 }+ ]++test_nested :: UnitTest+test_nested =+ renderSpec treeNested nestedTarget++treeTwoLayouts :: ViewTree+treeTwoLayouts =+ Tree (consLayout id0) [+ TreeNode $+ Tree (consLayoutVertical id1) [+ TreeLeaf (openPane id0 def)+ ],+ TreeNode $+ Tree (consLayoutVertical id2) [+ TreeLeaf (openPane id1 def)+ ]+ ]+ where+ openPane i geo = Ui.View i (ViewState False) geo (Ui.Pane True False Nothing)++twoLayoutsTarget :: [PaneDetail]+twoLayoutsTarget =+ [+ PaneDetail { paneId = PaneId 1, paneWidth = 120, paneHeight = 60, paneTop = 0, paneLeft = 0 },+ PaneDetail { paneId = PaneId 2, paneWidth = 119, paneHeight = 60, paneTop = 0, paneLeft = 121 }+ ]++test_twoLayouts :: UnitTest+test_twoLayouts =+ renderSpec treeTwoLayouts twoLayoutsTarget++treePosition :: ViewTree+treePosition =+ Tree (consLayout id0) [+ TreeLeaf (openPane id0 1 (Just 10)),+ TreeLeaf (openPane id1 4 (Just 20)),+ TreeLeaf (openPane id2 2 (Just 30)),+ TreeLeaf (openPane id3 3 Nothing)+ ]+ where+ openPane i pos size =+ Ui.View i (ViewState False) def { position = Just pos, fixedSize = size } (Ui.Pane True False Nothing)++positionTarget :: [PaneDetail]+positionTarget =+ [+ PaneDetail { paneId = PaneId 1, paneWidth = 10, paneHeight = 60, paneTop = 0, paneLeft = 0 },+ PaneDetail { paneId = PaneId 2, paneWidth = 30, paneHeight = 60, paneTop = 0, paneLeft = 11 },+ PaneDetail { paneId = PaneId 3, paneWidth = 177, paneHeight = 60, paneTop = 0, paneLeft = 42 },+ PaneDetail { paneId = PaneId 4, paneWidth = 20, paneHeight = 60, paneTop = 0, paneLeft = 220 }+ ]++test_position :: UnitTest+test_position =+ renderSpec treePosition positionTarget++treeSuccessiveOpen :: ViewTree+treeSuccessiveOpen =+ Tree (consLayout id0) [+ TreeNode $ Tree (consLayoutVertical id1) [+ TreeLeaf (pane id0 True False)+ ],+ TreeNode $ Tree (consLayoutVertical id2) [+ TreeLeaf (pane id1 False True),+ TreeLeaf (pane id2 False False)+ ]+ ]+ where+ pane i open pin =+ Ui.View i (ViewState False) def (Ui.Pane open pin Nothing)++successiveOpenTarget :: [PaneDetail]+successiveOpenTarget =+ [+ PaneDetail { paneId = PaneId 1, paneWidth = 120, paneHeight = 60, paneTop = 0, paneLeft = 0 },+ PaneDetail { paneId = PaneId 2, paneWidth = 119, paneHeight = 30, paneTop = 0, paneLeft = 121 },+ PaneDetail { paneId = PaneId 3, paneWidth = 119, paneHeight = 29, paneTop = 31, paneLeft = 121 }+ ]++test_successiveOpen :: UnitTest+test_successiveOpen = do+ ps <- liftIO $ tmuxSpec \ api -> do+ vs1 <- safeRender views treeSuccessiveOpen api+ sleep 0.2+ vs2 <- safeRender vs1 tree1 api+ sleep 0.2+ _ <- safeRender vs2 tree2 api+ sleep 0.2+ runExceptT @TmuxError $ runTmux api panesAs+ ps1 <- evalEither (sortOn paneId . drop 1 <$> ps)+ successiveOpenTarget === ps1+ where+ (ToggleResult.Success tree2) = togglePane id2 tree1+ (ToggleResult.Success tree1) = togglePane id1 treeSuccessiveOpen++test_render :: TestTree+test_render =+ testGroup "render" [+ integrationTest "imbalanced tree" test_imbalanced,+ integrationTest "nested panes" test_nested,+ integrationTest "two layouts" test_twoLayouts,+ integrationTest "fixed pane position" test_position,+ integrationTest "open multiple panes" test_successiveOpen+ ]
+ integration/Chiasma/Test/TmuxStreamTest.hs view
@@ -0,0 +1,44 @@+module Chiasma.Test.TmuxStreamTest where++import Chiasma.Codec.Data (Pane(Pane), Window(Window))+import Chiasma.Data.TmuxError (TmuxError)+import Chiasma.Data.TmuxId (PaneId(..), WindowId(..))+import Chiasma.Data.TmuxThunk (TmuxThunk)+import Chiasma.Monad.Stream (runTmux)+import qualified Chiasma.Monad.Tmux as Tmux (read, write)+import Chiasma.Native.Api (TmuxNative(..))+import Control.Monad.Free.Class (MonadFree)+import Hedgehog ((===))++import Chiasma.Test.Tmux (tmuxSpec)+import Chiasma.Test.Util (UnitTest)++prog :: MonadFree TmuxThunk m => m ([Pane], [Pane], [Window])+prog = do+ panes1 <- Tmux.read "list-panes" ["-t", "%0"]+ Tmux.write "new-window" []+ Tmux.write "new-window" []+ wins <- Tmux.read "list-windows" []+ panes <- Tmux.read "list-panes" ["-a"]+ return (panes1, panes, wins)++p :: Int -> Pane+p i = Pane (PaneId i) 240 60++w :: Int -> Window+w i = Window (WindowId i) 240 60++runProg :: TmuxNative -> IO (Either TmuxError ([Pane], [Pane], [Window]))+runProg api = runExceptT @TmuxError $ runTmux api prog++test_streamed :: UnitTest+test_streamed = do+ result <- liftIO (tmuxSpec runProg)+ (Right ([p0], [p0, p1, p2], [w0, w1, w2])) === result+ where+ p0 = p 0+ p1 = p 1+ p2 = p 2+ w0 = w 0+ w1 = w 1+ w2 = w 2
+ integration/Chiasma/Test/Util.hs view
@@ -0,0 +1,19 @@+module Chiasma.Test.Util where++import Hedgehog (TestT, withTests, property, test)+import Test.Tasty (TestName, TestTree)+import Test.Tasty.Hedgehog (testProperty)+import qualified System.Environment as Environment++type UnitTest = TestT IO ()++checkEnv :: UnitTest -> UnitTest+checkEnv t =+ maybe unit (const t) =<< liftIO (Environment.lookupEnv "DISPLAY")++integrationTest ::+ TestName ->+ UnitTest ->+ TestTree+integrationTest desc =+ testProperty desc . withTests 1 . property . test . checkEnv
+ integration/Main.hs view
@@ -0,0 +1,21 @@+module Main where++import Chiasma.Test.IndividualProcessTest (test_individual)+import Chiasma.Test.ProcessTest (test_process)+import Chiasma.Test.RenderTest (test_render)+import Chiasma.Test.TmuxStreamTest (test_streamed)+import Chiasma.Test.Util (integrationTest)+import Test.Tasty (TestTree, defaultMain, testGroup)++tests :: TestTree+tests =+ testGroup "all" [+ integrationTest "use individual subprocesses for queries" test_individual,+ integrationTest "tmux control process" test_process,+ test_render,+ integrationTest "streamed tmux commands" test_streamed+ ]++main :: IO ()+main =+ defaultMain tests
lib/Chiasma/Api/Class.hs view
@@ -1,15 +1,19 @@-module Chiasma.Api.Class(- TmuxApi(..),- DecodeTmuxResponse(..),-) where+module Chiasma.Api.Class where -import Control.Monad.IO.Class (MonadIO)-import Control.Monad.Trans.Except (ExceptT)+import Conduit (ConduitT, Flush)+ import Chiasma.Codec.Decode (TmuxDecodeError)-import Chiasma.Data.TmuxThunk (Cmds, TmuxError)+import Chiasma.Data.Cmd (Cmd, Cmds)+import Chiasma.Native.StreamParse (TmuxOutputBlock) -class TmuxApi a where- runCommands :: MonadIO m => a -> ([String] -> Either TmuxDecodeError b) -> Cmds -> ExceptT TmuxError m [b]+class TmuxApi m a where+ runCommands ::+ a ->+ (Text -> Either TmuxDecodeError b) ->+ Cmds ->+ m [b] -class DecodeTmuxResponse a where- decode :: String -> Either TmuxError a+ withTmux ::+ a ->+ (ConduitT (Flush Cmd) Void m () -> ConduitT () TmuxOutputBlock m () -> m b) ->+ m b
lib/Chiasma/Codec.hs view
@@ -1,32 +1,37 @@-{-# LANGUAGE DefaultSignatures #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE AllowAmbiguousTypes #-}+module Chiasma.Codec where -module Chiasma.Codec(- TmuxCodec(..),- TmuxQuery(..),-) where+import Chiasma.Data.TmuxId (PaneId, SessionId, WindowId)+import qualified Data.Text as Text (drop, dropEnd, splitOn, take, takeEnd, unwords)+import GHC.Generics (Rep, to) -import GHC.Generics (Generic, Rep, to) import Chiasma.Codec.Decode (TmuxDataDecode(..), TmuxDecodeError(TooManyFields)) import Chiasma.Codec.Query (TmuxDataQuery(..)) newtype TmuxQuery =- TmuxQuery { unQ :: String }+ TmuxQuery { unQ :: Text } deriving (Eq, Show) -genDecode :: (Generic a, TmuxDataDecode (Rep a)) => [String] -> Either TmuxDecodeError a+genDecode :: (Generic a, TmuxDataDecode (Rep a)) => Text -> Either TmuxDecodeError a genDecode fields = do- (rest, result) <- decode' fields+ (rest, result) <- decode' (Text.splitOn " " . trim $ fields) case rest of [] -> return $ to result a -> Left $ TooManyFields a+ where+ trim text =+ if Text.take 1 text == " " && Text.takeEnd 1 text == " "+ then Text.drop 1 . Text.dropEnd 1 $ text+ else text class TmuxCodec a where- decode :: [String] -> Either TmuxDecodeError a- default decode :: (Generic a, TmuxDataDecode (Rep a)) => [String] -> Either TmuxDecodeError a+ decode :: Text -> Either TmuxDecodeError a+ default decode :: (Generic a, TmuxDataDecode (Rep a)) => Text -> Either TmuxDecodeError a decode = genDecode query :: TmuxQuery- default query :: (Generic a, TmuxDataQuery (Rep a)) => TmuxQuery- query = TmuxQuery $ unwords $ query' @(Rep a)+ default query :: TmuxDataQuery (Rep a) => TmuxQuery+ query = TmuxQuery $ Text.unwords $ query' @(Rep a)++instance TmuxCodec SessionId+instance TmuxCodec WindowId+instance TmuxCodec PaneId
+ lib/Chiasma/Codec/Data.hs view
@@ -0,0 +1,9 @@+module Chiasma.Codec.Data(+ Session(..),+ Window(..),+ Pane(..),+) where++import Chiasma.Codec.Data.Pane (Pane(..))+import Chiasma.Codec.Data.Session (Session(..))+import Chiasma.Codec.Data.Window (Window(..))
+ lib/Chiasma/Codec/Data/Pane.hs view
@@ -0,0 +1,16 @@+module Chiasma.Codec.Data.Pane where++import Chiasma.Codec (TmuxCodec)+import Chiasma.Data.TmuxId (HasPaneId, PaneId)+import qualified Chiasma.Data.TmuxId as HasPaneId (HasPaneId(..))++data Pane =+ Pane {+ paneId :: PaneId,+ paneWidth :: Int,+ paneHeight :: Int+ }+ deriving (Eq, Show, Generic, TmuxCodec)++instance HasPaneId Pane where+ paneId = paneId
+ lib/Chiasma/Codec/Data/PaneCoords.hs view
@@ -0,0 +1,17 @@+module Chiasma.Codec.Data.PaneCoords where++import Chiasma.Data.TmuxId (HasPaneId, PaneId, SessionId, WindowId)+import qualified Chiasma.Data.TmuxId as HasPaneId (HasPaneId(..))++import Chiasma.Codec (TmuxCodec)++data PaneCoords =+ PaneCoords {+ sessionId :: SessionId,+ windowId :: WindowId,+ paneId :: PaneId+ }+ deriving (Eq, Show, Generic, TmuxCodec)++instance HasPaneId PaneCoords where+ paneId = paneId
+ lib/Chiasma/Codec/Data/PaneDetail.hs view
@@ -0,0 +1,18 @@+module Chiasma.Codec.Data.PaneDetail where++import Chiasma.Codec (TmuxCodec)+import Chiasma.Data.TmuxId (HasPaneId, PaneId)+import qualified Chiasma.Data.TmuxId as HasPaneId (HasPaneId(..))++data PaneDetail =+ PaneDetail {+ paneId :: PaneId,+ paneWidth :: Int,+ paneHeight :: Int,+ paneTop :: Int,+ paneLeft :: Int+ }+ deriving (Eq, Show, Generic, TmuxCodec)++instance HasPaneId PaneDetail where+ paneId = paneId
+ lib/Chiasma/Codec/Data/PaneMode.hs view
@@ -0,0 +1,15 @@+module Chiasma.Codec.Data.PaneMode where++import Chiasma.Codec (TmuxCodec)+import Chiasma.Data.TmuxId (HasPaneId, PaneId)+import qualified Chiasma.Data.TmuxId as HasPaneId (HasPaneId(paneId))++data PaneMode =+ PaneMode {+ paneId :: PaneId,+ paneMode :: Text+ }+ deriving (Eq, Show, Generic, TmuxCodec)++instance HasPaneId PaneMode where+ paneId = paneId
+ lib/Chiasma/Codec/Data/PanePid.hs view
@@ -0,0 +1,15 @@+module Chiasma.Codec.Data.PanePid where++import Chiasma.Codec (TmuxCodec)+import Chiasma.Data.TmuxId (HasPaneId, PaneId)+import qualified Chiasma.Data.TmuxId as HasPaneId (HasPaneId(paneId))++data PanePid =+ PanePid {+ paneId :: PaneId,+ panePid :: Int+ }+ deriving (Eq, Show, Generic, TmuxCodec)++instance HasPaneId PanePid where+ paneId = paneId
+ lib/Chiasma/Codec/Data/Session.hs view
@@ -0,0 +1,11 @@+module Chiasma.Codec.Data.Session where++import Chiasma.Codec (TmuxCodec)+import Chiasma.Data.TmuxId (SessionId)++-- must be data for now because of how derivation of `TmuxCodec` is implemented+data Session =+ Session {+ sessionId :: SessionId+ }+ deriving (Eq, Show, Generic, TmuxCodec)
+ lib/Chiasma/Codec/Data/Window.hs view
@@ -0,0 +1,12 @@+module Chiasma.Codec.Data.Window where++import Chiasma.Codec (TmuxCodec)+import Chiasma.Data.TmuxId (WindowId)++data Window =+ Window {+ windowId :: WindowId,+ windowWidth :: Int,+ windowHeight :: Int+ }+ deriving (Eq, Show, Generic, TmuxCodec)
lib/Chiasma/Codec/Decode.hs view
@@ -1,41 +1,38 @@-{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE TypeOperators #-} -module Chiasma.Codec.Decode(- TmuxDecodeError(..),- TmuxPrimDecode(..),- TmuxDataDecode(..),- idParser,- parseId,- readInt,-) where+module Chiasma.Codec.Decode where -import GHC.Generics ((:*:)(..), K1(..), M1(..))-import Data.Bifunctor (first, second)-import Text.Read (readEither)+import qualified Data.Text as Text (null, unpack)+import Data.Text.Read (decimal)+import GHC.Generics (K1(..), M1(..), (:*:)(..))+import Prelude hiding (many)+import Text.Parsec.Char (char, digit) import Text.ParserCombinators.Parsec ( GenParser, ParseError,- parse, many,+ parse, )-import Text.Parsec.Char (char, digit) +import Chiasma.Data.TmuxId (PaneId(..), SessionId(..), WindowId(..), panePrefix, sessionPrefix, windowPrefix)+ data TmuxDecodeError =- ParseFailure String ParseError+ ParseFailure Text ParseError |- IntParsingFailure String+ IntParsingFailure Text |+ BoolParsingFailure Text+ | TooFewFields |- TooManyFields [String]+ TooManyFields [Text] deriving (Eq, Show) class TmuxPrimDecode a where- primDecode :: String -> Either TmuxDecodeError a+ primDecode :: Text -> Either TmuxDecodeError a class TmuxDataDecode f where- decode' :: [String] -> Either TmuxDecodeError ([String], f a)+ decode' :: [Text] -> Either TmuxDecodeError ([Text], f a) instance (TmuxDataDecode f, TmuxDataDecode g) => TmuxDataDecode (f :*: g) where decode' fields = do@@ -53,18 +50,49 @@ return (as, K1 prim) decode' [] = Left TooFewFields -readInt :: String -> String -> Either TmuxDecodeError Int+readInt :: Text -> Text -> Either TmuxDecodeError Int readInt input num =- first (const $ IntParsingFailure input) $ readEither num+ first (const $ IntParsingFailure input) parsed+ where+ parsed = do+ (num', rest) <- decimal num+ if Text.null rest then Right num' else Left "" instance TmuxPrimDecode Int where primDecode field = readInt field field -idParser :: Char -> GenParser Char st String-idParser sym = char sym >> many digit+instance TmuxPrimDecode Bool where+ primDecode field =+ convert =<< readInt field field+ where+ convert 0 =+ Right False+ convert 1 =+ Right True+ convert _ =+ Left (BoolParsingFailure $ "got non-bool `" <> show field <> "`") -parseId :: (Int -> a) -> Char -> String -> Either TmuxDecodeError a+idParser :: Char -> GenParser Char st Text+idParser sym =+ char sym *> (toText <$> many digit)++parseId :: (Int -> a) -> Char -> Text -> Either TmuxDecodeError a parseId cons sym input = do- num <- first (ParseFailure "id") $ parse (idParser sym) "none" input+ num <- first (ParseFailure "id") $ parse (idParser sym) "none" (Text.unpack input) i <- readInt input num return $ cons i++instance TmuxPrimDecode SessionId where+ primDecode = parseId SessionId sessionPrefix++instance TmuxPrimDecode WindowId where+ primDecode = parseId WindowId windowPrefix++instance TmuxPrimDecode PaneId where+ primDecode = parseId PaneId panePrefix++instance TmuxPrimDecode [Char] where+ primDecode = Right . toString++instance TmuxPrimDecode Text where+ primDecode = Right
lib/Chiasma/Codec/Query.hs view
@@ -1,20 +1,14 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE PolyKinds #-}-{-# LANGUAGE TypeOperators #-} {-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE TypeOperators #-} -module Chiasma.Codec.Query(- TmuxDataQuery(..),-) where+module Chiasma.Codec.Query where -import GHC.Generics ((:*:), D1, C1, S1, Selector, selName)-import GHC.Unicode (isUpper, toLower)+import Data.Char (isUpper, toLower)+import qualified Data.Text as Text (concatMap, singleton)+import GHC.Generics (C1, D1, S1, Selector, selName, (:*:)) class TmuxDataQuery f where- query' :: [String]--instance (TmuxDataQuery f, TmuxDataQuery g) => TmuxDataQuery (f :*: g) where- query' = query' @f ++ query' @g+ query' :: [Text] instance TmuxDataQuery f => (TmuxDataQuery (D1 c f)) where query' = query' @f@@ -22,18 +16,22 @@ instance TmuxDataQuery f => (TmuxDataQuery (C1 c f)) where query' = query' @f -trans :: Char -> String-trans a | isUpper a = ['_', toLower a]-trans a = [a]+instance (TmuxDataQuery f, TmuxDataQuery g) => TmuxDataQuery (f :*: g) where+ query' = query' @f <> query' @g -snakeCase :: String -> String-snakeCase = (>>= trans)+trans :: Char -> Text+trans a | isUpper a = toText @String ['_', toLower a]+trans a = Text.singleton a -formatQuery :: String -> String-formatQuery q = "#{" ++ snakeCase q ++ "}"+snakeCase :: Text -> Text+snakeCase =+ Text.concatMap trans +formatQuery :: Text -> Text+formatQuery q = "#{" <> snakeCase q <> "}"+ instance Selector s => (TmuxDataQuery (S1 s f)) where query' =- [formatQuery query]+ [formatQuery (toText query)] where query = selName (undefined :: t s f p)
+ lib/Chiasma/Command/Pane.hs view
@@ -0,0 +1,173 @@+module Chiasma.Command.Pane where++import Data.List (dropWhileEnd)+import qualified Data.Text as Text (intercalate, singleton, splitOn)++import Chiasma.Codec (TmuxCodec)+import qualified Chiasma.Codec.Data as Codec (Pane)+import qualified Chiasma.Codec.Data.PaneCoords as Codec (PaneCoords)+import qualified Chiasma.Codec.Data.PaneMode as Codec (PaneMode(PaneMode))+import qualified Chiasma.Codec.Data.PanePid as Codec (PanePid)+import Chiasma.Data.TmuxId (HasPaneId, PaneId, WindowId, formatId)+import qualified Chiasma.Data.TmuxId as HasPaneId (paneId)+import Chiasma.Data.TmuxThunk (TmuxThunk)+import Chiasma.Data.View (View(View))+import qualified Chiasma.Monad.Tmux as Tmux (read, readRaw, unsafeReadFirst, write)+import Control.Monad.Free.Class (MonadFree)++paneTarget :: PaneId -> [Text]+paneTarget paneId =+ ["-t", formatId paneId]++sameId :: HasPaneId a => PaneId -> a -> Bool+sameId target candidate = target == HasPaneId.paneId candidate++panesAs :: (MonadFree TmuxThunk m, TmuxCodec a) => m [a]+panesAs =+ Tmux.read "list-panes" ["-a"]++panes :: MonadFree TmuxThunk m => m [Codec.Pane]+panes =+ panesAs++pane :: (MonadFree TmuxThunk m, TmuxCodec a, HasPaneId a) => PaneId -> m (Maybe a)+pane paneId =+ find (sameId paneId) <$> Tmux.read "list-panes" ["-t", formatId paneId]++windowPanesAs :: (MonadFree TmuxThunk m, TmuxCodec a) => WindowId -> m [a]+windowPanesAs windowId =+ Tmux.read "list-panes" ["-t", formatId windowId]++windowPanes :: MonadFree TmuxThunk m => WindowId -> m [Codec.Pane]+windowPanes =+ windowPanesAs++firstWindowPane :: MonadFree TmuxThunk m => WindowId -> m Codec.Pane+firstWindowPane windowId =+ Tmux.unsafeReadFirst "list-panes" ["-t", formatId windowId]++closePane :: MonadFree TmuxThunk m => PaneId -> m ()+closePane paneId =+ Tmux.write "kill-pane" (paneTarget paneId)++isPaneIdOpen ::+ MonadFree TmuxThunk m =>+ PaneId ->+ m Bool+isPaneIdOpen paneId =+ any (sameId paneId) <$> panes++isPaneOpen ::+ MonadFree TmuxThunk m =>+ View PaneId ->+ m Bool+isPaneOpen (View _ (Just paneId)) =+ isPaneIdOpen paneId+isPaneOpen _ = return False++movePane ::+ MonadFree TmuxThunk m =>+ PaneId ->+ PaneId ->+ Bool ->+ m ()+movePane paneId refId vertical =+ Tmux.write "move-pane" ["-d", "-s", formatId paneId, "-t", formatId refId, direction]+ where+ direction = if vertical then "-v" else "-h"++resizePane ::+ MonadFree TmuxThunk m =>+ PaneId ->+ Bool ->+ Int ->+ m ()+resizePane paneId vertical size =+ Tmux.write "resize-pane" ["-t", formatId paneId, direction, show size]+ where+ direction = if vertical then "-y" else "-x"++formatLine :: Text -> [Text]+formatLine line =+ ["\"" <> replace "\"" "\\\"" line <> Text.singleton '"', "enter"]+ where+ replace from to =+ Text.intercalate to . Text.splitOn from++sendKeys ::+ MonadFree TmuxThunk m =>+ PaneId ->+ [Text] ->+ m ()+sendKeys paneId lines' =+ traverse_ send formatted+ where+ formatted = lines' >>= formatLine+ send line = Tmux.write "send-keys" (paneTarget paneId <> [line])++pipePane ::+ MonadFree TmuxThunk m =>+ PaneId ->+ Text ->+ m ()+pipePane paneId cmd =+ Tmux.write "pipe-pane" (paneTarget paneId <> [cmd])++capturePane ::+ MonadFree TmuxThunk m =>+ PaneId ->+ m [Text]+capturePane paneId = do+ lines' <- Tmux.readRaw "capture-pane" (paneTarget paneId <> ["-p", "-e"])+ return $ dropWhileEnd ("" ==) lines'++panePid ::+ MonadFree TmuxThunk m =>+ PaneId ->+ m (Maybe Codec.PanePid)+panePid =+ pane++panePids ::+ MonadFree TmuxThunk m =>+ m [Codec.PanePid]+panePids =+ panesAs++paneCoords ::+ MonadFree TmuxThunk m =>+ PaneId ->+ m (Maybe Codec.PaneCoords)+paneCoords =+ pane++selectPane ::+ MonadFree TmuxThunk m =>+ PaneId ->+ m ()+selectPane paneId =+ Tmux.write "select-pane" (paneTarget paneId)++copyMode ::+ MonadFree TmuxThunk m =>+ PaneId ->+ m ()+copyMode =+ Tmux.write "copy-mode" . paneTarget++paneMode ::+ MonadFree TmuxThunk m =>+ PaneId ->+ m (Maybe Codec.PaneMode)+paneMode =+ pane++quitCopyMode ::+ MonadFree TmuxThunk m =>+ PaneId ->+ m ()+quitCopyMode paneId =+ traverse_ check =<< pane paneId+ where+ check (Codec.PaneMode _ mode) =+ when (mode == "copy-mode") (sendKeys paneId ["C-c"])
+ lib/Chiasma/Command/Session.hs view
@@ -0,0 +1,33 @@+module Chiasma.Command.Session where++import Control.Monad.Free.Class (MonadFree)++import Chiasma.Codec.Data (Session(Session))+import Chiasma.Data.Ident (Ident, identText)+import Chiasma.Data.TmuxId (SessionId)+import Chiasma.Data.TmuxThunk (TmuxThunk)+import qualified Chiasma.Monad.Tmux as Tmux (read, unsafeReadOne, write)++sameId :: SessionId -> Session -> Bool+sameId target (Session i) = target == i++sessions :: MonadFree TmuxThunk m => m [Session]+sessions =+ Tmux.read "list-sessions" []++doesSessionExist :: MonadFree TmuxThunk m => SessionId -> m Bool+doesSessionExist sessionId =+ any (sameId sessionId) <$> sessions++existingSessionId :: MonadFree TmuxThunk m => SessionId -> m (Maybe SessionId)+existingSessionId sessionId = do+ exists <- doesSessionExist sessionId+ return $ if exists then Just sessionId else Nothing++newSession :: MonadFree TmuxThunk m => Ident -> m Session+newSession name =+ Tmux.unsafeReadOne "new-session" ["-s", identText name, "-P"]++activateSession :: MonadFree TmuxThunk m => Int -> m ()+activateSession sessionId =+ Tmux.write "send-keys" ["-t", "%1", "'tmux switch-client -t \\$" <> show sessionId <> "'", "enter"]
+ lib/Chiasma/Command/Window.hs view
@@ -0,0 +1,53 @@+module Chiasma.Command.Window where++import Control.Monad.Free.Class (MonadFree)++import Chiasma.Codec (TmuxCodec)+import Chiasma.Codec.Data (Pane, Window(Window))+import Chiasma.Data.Ident (Ident, identText)+import Chiasma.Data.TmuxId (SessionId, TmuxId(formatId), WindowId)+import Chiasma.Data.TmuxThunk (TmuxThunk)+import qualified Chiasma.Monad.Tmux as Tmux (read, unsafeReadFirst, unsafeReadOne)++sameId :: WindowId -> Window -> Bool+sameId target (Window i _ _) = target == i++windows :: MonadFree TmuxThunk m => m [Window]+windows =+ Tmux.read "list-windows" ["-a"]++window :: MonadFree TmuxThunk m => WindowId -> m (Maybe Window)+window windowId =+ find (sameId windowId) <$> windows++sessionWindows :: MonadFree TmuxThunk m => SessionId -> m [Window]+sessionWindows sid =+ Tmux.read "list-windows" ["-t", formatId sid]++newSessionWindow :: MonadFree TmuxThunk m => SessionId -> m Window+newSessionWindow sid =+ Tmux.unsafeReadOne "list-windows" ["-t", formatId sid]++doesWindowExist :: MonadFree TmuxThunk m => WindowId -> m Bool+doesWindowExist windowId =+ any (sameId windowId) <$> windows++newWindow :: MonadFree TmuxThunk m => SessionId -> Ident -> m Window+newWindow sid name =+ Tmux.unsafeReadOne "new-window" ["-t", formatId sid, "-n", identText name, "-P"]++splitWindowAs ::+ (MonadFree TmuxThunk m, TmuxCodec a) =>+ FilePath ->+ WindowId ->+ m a+splitWindowAs dir windowId =+ Tmux.unsafeReadFirst "split-window" ["-t", formatId windowId, "-d", "-P", "-c", toText dir]++splitWindow ::+ (MonadFree TmuxThunk m) =>+ FilePath ->+ WindowId ->+ m Pane+splitWindow =+ splitWindowAs
+ lib/Chiasma/Control/IO/Unsafe.hs view
@@ -0,0 +1,6 @@+module Chiasma.Control.IO.Unsafe where++import GHC.IO.Unsafe (unsafePerformIO)++unsafeLog :: Show a => a -> b -> b+unsafeLog a b = unsafePerformIO $ print a >> return b
+ lib/Chiasma/Data/Cmd.hs view
@@ -0,0 +1,26 @@+module Chiasma.Data.Cmd(+ CmdName(..),+ CmdArgs(..),+ Cmd(..),+ Cmds(..),+ cmd,+) where++newtype CmdName =+ CmdName Text+ deriving (Eq, Show)++newtype CmdArgs =+ CmdArgs [Text]+ deriving (Eq, Show)++data Cmd =+ Cmd CmdName CmdArgs+ deriving (Eq, Show)++newtype Cmds =+ Cmds [Cmd]+ deriving (Eq, Show)++cmd :: Text -> [Text] -> Cmd+cmd name args = Cmd (CmdName name) (CmdArgs args)
+ lib/Chiasma/Data/Conduit.hs view
@@ -0,0 +1,10 @@+{-# LANGUAGE DataKinds #-}++module Chiasma.Data.Conduit where++import Conduit (ConduitT, Flush)+import Data.Conduit.Binary (sinkHandleFlush)+import Data.Conduit.Process.Typed (StreamSpec, StreamType(STInput), createPipe)++createSinkFlush :: MonadIO m => StreamSpec 'STInput (ConduitT (Flush ByteString) o m ())+createSinkFlush = sinkHandleFlush <$> createPipe
+ lib/Chiasma/Data/Ident.hs view
@@ -0,0 +1,59 @@+module Chiasma.Data.Ident where++import Data.Aeson (FromJSON, ToJSON(toEncoding), defaultOptions, genericToEncoding)+import Data.Data (Data)+import Data.Text.Prettyprint.Doc (Pretty(..))+import Data.UUID (UUID)+import qualified Data.UUID as UUID (fromText, toText)+import System.Random (randomIO)+import qualified Text.Show as Show++data Ident =+ Str Text+ |+ Uuid UUID+ deriving (Eq, Generic, Data, NFData, Ord)++instance Show Ident where+ show = toString . identText++class Identifiable a where+ identify :: a -> Ident++instance Identifiable Ident where+ identify = id++instance Pretty Ident where+ pretty (Str s) = pretty s+ pretty (Uuid u) = pretty . UUID.toText $ u++instance Default Ident where+ def = Str ""++instance IsString Ident where+ fromString = Str . toText++instance FromJSON Ident where++instance ToJSON Ident where+ toEncoding = genericToEncoding defaultOptions++sameIdent ::+ Identifiable a =>+ Identifiable b =>+ a ->+ b ->+ Bool+sameIdent target b =+ identify target == identify b++identText :: Ident -> Text+identText (Str a) = a+identText (Uuid a) = UUID.toText a++generateIdent :: MonadIO m => m Ident+generateIdent = liftIO $ Uuid <$> randomIO++parseIdent :: Text -> Ident+parseIdent text =+ maybe (Str text) Uuid (UUID.fromText text)
+ lib/Chiasma/Data/List.hs view
@@ -0,0 +1,16 @@+module Chiasma.Data.List(+ head',+ tail',+ last',+) where++head' :: [a] -> Maybe a+head' (a : _) = Just a+head' _ = Nothing++tail' :: [a] -> Maybe [a]+tail' (_ : as) = Just as+tail' _ = Nothing++last' :: [a] -> Maybe a+last' = head' . reverse
+ lib/Chiasma/Data/Maybe.hs view
@@ -0,0 +1,17 @@+module Chiasma.Data.Maybe where++import Control.Monad.Error.Class (MonadError(throwError))++maybeExcept :: MonadError e m => e -> Maybe a -> m a+maybeExcept e Nothing = throwError e+maybeExcept _ (Just a) = return a++findMaybe :: (a -> Maybe b) -> [a] -> Maybe b+findMaybe f as =+ case mapMaybe f as of+ (a : _) -> Just a+ _ -> Nothing++orElse :: Maybe a -> Maybe a -> Maybe a+orElse _ (Just a) = Just a+orElse fallback Nothing = fallback
− lib/Chiasma/Data/Pane.hs
@@ -1,23 +0,0 @@-module Chiasma.Data.Pane(- Pane(..),- PaneId(..),-) where--import GHC.Generics (Generic)-import Chiasma.Codec (TmuxCodec)-import Chiasma.Codec.Decode (TmuxPrimDecode(..), parseId)--newtype PaneId =- PaneId Int- deriving (Eq, Show)--instance TmuxPrimDecode PaneId where- primDecode = parseId PaneId '%'--data Pane =- Pane {- paneId :: PaneId,- paneWidth :: Int,- paneHeight :: Int- }- deriving (Eq, Show, Generic, TmuxCodec)
+ lib/Chiasma/Data/RenderError.hs view
@@ -0,0 +1,17 @@+module Chiasma.Data.RenderError where++import Chiasma.Data.Ident (Ident)+import Chiasma.Data.TmuxError (TmuxError)+import Chiasma.Data.Views (ViewsError)++data RenderError =+ NoPrincipal Ident+ |+ Views ViewsError+ |+ Pack Text+ |+ Fatal TmuxError+ deriving (Eq, Show)++deepPrisms ''RenderError
+ lib/Chiasma/Data/TmuxError.hs view
@@ -0,0 +1,39 @@+module Chiasma.Data.TmuxError where++import Chiasma.Codec.Decode (TmuxDecodeError)+import Text.ParserCombinators.Parsec (ParseError)++import Chiasma.Data.Cmd (Cmds(..))++data TmuxError =+ ProcessFailed {+ processFailedCmds :: Cmds,+ processFailedReason :: Text+ }+ |+ OutputParsingFailed {+ parsingFailedCmds :: Cmds,+ parsingFailedOutput :: [Text],+ parsingFailedError :: ParseError+ }+ |+ NoOutput Cmds+ |+ DecodingFailed {+ decodingFailedCmds :: Cmds,+ decodingFailedOutput :: Text,+ decodingFailedError :: TmuxDecodeError+ }+ |+ InvalidOutput {+ invalidOutputReason :: Text,+ invalidOutputCommand :: Text+ }+ |+ CommandFailed {+ commandFailedCmds :: Cmds,+ commandFailedError :: [Text]+ }+ deriving (Eq, Show)++deepPrisms ''TmuxError
+ lib/Chiasma/Data/TmuxId.hs view
@@ -0,0 +1,64 @@+module Chiasma.Data.TmuxId where++import Data.Text.Prettyprint.Doc (Pretty(..))++sessionPrefix :: Char+sessionPrefix = '$'++newtype SessionId =+ SessionId Int+ deriving (Eq, Show, Generic)+ deriving newtype (Num, Ord)++instance Pretty SessionId where+ pretty = pretty . formatId++windowPrefix :: Char+windowPrefix = '@'++newtype WindowId =+ WindowId Int+ deriving (Eq, Show, Generic)+ deriving newtype (Num, Ord)++instance Pretty WindowId where+ pretty = pretty . formatId++panePrefix :: Char+panePrefix = '%'++newtype PaneId =+ PaneId Int+ deriving (Eq, Show, Generic)+ deriving newtype (Num, Ord)++instance Pretty PaneId where+ pretty = pretty . formatId++class HasPaneId a where+ paneId :: a -> PaneId++newtype TmuxIdPrefix a =+ TmuxIdPrefix Char++class TmuxId a where+ prefix :: TmuxIdPrefix a+ number :: a -> Int++ formatId :: a -> Text+ formatId a =+ toText (p : show (number a))+ where+ (TmuxIdPrefix p) = prefix @a++instance TmuxId SessionId where+ prefix = TmuxIdPrefix sessionPrefix+ number (SessionId i) = i++instance TmuxId WindowId where+ prefix = TmuxIdPrefix windowPrefix+ number (WindowId i) = i++instance TmuxId PaneId where+ prefix = TmuxIdPrefix panePrefix+ number (PaneId i) = i
lib/Chiasma/Data/TmuxThunk.hs view
@@ -1,53 +1,16 @@-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE StandaloneDeriving #-}--module Chiasma.Data.TmuxThunk(- CmdName(..),- CmdArgs(..),- TmuxThunk(..),- TmuxError(..),- Cmd(..),- Cmds(..),- cmd,-) where+module Chiasma.Data.TmuxThunk where -import Text.ParserCombinators.Parsec (ParseError) import Chiasma.Codec.Decode (TmuxDecodeError)--newtype CmdName =- CmdName String- deriving (Eq, Show)--newtype CmdArgs =- CmdArgs [String]- deriving (Eq, Show)--data Cmd =- Cmd CmdName CmdArgs- deriving (Eq, Show)--newtype Cmds =- Cmds [Cmd]- deriving (Eq, Show)--data TmuxError =- ProcessFailed Cmds String- |- OutputParsingFailed Cmds [String] ParseError- |- NoOutput Cmds- |- DecodingFailed Cmds String TmuxDecodeError- deriving (Eq, Show)+import Chiasma.Data.Cmd (Cmd(..))+import Chiasma.Data.TmuxError (TmuxError(..)) data TmuxThunk next =- ∀ a . Read Cmd ([String] -> Either TmuxDecodeError a) ([a] -> next)+ ∀ a . Read Cmd (Text -> Either TmuxDecodeError a) ([a] -> next) | Write Cmd (() -> next) |+ Flush (() -> next)+ | Failed TmuxError deriving instance Functor TmuxThunk--cmd :: String -> [String] -> Cmd-cmd name args = Cmd (CmdName name) (CmdArgs args)
+ lib/Chiasma/Data/View.hs view
@@ -0,0 +1,21 @@+module Chiasma.Data.View where++import Chiasma.Data.Ident (Ident, Identifiable(..))+import Control.Lens (makeClassy_)+import qualified Control.Lens as Lens (set)++data View a =+ View {+ viewIdent :: Ident,+ viewId :: Maybe a+ }+ deriving (Eq, Show)++makeClassy_ ''View++instance Identifiable (View a) where+ identify = viewIdent++setViewId :: a -> View a -> View a+setViewId =+ Lens.set _viewId . Just
+ lib/Chiasma/Data/Views.hs view
@@ -0,0 +1,37 @@+{-# LANGUAGE DeriveAnyClass #-}++module Chiasma.Data.Views where++import Data.Text.Prettyprint.Doc (Doc)+import Data.Text.Prettyprint.Doc.Render.Terminal (AnsiStyle)++import Chiasma.Data.Ident (Ident)+import Chiasma.Data.TmuxId (PaneId, SessionId, WindowId)+import Chiasma.Data.View (View)++data ViewsError =+ NoSuchSession Ident+ |+ NoSuchWindow Ident+ |+ NoSuchPane Ident+ |+ NoPaneId Ident+ deriving (Eq, Show)++deepPrisms ''ViewsError++data Views =+ Views {+ _sessions :: [View SessionId],+ _windows :: [View WindowId],+ _panes :: [View PaneId],+ _log :: [Doc AnsiStyle]+ }+ deriving (Show, Generic, Default)++instance Eq Views where+ (Views sa wa pa _) == (Views sb wb pb _) =+ (sa == sb) && (wa == wb) && (pa == pb)++deepLenses ''Views
− lib/Chiasma/Data/Window.hs
@@ -1,23 +0,0 @@-module Chiasma.Data.Window(- Window(..),- WindowId(..),-) where--import GHC.Generics (Generic)-import Chiasma.Codec (TmuxCodec)-import Chiasma.Codec.Decode (TmuxPrimDecode(..), parseId)--newtype WindowId =- WindowId Int- deriving (Eq, Show)--instance TmuxPrimDecode WindowId where- primDecode = parseId WindowId '@'--data Window =- Window {- windowId :: WindowId,- windowWidth :: Int,- windowHeight :: Int- }- deriving (Eq, Show, Generic, TmuxCodec)
+ lib/Chiasma/Data/WindowState.hs view
@@ -0,0 +1,18 @@+module Chiasma.Data.WindowState(+ WindowState(..),+) where++import qualified Chiasma.Codec.Data as Codec (Window, Pane)+import Chiasma.Data.Ident (Ident)+import Chiasma.Data.TmuxId (PaneId)+import Chiasma.Ui.Data.RenderableTree (RenderableTree)++data WindowState =+ WindowState {+ wsNativeWindow :: Codec.Window,+ wsNativeRefPane :: Codec.Pane,+ wsWindowIdent :: Ident,+ wsLayout :: RenderableTree,+ wsReferencePane :: PaneId+ }+ deriving (Eq, Show)
+ lib/Chiasma/Lens/Tree.hs view
@@ -0,0 +1,127 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE DeriveDataTypeable #-}++module Chiasma.Lens.Tree where++import Chiasma.Data.Ident (Ident, Identifiable(..))+import Chiasma.Ui.Data.View+import Chiasma.Ui.Lens.Ident (matchIdentP)+import Control.Lens (+ Fold,+ Index,+ IxValue,+ Ixed(ix),+ Plated(..),+ Traversal',+ cosmos,+ each,+ makeClassy_,+ over,+ preview,+ toListOf,+ transform,+ )+import Data.Data (Data)+import Data.Foldable (foldrM)++newtype NodeIndexTree l p =+ NodeIndexTree {+ nitTree :: Tree l p+ }+ deriving (Eq, Show)++makeClassy_ ''NodeIndexTree++newtype LeafIndexTree l p =+ LeafIndexTree {+ litTree :: Tree l p+ }+ deriving (Eq, Show)++makeClassy_ ''LeafIndexTree++plateWrap :: (Data l, Data p) => (Tree l p -> t l p) -> (t l p -> Tree l p) -> Traversal' (t l p) (t l p)+plateWrap consWrapper unconsWrapper f wrappedTree =+ consWrapper <$> plate g (unconsWrapper wrappedTree)+ where+ g tree' = unconsWrapper <$> f (consWrapper tree')++instance (Data l, Data p) => Plated (NodeIndexTree l p) where+ plate = plateWrap NodeIndexTree nitTree++instance (Data l, Data p) => Plated (LeafIndexTree l p) where+ plate = plateWrap LeafIndexTree litTree++type LayoutIndexTree = NodeIndexTree LayoutView PaneView+type PaneIndexTree = LeafIndexTree LayoutView PaneView++type instance Index (NodeIndexTree _ _) = Ident+type instance Index (LeafIndexTree _ _) = Ident++type instance IxValue (NodeIndexTree l _) = l+type instance IxValue (LeafIndexTree _ p) = p++leafDataTraversal :: Traversal' (Tree l p) p+leafDataTraversal = _treeSubs . each . leafData++leafByIdentTraversal :: Identifiable p => Ident -> Traversal' (Tree l p) p+leafByIdentTraversal ident' = leafDataTraversal . matchIdentP ident'++instance Identifiable p => Ixed (LeafIndexTree l p) where+ ix ident' = _litTree . leafByIdentTraversal ident'++leavesByIdentRecursive :: (Identifiable p, Data l, Data p) => Ident -> Fold (LeafIndexTree l p) p+leavesByIdentRecursive ident' = cosmos . ix ident'++leafByIdent :: (Identifiable p, Data l, Data p) => Ident -> Tree l p -> Maybe p+leafByIdent ident' = preview (leavesByIdentRecursive ident') . LeafIndexTree++leavesByIdent :: (Identifiable p, Data l, Data p) => Ident -> Tree l p -> [p]+leavesByIdent ident' = toListOf (leavesByIdentRecursive ident') . LeafIndexTree++modifyLeafByIdent :: (Identifiable p, Data l, Data p) => Ident -> (p -> p) -> Tree l p -> Tree l p+modifyLeafByIdent ident' f tree' =+ litTree $ (transform $ over (ix ident') f) (LeafIndexTree tree')++-- subtreesWithLayout :: Traversal' (Tree l p) (l, TreeSub l p)+subtreesWithLayout :: ∀ l p m. Monad m => ((l, TreeSub l p) -> m (l, TreeSub l p)) -> Tree l p -> m (Tree l p)+subtreesWithLayout f (Tree l0 sub) = do+ (newL, newSub) <- foldrM applySub (l0, []) sub+ return (Tree newL newSub)+ where+ prependSub s (newL, newN) = (newL, newN : s)+ applySub :: TreeSub l p -> (l, [TreeSub l p]) -> m (l, [TreeSub l p])+ applySub (TreeNode t) (l, s) = do+ recur <- (\rsub -> (l, TreeNode rsub)) <$> subtreesWithLayout f t+ (fmap (prependSub s) . f) recur+ applySub p (l, s) =+ (fmap (prependSub s) . f) (l, p)++subtrees :: ∀ l p m. Monad m => (TreeSub l p -> m (TreeSub l p)) -> Tree l p -> m (Tree l p)+subtrees f (Tree l sub) = do+ newSub <- mapM applySub sub+ return (Tree l newSub)+ where+ applySub :: TreeSub l p -> m (TreeSub l p)+ applySub (TreeNode t) = do+ recur <- subtrees f t+ f (TreeNode recur)+ applySub p = f p++treesAndSubs ::+ Monad m =>+ (Tree l p -> m (Tree l p)) ->+ (TreeSub l p -> m (TreeSub l p)) ->+ Tree l p ->+ m (Tree l p)+treesAndSubs ft fs (Tree l sub) = do+ treeResult <- mapM applySub sub+ ft (Tree l treeResult)+ where+ applySub (TreeNode t) = do+ recur <- treesAndSubs ft fs t+ fs (TreeNode recur)+ applySub p = fs p
+ lib/Chiasma/Lens/Where.hs view
@@ -0,0 +1,10 @@+{-# LANGUAGE RankNTypes #-}++module Chiasma.Lens.Where(+ where1,+) where++import Control.Lens (Over, filtered, taking)++where1 :: (Applicative f, Traversable t) => (a -> Bool) -> Over (->) f (t a) (t a) a a+where1 predicate = taking 1 $ traverse . filtered predicate
− lib/Chiasma/Monad/Buffered.hs
@@ -1,29 +0,0 @@-module Chiasma.Monad.Buffered(- runTmux,-) where--import Control.Monad.Free (Free(..))-import Control.Monad.IO.Class (MonadIO)-import Control.Monad.Trans.Except (ExceptT, runExceptT, throwE)-import Data.Default.Class (Default(def))-import Chiasma.Api.Class (TmuxApi(..))-import Chiasma.Data.TmuxThunk (Cmd(..), Cmds(..), TmuxThunk(..), TmuxError)-import Chiasma.Monad.Tmux (TmuxProg)--newtype TmuxState = TmuxState [Cmd]--instance Default TmuxState where- def = TmuxState def--interpret :: (MonadIO m, TmuxApi api) => TmuxState -> api -> TmuxProg b -> ExceptT TmuxError m b-interpret (TmuxState cmds) api (Pure a) = a <$ runCommands api (const $ Right ()) (Cmds cmds)-interpret (TmuxState cmds) api (Free (Read cmd decode next)) = do- a <- runCommands api decode $ Cmds (cmd : cmds)- interpret def api (next a)-interpret (TmuxState cmds) api (Free (Write cmd next)) =- interpret (TmuxState (cmd : cmds)) api (next ())-interpret _ _ (Free (Failed err)) =- throwE err--runTmux :: (MonadIO m, TmuxApi api) => api -> TmuxProg b -> m (Either TmuxError b)-runTmux api prog = runExceptT $ interpret def api prog
+ lib/Chiasma/Monad/EvalFreeT.hs view
@@ -0,0 +1,50 @@+module Chiasma.Monad.EvalFreeT where++import Control.Monad.Trans.Free (FreeF(..), FreeT(..))++import Chiasma.Codec.Decode (TmuxDecodeError)+import Chiasma.Data.Cmd (Cmd(..), Cmds(..))+import Chiasma.Data.TmuxError (TmuxError)+import Chiasma.Data.TmuxThunk (TmuxThunk(..))++newtype CmdBuffer = CmdBuffer [Cmd]++instance Default CmdBuffer where+ def = CmdBuffer def++type CommandExec m =+ (∀ b. (Text -> Either TmuxDecodeError b) -> Cmds -> m (Either TmuxError [b]))++evalFreeF ::+ Monad m =>+ CommandExec m ->+ CmdBuffer ->+ FreeF TmuxThunk a (FreeT TmuxThunk m a) ->+ m (Either TmuxError a)+evalFreeF _ (CmdBuffer []) (Pure a) =+ return (Right a)+evalFreeF exec (CmdBuffer cmds) (Pure a) =+ Right a <$ exec (const $ Right ()) (Cmds cmds)+evalFreeF exec (CmdBuffer cmds) (Free (Read cmd decode next)) = do+ a <- exec decode $ Cmds (cmd : cmds)+ case a of+ Right a' -> evalFreeT exec def (next a')+ Left err -> return (Left err)+evalFreeF exec (CmdBuffer cmds) (Free (Write cmd next)) =+ evalFreeT exec (CmdBuffer (cmd : cmds)) (next ())+evalFreeF exec (CmdBuffer cmds) (Free (Flush next)) =+ exec (const $ Right ()) (Cmds cmds) >>= \case+ Right _ -> evalFreeT exec def (next ())+ Left err -> return (Left err)+evalFreeF _ _ (Free (Failed err)) =+ return (Left err)++evalFreeT ::+ Monad m =>+ CommandExec m ->+ CmdBuffer ->+ FreeT TmuxThunk m a ->+ m (Either TmuxError a)+evalFreeT exec s (FreeT ma) = do+ inner <- ma+ evalFreeF exec s inner
+ lib/Chiasma/Monad/IndividualProcess.hs view
@@ -0,0 +1,40 @@+module Chiasma.Monad.IndividualProcess where++import Control.Monad.Free (Free(..))++import Chiasma.Api.Class (TmuxApi(..))+import Chiasma.Data.Cmd (Cmd(..), Cmds(..))+import Chiasma.Data.TmuxError (TmuxError)+import Chiasma.Data.TmuxThunk (TmuxThunk(..))++type TmuxProg = Free TmuxThunk++newtype TmuxState = TmuxState [Cmd]++instance Default TmuxState where+ def = TmuxState def++interpret ::+ (TmuxApi m api, MonadDeepError e TmuxError m) =>+ TmuxState ->+ api ->+ TmuxProg a ->+ m a+interpret (TmuxState cmds) api (Pure a) = a <$ runCommands api (const $ Right ()) (Cmds cmds)+interpret (TmuxState cmds) api (Free (Read cmd decode next)) = do+ a <- runCommands api decode $ Cmds (cmd : cmds)+ interpret def api (next a)+interpret (TmuxState cmds) api (Free (Write cmd next)) =+ interpret (TmuxState (cmd : cmds)) api (next ())+interpret (TmuxState cmds) api (Free (Flush next)) = do+ _ <- runCommands api (const $ Right ()) (Cmds cmds)+ interpret def api (next ())+interpret _ _ (Free (Failed err)) =+ throwHoist err++runTmux ::+ (TmuxApi m api, MonadDeepError e TmuxError m) =>+ api ->+ TmuxProg a ->+ m a+runTmux = interpret def
− lib/Chiasma/Monad/Simple.hs
@@ -1,38 +0,0 @@-module Chiasma.Monad.Simple(- -- tmuxProcessConfig,- -- tmuxProcess,- -- interpret,- -- runTmux,-) where---- import GHC.IO.Exception (ExitCode(ExitSuccess))--- import Control.Monad (when)--- import Control.Monad.Free (foldFree)--- import Control.Monad.IO.Class (MonadIO)--- import Control.Monad.Trans.Except (ExceptT(ExceptT), catchE, runExceptT)--- import qualified Data.ByteString.Lazy.Internal as B (unpackChars)--- import Data.Functor (void)--- import Data.List.Split (linesBy)--- import System.Process.Typed (ProcessConfig, readProcessStdout, proc)--- import UnliftIO (throwIO)--- import Chiasma.Data.TmuxThunk (Cmd(..), CmdName(..), CmdArgs(..), Cmds(..), TmuxThunk(..), TmuxError(..))--- import Chiasma.Monad.Tmux (TmuxProg)---- tmuxProcessConfig :: CmdName -> CmdArgs -> ProcessConfig () () ()--- tmuxProcessConfig (CmdName cmd) (CmdArgs args) =--- proc "tmux" (["-C", cmd] ++ args)---- tmuxProcess :: MonadIO m => Cmd -> m (Either TmuxError [String])--- tmuxProcess cmd@(Cmd name args) = do--- (code, out) <- readProcessStdout $ tmuxProcessConfig name args--- let outLines = linesBy (=='\n') $ B.unpackChars out--- return $ case code of--- ExitSuccess -> Right outLines--- _ -> Left $ TmuxProcessFailed (Cmds [cmd]) outLines---- interpret :: MonadIO m => TmuxThunk a next -> ExceptT TmuxError m next--- interpret (Read cmd next) = next <$> tmuxProcess cmd--- interpret (Write cmd next) = next <$> void (tmuxProcess cmd)---- runTmux :: MonadIO m => TmuxProg a next -> m (Either TmuxError next)--- runTmux = runExceptT . foldFree interpret
+ lib/Chiasma/Monad/Stream.hs view
@@ -0,0 +1,80 @@+module Chiasma.Monad.Stream where++import Conduit (ConduitT, Flush(..), runConduit, sinkList, yield, yieldMany, (.|))+import Control.Monad.Trans.Free (FreeT(..))+import qualified Data.Conduit.Combinators as Conduit (drop, take)++import Chiasma.Api.Class (TmuxApi(..))+import Chiasma.Codec.Decode (TmuxDecodeError)+import Chiasma.Data.Cmd (Cmd(..), Cmds(..))+import Chiasma.Data.TmuxError (TmuxError)+import qualified Chiasma.Data.TmuxError as TmuxError (TmuxError(ProcessFailed, DecodingFailed, CommandFailed))+import Chiasma.Data.TmuxThunk (TmuxThunk)+import Chiasma.Monad.EvalFreeT (evalFreeT)+import Chiasma.Native.StreamParse (TmuxOutputBlock)+import qualified Chiasma.Native.StreamParse as TmuxOutputBlock (TmuxOutputBlock(..))++type TmuxProg = FreeT TmuxThunk++type WriteCmd m =+ ConduitT (Flush Cmd) Void m ()++type ReadOutput m =+ ConduitT () TmuxOutputBlock m ()++handleProcessOutput ::+ Cmds ->+ (Text -> Either TmuxDecodeError a) ->+ [TmuxOutputBlock] ->+ Either TmuxError [a]+handleProcessOutput cs@(Cmds cmds) _ output | length output < length cmds =+ Left $ TmuxError.ProcessFailed cs "tmux terminated before all commands were processed"+handleProcessOutput cmds decode output = do+ readOutput <- foldl validate (Right []) output+ traverse decode' readOutput+ where+ validate (Left err) _ = Left err+ validate _ (TmuxOutputBlock.Success a) = Right a+ validate _ (TmuxOutputBlock.Error a) = Left $ TmuxError.CommandFailed cmds a+ decode' outputLine =+ mapLeft (TmuxError.DecodingFailed cmds outputLine) . decode $ outputLine++executeCommands ::+ MonadIO m =>+ WriteCmd m ->+ ReadOutput m ->+ (Text -> Either TmuxDecodeError a) ->+ Cmds ->+ m (Either TmuxError [a])+executeCommands writeCmd readOutput decode cs@(Cmds cmds) = do+ output <- runConduit $ do+ yieldMany (Chunk <$> reverse cmds) .| writeCmd+ yield Flush .| writeCmd+ readOutput .| Conduit.take (length cmds) .| sinkList+ return $ handleProcessOutput cs decode output++runTmuxProg ::+ MonadIO m =>+ TmuxProg m a ->+ WriteCmd m ->+ ReadOutput m ->+ m (Either TmuxError a)+runTmuxProg prog writeCmd readOutput = do+ runConduit $ readOutput .| Conduit.drop 1+ evalFreeT (executeCommands writeCmd readOutput) def prog++runTmuxE ::+ (MonadIO m, TmuxApi m api) =>+ api ->+ TmuxProg m a ->+ m (Either TmuxError a)+runTmuxE api prog =+ withTmux api (runTmuxProg prog)++runTmux ::+ (MonadIO m, MonadDeepError e TmuxError m, TmuxApi m api) =>+ api ->+ TmuxProg m a ->+ m a+runTmux api =+ hoistEither <=< runTmuxE api
lib/Chiasma/Monad/Tmux.hs view
@@ -1,21 +1,49 @@-{-# LANGUAGE ScopedTypeVariables #-}+module Chiasma.Monad.Tmux where -module Chiasma.Monad.Tmux(- Chiasma.Monad.Tmux.read,- write,- TmuxProg,-) where+import Control.Monad.Free (liftF)+import Control.Monad.Free.Class (MonadFree) -import Control.Monad.Free (Free, liftF) import Chiasma.Codec (TmuxCodec, TmuxQuery(unQ)) import qualified Chiasma.Codec as TmuxCodec (TmuxCodec(decode, query))-import Chiasma.Data.TmuxThunk (TmuxThunk(..), cmd)--type TmuxProg = Free TmuxThunk+import Chiasma.Data.Cmd (cmd)+import Chiasma.Data.TmuxError (TmuxError(InvalidOutput))+import Chiasma.Data.TmuxThunk (TmuxThunk(..)) -read :: ∀ a . TmuxCodec a => String -> [String] -> TmuxProg [a]+read :: ∀ a m . (TmuxCodec a, MonadFree TmuxThunk m) => Text -> [Text] -> m [a] read name args =- liftF $ Read (cmd name (args ++ ["-F", "'" ++ unQ (TmuxCodec.query @a) ++ "'"])) TmuxCodec.decode id+ liftF $ Read (cmd name (args <> formatArgs)) TmuxCodec.decode id+ where+ formatArgs = ["-F", "'", unQ (TmuxCodec.query @a), "'"] -write :: String -> [String] -> TmuxProg ()+unsafeReadOne :: ∀ a m . (TmuxCodec a, MonadFree TmuxThunk m) => Text -> [Text] -> m a+unsafeReadOne name args = do+ outputs <- read name args+ case outputs of+ [a] -> return a+ [] -> liftF $ Failed $ InvalidOutput "no data" (name <> unwords args)+ _ -> liftF $ Failed $ InvalidOutput "multiple outputs for `unsafeReadOne`" (name <> unwords args)++readFirst :: ∀ a m . (TmuxCodec a, MonadFree TmuxThunk m) => Text -> [Text] -> m (Maybe a)+readFirst name args = do+ outputs <- read name args+ return $ case outputs of+ (a : _) -> Just a+ [] -> Nothing++unsafeReadFirst :: ∀ a m . (TmuxCodec a, MonadFree TmuxThunk m) => Text -> [Text] -> m a+unsafeReadFirst name args = do+ mayFirst <- readFirst name args+ case mayFirst of+ (Just a) -> return a+ Nothing -> liftF $ Failed $ InvalidOutput "no data" (name <> unwords args)++readRaw :: ∀ m . (MonadFree TmuxThunk m) => Text -> [Text] -> m [Text]+readRaw name args =+ liftF $ Read (cmd name args) Right id++write :: MonadFree TmuxThunk m => Text -> [Text] -> m () write name args = liftF $ Write (cmd name args) id++flush :: MonadFree TmuxThunk m => m ()+flush =+ liftF $ Flush id
lib/Chiasma/Native/Api.hs view
@@ -1,15 +1,67 @@-module Chiasma.Native.Api(- TmuxApi(..),- TmuxNative(..),-) where+{-# LANGUAGE UndecidableInstances #-} -import Control.Monad.Trans.Except (ExceptT(ExceptT))+module Chiasma.Native.Api where++import Chiasma.Data.TmuxError (TmuxError)+import Conduit (ConduitT, Flush, mapC, (.|))+import Control.Monad.Catch (MonadMask)+import qualified Control.Monad.Catch as Catch (bracket)+import Data.Conduit.Process.Typed (createSource)+import qualified Data.Text as Text (unwords)+import System.Process.Typed (+ Process,+ ProcessConfig,+ getStdin,+ getStdout,+ proc,+ setStdin,+ setStdout,+ startProcess,+ stopProcess,+ ) import Text.ParserCombinators.Parsec ()+ import Chiasma.Api.Class (TmuxApi(..))-import Chiasma.Native.Process (nativeTmuxProcess)+import Chiasma.Data.Cmd (Cmd(..), CmdArgs(..), CmdName(..))+import Chiasma.Data.Conduit (createSinkFlush)+import Chiasma.Native.Process (nativeTmuxProcess, socketArg)+import Chiasma.Native.StreamParse (parseConduit) newtype TmuxNative =- TmuxNative FilePath+ TmuxNative { tmuxServerSocket :: Maybe FilePath }+ deriving Show -instance TmuxApi TmuxNative where- runCommands (TmuxNative socket) decode cmds = ExceptT $ nativeTmuxProcess socket decode cmds+formatCmd :: Cmd -> ByteString+formatCmd (Cmd (CmdName name) (CmdArgs args)) =+ encodeUtf8 . Text.unwords $ name : args ++ ["\n"]++tmuxProcessConfig ::+ MonadIO m =>+ Maybe FilePath ->+ ProcessConfig (ConduitT (Flush ByteString) Void m ()) (ConduitT () ByteString m ()) ()+tmuxProcessConfig sock =+ cons args+ where+ cons =+ setStdin createSinkFlush . setStdout createSource . proc "tmux"+ args =+ toString <$> (socketArg sock ++ ["-C", "attach"])++withProcess :: (MonadIO m, MonadMask m)+ => ProcessConfig stdin stdout stderr+ -> (Process stdin stdout stderr -> m a)+ -> m a+withProcess config = Catch.bracket (startProcess config) stopProcess++instance (MonadIO m, MonadDeepError e TmuxError m, MonadMask m) => TmuxApi m TmuxNative where+ runCommands (TmuxNative socket) =+ nativeTmuxProcess socket++ withTmux (TmuxNative socket) f =+ withProcess (tmuxProcessConfig socket) handler+ where+ handler prc =+ let+ stdin' = mapC (fmap formatCmd) .| getStdin prc+ stdout' = getStdout prc .| parseConduit+ in f stdin' stdout'
lib/Chiasma/Native/Parse.hs view
@@ -1,43 +1,35 @@-module Chiasma.Native.Parse(- resultParser,- resultLines,-) where+module Chiasma.Native.Parse where -import Text.ParserCombinators.Parsec (- GenParser,+import qualified Data.Text as T (pack)+import Prelude hiding (many)+import Text.Parsec ( ParseError,- parse, many,- skipMany, manyTill,- notFollowedBy,+ parse,+ skipMany, try, )-import Text.Parsec.Char (endOfLine, string, anyChar)+import Text.Parsec.Char (anyChar, endOfLine, string)+import Text.Parsec.Text (GenParser) -tillEol :: GenParser Char st String-tillEol = manyTill anyChar endOfLine+tillEol :: GenParser st Text+tillEol = T.pack <$> manyTill anyChar endOfLine -beginLine :: GenParser Char st String+beginLine :: GenParser st Text beginLine = string "%begin" >> tillEol -endLine :: GenParser Char st String+endLine :: GenParser st Text endLine = string "%end" >> tillEol -notBeginLine :: GenParser Char st String-notBeginLine = notFollowedBy (string "%begin") >> tillEol--parseBlock :: GenParser Char st [String]+parseBlock :: GenParser st [Text] parseBlock = do- _ <- skipMany notBeginLine- _ <- beginLine+ _ <- manyTill tillEol (try beginLine) manyTill tillEol (try endLine) -resultParser :: GenParser Char st [[String]]-resultParser = do- result <- many (try parseBlock)- skipMany tillEol- return result+resultParser :: GenParser st [[Text]]+resultParser =+ many (try parseBlock) <* skipMany tillEol -resultLines :: String -> Either ParseError [[String]]+resultLines :: Text -> Either ParseError [[Text]] resultLines = parse resultParser "tmux output"
lib/Chiasma/Native/Process.hs view
@@ -1,45 +1,57 @@-module Chiasma.Native.Process(- tmuxProcessConfig,- nativeTmuxProcess,-) where+module Chiasma.Native.Process where -import GHC.IO.Exception (ExitCode(ExitSuccess))-import Control.Monad.IO.Class (MonadIO)-import Data.ByteString.Lazy (ByteString)-import Data.ByteString.Lazy.Internal (packChars, unpackChars)-import Data.Either.Combinators (mapLeft)-import Data.List (intercalate)-import System.Process.Typed (ProcessConfig, readProcessStdout, proc, setStdin, byteStringInput)+import qualified Data.ByteString.Lazy as Lazy (ByteString)+import Data.ByteString.Lazy.Internal (unpackChars)+import qualified Data.Text as Text (intercalate, lines, pack, unwords)+import System.Exit (ExitCode(ExitSuccess))+import System.Process.Typed (ProcessConfig, byteStringInput, proc, readProcessStdout, setStdin)+ import Chiasma.Codec.Decode (TmuxDecodeError)-import Chiasma.Data.TmuxThunk (CmdName(..), Cmd(..), CmdArgs(..), Cmds(..), TmuxError(..))-import qualified Chiasma.Data.TmuxThunk as TmuxError (- TmuxError(OutputParsingFailed, NoOutput, ProcessFailed, DecodingFailed)+import Chiasma.Data.Cmd (Cmd(..), CmdArgs(..), CmdName(..), Cmds(..))+import Chiasma.Data.TmuxError (TmuxError)+import qualified Chiasma.Data.TmuxError as TmuxError (+ TmuxError(OutputParsingFailed, NoOutput, ProcessFailed, DecodingFailed), ) import Chiasma.Native.Parse (resultLines) -cmdBytes :: [String] -> ByteString-cmdBytes cmds = packChars $ intercalate "\n" $ reverse $ "" : cmds+cmdBytes :: [Text] -> Lazy.ByteString+cmdBytes cmds = encodeUtf8 $ Text.intercalate "\n" $ reverse $ "" : cmds -tmuxProcessConfig :: FilePath -> [String] -> ProcessConfig () () ()+socketArg :: Maybe FilePath -> [Text]+socketArg (Just socket) = ["-S", toText socket]+socketArg Nothing = []++tmuxProcessConfig :: Maybe FilePath -> [Text] -> ProcessConfig () () () tmuxProcessConfig socket cmds =- setStdin (byteStringInput $ cmdBytes cmds) $ proc "tmux" ["-S", socket, "-C", "attach"]+ cons args+ where+ cons =+ setStdin (byteStringInput $ cmdBytes cmds) . proc "tmux"+ args =+ toString <$> (socketArg socket <> ["-C", "attach"]) -handleProcessOutput :: Cmds -> ExitCode -> ([String] -> Either TmuxDecodeError a) -> String -> Either TmuxError [a]+handleProcessOutput :: Cmds -> ExitCode -> (Text -> Either TmuxDecodeError a) -> Text -> Either TmuxError [a] handleProcessOutput cmds ExitSuccess decode out = do- outputs <- mapLeft (TmuxError.OutputParsingFailed cmds (lines out)) $ resultLines out+ outputs <- mapLeft (TmuxError.OutputParsingFailed cmds (Text.lines out)) $ resultLines out case reverse outputs of output : _ -> traverse decode' output _ -> Left $ TmuxError.NoOutput cmds where- decode' = mapLeft (TmuxError.DecodingFailed cmds out) . decode . words+ decode' = mapLeft (TmuxError.DecodingFailed cmds out) . decode handleProcessOutput cmds _ _ out = Left $ TmuxError.ProcessFailed cmds out -formatCmd :: Cmd -> String-formatCmd (Cmd (CmdName name) (CmdArgs args)) = unwords $ name : args+formatCmd :: Cmd -> Text+formatCmd (Cmd (CmdName name) (CmdArgs args)) =+ Text.unwords $ name : args -nativeTmuxProcess :: MonadIO m => FilePath -> ([String] -> Either TmuxDecodeError a) -> Cmds -> m (Either TmuxError [a])+nativeTmuxProcess ::+ (MonadIO m, MonadDeepError e TmuxError m) =>+ Maybe FilePath ->+ (Text -> Either TmuxDecodeError a) ->+ Cmds ->+ m [a] nativeTmuxProcess socket decode cmds@(Cmds cmds') = do let cmdLines = fmap formatCmd cmds' (code, out) <- readProcessStdout $ tmuxProcessConfig socket cmdLines- return $ handleProcessOutput cmds code decode $ unpackChars out+ hoistEither $ handleProcessOutput cmds code decode $ Text.pack $ unpackChars out
+ lib/Chiasma/Native/StreamParse.hs view
@@ -0,0 +1,65 @@+module Chiasma.Native.StreamParse(+ parseConduit,+ parseBlocks,+ TmuxOutputBlock(..),+) where++import Conduit (ConduitT, mapC, (.|))+import Control.Monad.Catch (MonadThrow)+import Data.Attoparsec.ByteString (Parser)+import Data.Conduit.Attoparsec (conduitParser)+import qualified Data.Text as T (pack)+import Text.Parser.Char (CharParsing, anyChar, newline, string)+import Text.Parser.Combinators (choice, manyTill, notFollowedBy, skipMany, try)+import Text.Parser.LookAhead (LookAheadParsing, lookAhead)++data End =+ EndSuccess+ |+ EndError+ deriving (Eq, Show)++data TmuxOutputBlock =+ Success [Text]+ |+ Error [Text]+ deriving (Eq, Show)++tillEol :: (Alternative m, CharParsing m) => m Text+tillEol = T.pack <$> manyTill anyChar newline++beginLine :: (Alternative m, CharParsing m, Monad m) => m ()+beginLine = void $ string "%begin" >> tillEol++endLine :: (Alternative m, CharParsing m) => m End+endLine = do+ end <- choice [EndSuccess <$ string "%end", EndError <$ string "%error"]+ _ <- tillEol+ return end++notBeginLine :: (Alternative m, CharParsing m, Monad m) => m ()+notBeginLine = void $ notFollowedBy (string "%begin") >> tillEol++-- |Parse a sequence of lines between a %start and a %end line.+-- Tmux pads output lines with a single space on both sides, so strip those if the leading one is present.+parseBlock :: (Alternative m, CharParsing m, Monad m, LookAheadParsing m) => m TmuxOutputBlock+parseBlock = do+ _ <- skipMany notBeginLine+ _ <- beginLine+ dataLines <- manyTill tillEol $ try $ lookAhead endLine+ end <- endLine+ return $ case end of+ EndSuccess -> Success dataLines+ EndError -> Error dataLines++parseBlocks :: (Alternative m, CharParsing m, Monad m, LookAheadParsing m) => m [TmuxOutputBlock]+parseBlocks = do+ result <- many (try parseBlock)+ skipMany tillEol+ return result++parser :: Parser TmuxOutputBlock+parser = parseBlock++parseConduit :: MonadThrow m => ConduitT ByteString TmuxOutputBlock m ()+parseConduit = conduitParser parser .| mapC snd
+ lib/Chiasma/Pack.hs view
@@ -0,0 +1,109 @@+module Chiasma.Pack where++import qualified Chiasma.Codec.Data as Codec (Window(Window))+import Chiasma.Command.Pane (movePane, resizePane)+import Chiasma.Data.TmuxId (PaneId)+import Chiasma.Data.TmuxThunk (TmuxThunk)+import Chiasma.Data.Views (Views)+import Chiasma.Data.WindowState (WindowState(..))+import Chiasma.Ui.Data.Measure (MLayout(..), MPane(..), MeasureTree, MeasureTreeSub, Measured(Measured))+import Chiasma.Ui.Data.Tree (Node(Sub, Leaf), Tree(Tree))+import qualified Chiasma.Ui.Data.Tree as Tree (subTree)+import Chiasma.Ui.Measure (measureTree)+import Chiasma.View (viewsLog)+import Control.Lens (each, mapMOf_)+import Control.Monad.Free.Class (MonadFree)+import qualified Data.List.NonEmpty as NonEmpty (reverse, toList)+import qualified Data.Set as Set (fromList, size)+import Data.Text.Prettyprint.Doc (Doc, line, pretty, (<+>))++packPane ::+ (MonadDeepState s Views m, MonadFree TmuxThunk m) =>+ PaneId ->+ Bool ->+ PaneId ->+ m ()+packPane refId vertical paneId =+ when (paneId /= refId) $ movePane paneId refId vertical++positionView ::+ (MonadDeepState s Views m, MonadFree TmuxThunk m) =>+ Bool ->+ PaneId ->+ MeasureTreeSub ->+ m ()+positionView vertical refId =+ position+ where+ position (Sub (Tree (Measured _ (MLayout layoutRef _ _ _)) _)) =+ packPane refId vertical layoutRef+ position (Leaf (Measured _ (MPane paneId _ _))) =+ packPane refId vertical paneId++describeVertical :: Bool -> Doc a+describeVertical True = "vertically"+describeVertical False = "horizontally"++resizeView ::+ MonadDeepState s Views m =>+ MonadFree TmuxThunk m =>+ Bool ->+ MeasureTreeSub ->+ m ()+resizeView vertical (Sub (Tree (Measured size (MLayout refId _ _ _)) _)) = do+ viewsLog $ "resizing layout with ref" <+> pretty refId <+> "to" <+> pretty size <+> describeVertical vertical+ resizePane refId vertical size+resizeView vertical (Leaf (Measured size (MPane paneId _ _))) = do+ viewsLog $ "resizing pane" <+> pretty paneId <+> "to" <+> pretty size <+> describeVertical vertical+ resizePane paneId vertical size++needPositioning ::+ NonEmpty MeasureTreeSub ->+ Bool+needPositioning sub =+ wrongOrder || wrongDirection || unaligned+ where+ wrongOrder =+ sort positions /= positions+ wrongDirection =+ Set.size (Set.fromList positions) /= length positions+ unaligned =+ length sub > 1 && Set.size (Set.fromList offPositions) > 1+ positions =+ NonEmpty.toList $ position <$> sub+ position (Sub (Tree (Measured _ (MLayout _ mainPos _ _)) _)) =+ mainPos+ position (Leaf (Measured _ (MPane _ mainPos _))) =+ mainPos+ offPositions =+ NonEmpty.toList $ offPosition <$> sub+ offPosition (Sub (Tree (Measured _ (MLayout _ _ offPos _)) _)) =+ offPos+ offPosition (Leaf (Measured _ (MPane _ _ offPos))) =+ offPos++packTree ::+ (MonadDeepState s Views m, MonadFree TmuxThunk m) =>+ MeasureTree ->+ m ()+packTree =+ pack+ where+ pack (Tree (Measured _ (MLayout ref _ _ vertical)) sub) = do+ when needPos runPos+ mapMOf_ (each . Tree.subTree) pack sub+ traverse_ (resizeView vertical) sub+ where+ needPos = needPositioning sub+ runPos = do+ viewsLog $ "repositioning views" <+> pretty sub+ traverse_ (positionView vertical ref) (NonEmpty.reverse sub)++packWindow ::+ (MonadDeepState s Views m, MonadFree TmuxThunk m) =>+ WindowState ->+ m ()+packWindow (WindowState (Codec.Window _ width height) _ _ tree _) = do+ let measures = measureTree tree width height+ viewsLog $ "measured tree:" <> line <> pretty measures+ packTree measures
+ lib/Chiasma/Pane.hs view
@@ -0,0 +1,14 @@+module Chiasma.Pane where++import Chiasma.Data.Ident (Ident)+import Chiasma.Data.TmuxId (PaneId)+import qualified Chiasma.Data.View as Tmux (View(View))+import Chiasma.Data.Views (Views)+import qualified Chiasma.View as Views (insertPane)++addPane :: MonadDeepState s Views m => Ident -> m (Tmux.View PaneId)+addPane ident = do+ modify $ Views.insertPane pane+ return pane+ where+ pane = Tmux.View ident Nothing
+ lib/Chiasma/Prelude.hs view
@@ -0,0 +1,71 @@+{-# LANGUAGE NoImplicitPrelude #-}++module Chiasma.Prelude (+ module Cornea,+ module Data.Default,+ module Data.Foldable,+ module Relude,+ dbg,+ dbgs,+ dbgm,+ makeClassy,+ mapLeft,+ tuple,+ undefined,+ unit,+ unsafeLogAnd,+ unsafeLogS,+ unsafeLogSAnd,+ (<$$>),+) where++import Control.Lens (makeClassy)+import Cornea+import Data.Default (Default(def))+import Data.Either.Combinators (mapLeft)+import Data.Foldable (foldl, traverse_)+import Data.Functor.Syntax ((<$$>))+import GHC.Err (undefined)+import GHC.IO.Unsafe (unsafePerformIO)+import Relude hiding (Type, ask, asks, get, gets, hoistEither, hoistMaybe, local, modify, put, state, undefined)++dbg :: Monad m => Text -> m ()+dbg msg = do+ () <- return $ unsafePerformIO (putStrLn (toString msg))+ return ()++dbgs :: Monad m => Show a => a -> m ()+dbgs =+ dbg . show++dbgm :: Monad m => Show a => m a -> m a+dbgm ma = do+ a <- ma+ dbgs a+ return a++unit ::+ Applicative f =>+ f ()+unit =+ pure ()++tuple ::+ Applicative f =>+ f a ->+ f b ->+ f (a, b)+tuple fa fb =+ (,) <$> fa <*> fb++unsafeLogSAnd :: Show a => a -> b -> b+unsafeLogSAnd a b =+ unsafePerformIO $ print a >> return b++unsafeLogAnd :: Text -> b -> b+unsafeLogAnd a b =+ unsafePerformIO $ putStrLn (toString a) >> return b++unsafeLogS :: Show a => a -> a+unsafeLogS a =+ unsafePerformIO $ print a >> return a
+ lib/Chiasma/Render.hs view
@@ -0,0 +1,41 @@+module Chiasma.Render where++import qualified Chiasma.Codec.Data as Codec (Window(Window))+import Chiasma.Data.Ident (Ident, identText)+import Chiasma.Data.RenderError (RenderError)+import Chiasma.Data.TmuxThunk (TmuxThunk)+import Chiasma.Data.Views (Views)+import Chiasma.Pack (packWindow)+import Chiasma.Session (ensureSession, findOrCreateSession)+import Chiasma.Ui.Data.RenderableTree (RenderableTree)+import Chiasma.Ui.Data.View (ViewTree)+import Chiasma.View (viewsLog)+import Chiasma.Window (ensureView, ensureWindow, findOrCreateWindow, windowState)+import Control.Monad.Error.Class (MonadError)+import Control.Monad.Free.Class (MonadFree)+import Data.Text.Prettyprint.Doc (line, pretty)++renderTree ::+ (MonadDeepState s Views m, MonadFree TmuxThunk m) =>+ Ident ->+ Codec.Window ->+ RenderableTree ->+ m ()+renderTree windowIdent window tree = do+ viewsLog $ pretty ("rendering tree in window " <> identText windowIdent <> ":") <> line <> pretty tree+ wState <- windowState windowIdent window tree+ packWindow wState++render ::+ (MonadDeepState s Views m, MonadFree TmuxThunk m, MonadError RenderError m) =>+ FilePath ->+ Ident ->+ Ident ->+ ViewTree ->+ m ()+render cwd sessionIdent windowIdent tree = do+ initialSession <- findOrCreateSession sessionIdent+ initialWindow <- findOrCreateWindow windowIdent+ (sid, newSessionWid) <- ensureSession initialSession initialWindow+ window@(Codec.Window windowId _ _) <- ensureWindow sid initialWindow newSessionWid tree+ traverse_ (renderTree windowIdent window) =<< ensureView cwd windowId tree
+ lib/Chiasma/Session.hs view
@@ -0,0 +1,49 @@+{-# LANGUAGE FlexibleContexts #-}++module Chiasma.Session where++import Control.Monad.Free.Class (MonadFree)++import qualified Chiasma.Codec.Data as Codec (Session(Session), Window(Window))+import Chiasma.Command.Session (existingSessionId, newSession)+import Chiasma.Command.Window (newSessionWindow)+import Chiasma.Data.Ident (Ident)+import Chiasma.Data.TmuxId (SessionId, WindowId)+import Chiasma.Data.TmuxThunk (TmuxThunk)+import qualified Chiasma.Data.View as Tmux (View(viewId, viewIdent), setViewId)+import Chiasma.Data.Views (Views)+import Chiasma.View (findOrCreateView, viewsLogS)+import qualified Chiasma.View as Views (insertSession, session, updateSession, updateWindow)++findOrCreateSession ::+ MonadDeepState s Views m =>+ Ident ->+ m (Tmux.View SessionId)+findOrCreateSession =+ findOrCreateView Views.session Views.insertSession++spawnSession ::+ MonadDeepState s Views m =>+ MonadFree TmuxThunk m =>+ Tmux.View SessionId ->+ Tmux.View WindowId ->+ m (SessionId, WindowId)+spawnSession session' window = do+ Codec.Session sid <- newSession (Tmux.viewIdent session')+ modify $ Views.updateSession $ Tmux.setViewId sid session'+ Codec.Window wid _ _ <- newSessionWindow sid+ modify $ Views.updateWindow $ Tmux.setViewId wid window+ viewsLogS $ "spawned session " <> show session' <> " with id " <> show sid <> " and window id " <> show wid+ return (sid, wid)++ensureSession ::+ MonadDeepState s Views m =>+ MonadFree TmuxThunk m =>+ Tmux.View SessionId ->+ Tmux.View WindowId ->+ m (SessionId, Maybe WindowId)+ensureSession session' window = do+ existing <- join <$> traverse existingSessionId (Tmux.viewId session')+ case existing of+ Just sid -> return (sid, Nothing)+ Nothing -> second Just <$> spawnSession session' window
lib/Chiasma/Test/File.hs view
@@ -4,15 +4,14 @@ fixture, ) where -import Control.Monad.IO.Class (liftIO, MonadIO) import System.Directory (canonicalizePath, createDirectoryIfMissing, removePathForcibly) import System.FilePath ((</>)) -testDir :: String -> IO FilePath-testDir prefix = canonicalizePath $ "test" </> prefix+testDir :: Text -> IO FilePath+testDir prefix = canonicalizePath $ "test" </> toString prefix -- raises exception if cwd is not the package root so we don't damage anything-tempDirIO :: String -> FilePath -> IO FilePath+tempDirIO :: Text -> FilePath -> IO FilePath tempDirIO prefix path = do base <- testDir prefix let dir = base </> "temp"@@ -22,11 +21,11 @@ createDirectoryIfMissing True absPath return absPath -tempDir :: MonadIO m => String -> FilePath -> m FilePath+tempDir :: MonadIO m => Text -> FilePath -> m FilePath tempDir prefix path = liftIO $ tempDirIO prefix path -fixture :: MonadIO m => String -> FilePath -> m FilePath+fixture :: MonadIO m => Text -> FilePath -> m FilePath fixture prefix path = do base <- liftIO $ testDir prefix return $ base </> "fixtures" </> path
+ lib/Chiasma/Test/Screenshot.hs view
@@ -0,0 +1,67 @@+module Chiasma.Test.Screenshot where++import Control.Monad.Free.Class (MonadFree)+import qualified Data.ByteString as ByteString (writeFile)+import qualified Data.Text as Text (lines, unlines)+import qualified Data.Text.Encoding as Text (encodeUtf8)+import System.FilePath (takeDirectory, (</>))+import UnliftIO.Directory (createDirectoryIfMissing, doesFileExist)++import Chiasma.Command.Pane (capturePane)+import Chiasma.Data.TmuxId (PaneId(PaneId))+import Chiasma.Data.TmuxThunk (TmuxThunk)++loadScreenshot :: MonadIO m => FilePath -> m (Maybe Text)+loadScreenshot path =+ ifM (doesFileExist path) (Just . toText <$> liftIO (readFile path)) (pure Nothing)++storeScreenshot :: MonadIO m => FilePath -> [Text] -> m ()+storeScreenshot path text = do+ createDirectoryIfMissing True (takeDirectory path)+ liftIO $ ByteString.writeFile path (Text.encodeUtf8 . Text.unlines $ text)++takeScreenshot ::+ MonadFree TmuxThunk m =>+ MonadIO m =>+ Int ->+ m [Text]+takeScreenshot =+ capturePane . PaneId++recordScreenshot ::+ MonadFree TmuxThunk m =>+ MonadIO m =>+ FilePath ->+ Int ->+ m ()+recordScreenshot path paneId = do+ current <- takeScreenshot paneId+ storeScreenshot path current++testScreenshot ::+ MonadFree TmuxThunk m =>+ MonadIO m =>+ FilePath ->+ Int ->+ m (Maybe ([Text], [Text]))+testScreenshot path pane = do+ current <- takeScreenshot pane+ loadScreenshot path >>= check current+ where+ check current (Just existing) =+ return $ Just (current, Text.lines existing)+ check current Nothing =+ Nothing <$ storeScreenshot path current++screenshot ::+ MonadFree TmuxThunk m =>+ MonadIO m =>+ Bool ->+ FilePath ->+ Text ->+ Int ->+ m (Maybe ([Text], [Text]))+screenshot record storage name paneId =+ if record then Nothing <$ recordScreenshot path paneId else testScreenshot path paneId+ where+ path = storage </> toString name
lib/Chiasma/Test/Tmux.hs view
@@ -1,71 +1,121 @@-module Chiasma.Test.Tmux(- withTestTmux,- tmuxSpec,-) where+module Chiasma.Test.Tmux where -import GHC.Real (fromIntegral)-import GHC.IO.Handle (Handle)+import Chiasma.Data.TmuxError (TmuxError)+import Chiasma.Monad.Stream (runTmux)+import qualified Chiasma.Monad.Tmux as Tmux (write)+import Chiasma.Native.Api (TmuxNative(..))+import Control.Concurrent (threadDelay)+import System.Directory (doesFileExist) import System.FilePath ((</>))-import System.Posix.Pty (Pty, resizePty, createPty)-import System.Posix.Terminal (openPseudoTerminal) import System.Posix.IO (fdToHandle)-import qualified System.Posix.Signals as Signal (signalProcess, killProcess)+import System.Posix.Pty (Pty, createPty, resizePty)+import qualified System.Posix.Signals as Signal (killProcess, signalProcess)+import System.Posix.Terminal (openPseudoTerminal) import System.Process (getPid) import System.Process.Typed (- ProcessConfig, Process,- withProcess,+ ProcessConfig,+ StreamSpec, proc,+ setStderr, setStdin, setStdout,- setStderr,- useHandleClose, unsafeProcessHandle,+ useHandleClose,+ withProcessWait, )-import UnliftIO (finally)+import UnliftIO (finally, throwString)+import UnliftIO.Exception (tryAny) import UnliftIO.Temporary (withSystemTempDirectory)-import Chiasma.Native.Api (TmuxNative(..))+ import Chiasma.Test.File (fixture) data Terminal = Terminal Handle Pty +data TmuxTestConf =+ TmuxTestConf {+ ttcWidth :: Int,+ ttcHeight :: Int,+ ttcFontSize :: Int,+ ttcGui :: Bool+ }+ deriving (Eq, Show)++instance Default TmuxTestConf where+ def = TmuxTestConf 240 61 18 True++usleep :: MonadIO f => Double -> f ()+usleep =+ liftIO . threadDelay . round++sleep :: MonadIO f => Double -> f ()+sleep seconds =+ usleep $ seconds * 1e6+ unsafeTerminal :: IO Terminal unsafeTerminal = do (_, slave) <- openPseudoTerminal mayPty <- createPty slave handle <- fdToHandle slave- pty <- maybe (error "couldn't spawn pty") return mayPty+ pty <- maybe (throwString "couldn't spawn pty") return mayPty return $ Terminal handle pty -testTmuxProcessConfig :: FilePath -> FilePath -> Terminal -> IO (ProcessConfig () () ())-testTmuxProcessConfig socket confFile (Terminal handle pty) = do- resizePty pty (1000, 1000)- let stream = useHandleClose handle- let stdio = setStdin stream . setStdout stream . setStderr stream- return $ stdio $ proc "tmux" ["-S", socket, "-f", confFile]+urxvtArgs :: Int -> Int -> Int -> [Text]+urxvtArgs width height fontSize =+ ["-geometry", show width <> "x" <> show height, "-fn", "xft:monospace:size=" <> show fontSize, "-e", "tmux"] +testTmuxProcessConfig :: TmuxTestConf -> FilePath -> FilePath -> Terminal -> IO (ProcessConfig () () ())+testTmuxProcessConfig (TmuxTestConf width height fontSize gui) socket confFile (Terminal handle pty) = do+ confFileExists <- doesFileExist confFile+ resizePty pty (width, height)+ let+ stream :: StreamSpec st ()+ stream = useHandleClose handle+ stdio = setStdin stream . setStdout stream . setStderr stream+ tmuxArgs = ["-S", toText socket, "-f", toText confFileArg]+ confFileArg = if confFileExists then confFile else "/dev/null"+ prc =+ if gui+ then proc "urxvt" (toString <$> urxvtArgs width height fontSize ++ tmuxArgs)+ else proc "tmux" (toString <$> tmuxArgs)+ return $ stdio prc+ killPid :: Integral a => a -> IO () killPid =- Signal.signalProcess Signal.killProcess . fromIntegral+ void . tryAny . Signal.signalProcess Signal.killProcess . fromIntegral -killProcess :: Process () () () -> IO ()-killProcess prc = do+killProcess :: TmuxNative -> Process () () () -> IO ()+killProcess api prc = do+ _ <- runExceptT @TmuxError $ runTmux api $ Tmux.write "kill-server" [] let handle = unsafeProcessHandle prc mayPid <- getPid handle maybe (return ()) killPid mayPid +-- FIXME find a way to wait for tmux deterministically instead of sleeping+-- if the first tmux control mode process from a TmuxProg runs before urxvt has started the server,+-- it will not use the test tmux.conf+-- maybe start tmux first, then urxvt? runAndKillTmux :: (TmuxNative -> IO a) -> TmuxNative -> Process () () () -> IO a-runAndKillTmux thunk api prc =- finally (thunk api) (killProcess prc)+runAndKillTmux thunk api prc = do+ sleep 0.2+ finally (thunk api) (killProcess api prc) -withTestTmux :: (TmuxNative -> IO a) -> FilePath -> IO a-withTestTmux thunk tempDir = do+withTestTmux :: TmuxTestConf -> (TmuxNative -> IO a) -> FilePath -> IO a+withTestTmux tConf thunk tempDir = do let socket = tempDir </> "tmux_socket" conf <- fixture "u" "tmux.conf" terminal <- unsafeTerminal- pc <- testTmuxProcessConfig socket conf terminal- withProcess pc $ runAndKillTmux thunk (TmuxNative socket)+ pc <- testTmuxProcessConfig tConf socket conf terminal+ withProcessWait pc $ runAndKillTmux thunk (TmuxNative $ Just socket) +tmuxSpec' :: TmuxTestConf -> (TmuxNative -> IO a) -> IO a+tmuxSpec' conf thunk =+ withSystemTempDirectory "chiasma-test" $ withTestTmux conf thunk+ tmuxSpec :: (TmuxNative -> IO a) -> IO a-tmuxSpec thunk =- withSystemTempDirectory "chiasma-test" $ withTestTmux thunk+tmuxSpec =+ tmuxSpec' def { ttcGui = False }++tmuxGuiSpec :: (TmuxNative -> IO a) -> IO a+tmuxGuiSpec =+ tmuxSpec' def
+ lib/Chiasma/Ui/Data/Measure.hs view
@@ -0,0 +1,52 @@+module Chiasma.Ui.Data.Measure where++import Chiasma.Data.TmuxId (PaneId(..))+import Data.Text.Prettyprint.Doc (Pretty(..), (<+>))++import Chiasma.Ui.Data.Tree (NNode, NTree)++data MPane =+ MPane {+ _paneId :: PaneId,+ _mainPosition :: Int,+ _offPosition :: Int+ }+ deriving (Eq, Show)++makeClassy ''MPane++data MLayout =+ MLayout {+ _reference :: PaneId,+ _lMainPosition :: Int,+ _lOffPosition :: Int,+ _vertical :: Bool+ }+ deriving (Eq, Show)++makeClassy ''MLayout++data Measured a =+ Measured {+ _size :: Int,+ _view :: a+ }+ deriving (Eq, Show)++makeClassy ''Measured++type MeasureTree = NTree (Measured MLayout) (Measured MPane)+type MeasureTreeSub = NNode (Measured MLayout) (Measured MPane)++instance Pretty MLayout where+ pretty (MLayout (PaneId refId) mainPos offPos vertical') =+ "l –" <+> "ref:" <+> pretty refId <+> "pos:" <+> pretty mainPos <+> "(" <> pretty offPos <> ")" <+>+ if vertical' then "v" else "h"++instance Pretty MPane where+ pretty (MPane (PaneId paneId') mainPos offPos) =+ "p –" <+> pretty paneId' <+> "pos:" <+> pretty mainPos <+> "(" <> pretty offPos <> ")"++instance Pretty a => Pretty (Measured a) where+ pretty (Measured size' a) =+ pretty a <+> "size:" <+> pretty size'
+ lib/Chiasma/Ui/Data/RenderableTree.hs view
@@ -0,0 +1,54 @@+module Chiasma.Ui.Data.RenderableTree where++import Data.Text.Prettyprint.Doc (Doc, Pretty(..), emptyDoc, space, (<+>))++import Chiasma.Data.TmuxId (PaneId(..))+import Chiasma.Ui.Data.Tree (NNode, NTree)+import Chiasma.Ui.Data.ViewGeometry (ViewGeometry(ViewGeometry))+import Chiasma.Ui.Data.ViewState (ViewState)++data RLayout =+ RLayout {+ _ref :: RPane,+ _vertical :: Bool+ }+ deriving (Eq, Show)++data RPane =+ RPane {+ _id :: PaneId,+ _top :: Int,+ _left :: Int+ }+ deriving (Eq, Show)++data Renderable a =+ Renderable {+ _state :: ViewState,+ _geometry :: ViewGeometry,+ _view :: a+ }+ deriving (Eq, Show)++type RenderableLayout = Renderable RLayout+type RenderablePane = Renderable RPane+type RenderableTree = NTree RenderableLayout RenderablePane+type RenderableNode = NNode RenderableLayout RenderablePane++instance Pretty RLayout where+ pretty (RLayout (RPane (PaneId refId) _ _) vertical) =+ "l –" <+> "ref:" <+> pretty refId <+> "pos:" <+> if vertical then "v" else "h"++instance Pretty RPane where+ pretty (RPane (PaneId paneId) top left) =+ "p –" <+> pretty paneId <+> pretty top <+> pretty left++mayPretty :: Text -> Maybe Float -> Doc a+mayPretty prefix (Just a) =+ space <> pretty (prefix <> ":") <+> pretty a+mayPretty _ Nothing =+ emptyDoc++instance Pretty a => Pretty (Renderable a) where+ pretty (Renderable _ (ViewGeometry minSize maxSize fixedSize _ _ _) a) =+ pretty a <> mayPretty "min" minSize <> mayPretty "max" maxSize <> mayPretty "fixed" fixedSize
+ lib/Chiasma/Ui/Data/Tree.hs view
@@ -0,0 +1,45 @@+{-# LANGUAGE TemplateHaskell #-}++module Chiasma.Ui.Data.Tree where++import Data.Text.Prettyprint.Doc (Pretty(..), vsep, nest)++data Tree f l p =+ Tree {+ _treeData :: l,+ _forest :: f (Node f l p)+ }++deriving instance (Eq l, Eq p) => Eq (Tree [] l p)+deriving instance (Show l, Show p) => Show (Tree [] l p)++deriving instance (Eq l, Eq p) => Eq (Tree NonEmpty l p)+deriving instance (Show l, Show p) => Show (Tree NonEmpty l p)++data Node f l p =+ Sub { _subTree :: Tree f l p }+ |+ Leaf { _leafData :: p }++makeClassy ''Tree+makeClassy ''Node++deriving instance (Eq l, Eq p) => Eq (Node [] l p)+deriving instance (Show l, Show p) => Show (Node [] l p)++deriving instance (Eq l, Eq p) => Eq (Node NonEmpty l p)+deriving instance (Show l, Show p) => Show (Node NonEmpty l p)++type LTree l p = Tree [] l p+type LNode l p = Node [] l p++type NTree l p = Tree NonEmpty l p+type NNode l p = Node NonEmpty l p++instance (Foldable f, Pretty l, Pretty p) => Pretty (Tree f l p) where+ pretty (Tree l sub) =+ nest 2 $ vsep $ pretty l : (pretty <$> toList sub)++instance (Foldable f, Pretty l, Pretty p) => Pretty (Node f l p) where+ pretty (Sub tree') = pretty tree'+ pretty (Leaf a) = pretty a
+ lib/Chiasma/Ui/Data/TreeModError.hs view
@@ -0,0 +1,22 @@+module Chiasma.Ui.Data.TreeModError where++import Chiasma.Data.Ident (Ident)+import Chiasma.Ui.Data.View (LayoutView, PaneView)++data TreeModError =+ PaneExists PaneView+ |+ LayoutExists LayoutView+ |+ PaneMissing Ident+ |+ LayoutMissing Ident+ |+ AmbiguousPane Ident Int+ |+ AmbiguousLayout Ident Int+ |+ NoTrees+ deriving (Eq, Show)++deepPrisms ''TreeModError
+ lib/Chiasma/Ui/Data/View.hs view
@@ -0,0 +1,151 @@+module Chiasma.Ui.Data.View where++import Chiasma.Data.Ident (Ident, Identifiable(..))+import Control.Lens (Index, IxValue, Ixed(ix), makeClassy_)+import Control.Lens.Plated (Plated)+import Data.Data (Data)+import Data.Text.Prettyprint.Doc (Doc, Pretty(..), emptyDoc, nest, space, vsep, (<+>))+import Prelude hiding (state)++import Chiasma.Ui.Data.ViewGeometry (ViewGeometry)+import Chiasma.Ui.Data.ViewState (ViewState(ViewState))+import Chiasma.Ui.Lens.Ident (matchIdentP)++data Pane =+ Pane {+ _open :: Bool,+ _pin :: Bool,+ _cwd :: Maybe FilePath+ }+ deriving (Eq, Show, Data, Generic)++makeClassy ''Pane++instance Default Pane where+ def = Pane False False Nothing++newtype Layout =+ Layout {+ vertical :: Bool+ }+ deriving (Eq, Show, Data, Generic)++makeClassy_ ''Layout++instance Default Layout where+ def = Layout True++data View a =+ View {+ _ident :: Ident,+ _state :: ViewState,+ _geometry :: ViewGeometry,+ _extra :: a+ }+ deriving (Eq, Show, Data, Generic)++makeClassy ''View++instance Default a => Default (View a) where+ def = View def def def def++type PaneView = View Pane+type LayoutView = View Layout++instance Pretty Layout where+ pretty (Layout vertical) =+ if vertical then "▤" else "▥"++instance Pretty Pane where+ pretty (Pane open' pin' _) =+ (if open' then "🔓" else "🔒") <+> (if pin' then "📌" else emptyDoc)++prettyView :: Doc a -> Ident -> ViewState -> ViewGeometry -> Doc a+prettyView sym ident' (ViewState minimized) geo =+ sym <+> pretty ident' <+> "⎸" <+> (if minimized then "▂" <> space else emptyDoc) <> pretty geo++instance Pretty (View Pane) where+ pretty (View ident' st geo a) =+ prettyView "◳" ident' st geo <> pretty a++instance Pretty (View Layout) where+ pretty (View ident' st geo a) =+ prettyView (pretty a) ident' st geo++consPane :: Ident -> PaneView+consPane ident' = View ident' (ViewState False) def (Pane False False Nothing)++consLayoutAs :: Bool -> Ident -> LayoutView+consLayoutAs vert ident' = View ident' (ViewState False) def (Layout vert)++consLayout :: Ident -> LayoutView+consLayout =+ consLayoutAs False++consLayoutVertical :: Ident -> LayoutView+consLayoutVertical =+ consLayoutAs True++instance Identifiable (View a) where+ identify = _ident++-- split in two so there can be no lone leaves (panes without layout) as type 'Tree'+data Tree l p =+ Tree {+ treeData :: l,+ treeSubs :: [TreeSub l p]+ }+ deriving (Eq, Show, Data, Generic)++instance Bifunctor Tree where+ first f (Tree l sub) = Tree (f l) (fmap (first f) sub)++ second f (Tree l sub) =+ Tree l (fmap (second f) sub)++instance Bifoldable Tree where+ bifoldMap fl fr (Tree l sub) = mappend (fl l) (foldMap (bifoldMap fl fr) sub)++data TreeSub l p =+ TreeNode { _subTree :: Tree l p }+ |+ TreeLeaf { _leafData :: p }+ deriving (Eq, Show, Data, Generic)++instance Bifunctor TreeSub where+ first f (TreeNode t) = TreeNode (first f t)+ first _ (TreeLeaf p) = TreeLeaf p++ second f (TreeNode t) = TreeNode (second f t)+ second f (TreeLeaf p) = TreeLeaf (f p)++instance Bifoldable TreeSub where+ bifoldMap fl fr (TreeNode t) = bifoldMap fl fr t+ bifoldMap _ fr (TreeLeaf p) = fr p++instance (Data l, Data p) => Plated (Tree l p)++makeClassy_ ''Tree+makeClassy ''TreeSub++type ViewTree = Tree LayoutView PaneView+type ViewTreeSub = TreeSub LayoutView PaneView++instance Identifiable l => Identifiable (Tree l p) where+ identify (Tree l _) = identify l++type instance Index (Tree _ _) = Ident+type instance IxValue (Tree l p) = Tree l p++instance Identifiable l => Ixed (Tree l p) where+ ix = matchIdentP++instance (Pretty l, Pretty p) => Pretty (TreeSub l p) where+ pretty (TreeNode a) =+ pretty a+ pretty (TreeLeaf a) =+ pretty a++instance (Pretty l, Pretty p) => Pretty (Tree l p) where+ pretty (Tree l sub) =+ nest 2 . vsep $ pretty l : (pretty <$> sub)
+ lib/Chiasma/Ui/Data/ViewGeometry.hs view
@@ -0,0 +1,27 @@+{-# LANGUAGE DeriveAnyClass #-}++module Chiasma.Ui.Data.ViewGeometry where++import Data.Data (Data)+import Data.Text.Prettyprint.Doc (Doc, Pretty(..), emptyDoc, space, (<+>))++data ViewGeometry =+ ViewGeometry {+ minSize :: Maybe Float,+ maxSize :: Maybe Float,+ fixedSize :: Maybe Float,+ minimizedSize :: Maybe Float,+ weight :: Maybe Float,+ position :: Maybe Float+ }+ deriving (Eq, Show, Data, Generic, Default)++mayPretty :: Text -> Maybe Float -> Doc a+mayPretty prefix (Just a) =+ space <> pretty prefix <> ":" <+> pretty a+mayPretty _ Nothing =+ emptyDoc++instance Pretty ViewGeometry where+ pretty (ViewGeometry minSize maxSize fixedSize _ _ _) =+ foldl @[] (<>) emptyDoc (uncurry mayPretty <$> [("min", minSize), ("max", maxSize), ("fixed", fixedSize)])
+ lib/Chiasma/Ui/Data/ViewState.hs view
@@ -0,0 +1,12 @@+module Chiasma.Ui.Data.ViewState where++import Data.Data (Data)++newtype ViewState =+ ViewState {+ minimized :: Bool+ }+ deriving (Eq, Show, Data, Generic)++instance Default ViewState where+ def = ViewState False
+ lib/Chiasma/Ui/Lens/Ident.hs view
@@ -0,0 +1,23 @@+{-# LANGUAGE RankNTypes #-}++module Chiasma.Ui.Lens.Ident(+ matchIdent,+ matchIdentL,+ matchIdentP,+) where++import Control.Lens (Traversal', Prism', filtered, each, prism)+import Chiasma.Data.Ident (Ident, Identifiable(..), sameIdent)++matchIdent :: Identifiable a => Ident -> Traversal' a a+matchIdent = filtered . sameIdent++matchIdentL :: Identifiable a => Ident -> Traversal' [a] a+matchIdentL ident = each . matchIdent ident++identEither :: Identifiable a => Ident -> a -> Either a a+identEither target a =+ if sameIdent target a then Right a else Left a++matchIdentP :: Identifiable a => Ident -> Prism' a a+matchIdentP ident = prism id (identEither ident)
+ lib/Chiasma/Ui/Measure.hs view
@@ -0,0 +1,76 @@+module Chiasma.Ui.Measure where++import qualified Data.List.NonEmpty as NonEmpty (zip)+import GHC.Float (int2Float)++import Chiasma.Data.Maybe (orElse)+import Chiasma.Ui.Data.Measure (MLayout(..), MPane(..), MeasureTree, MeasureTreeSub, Measured(..))+import Chiasma.Ui.Data.RenderableTree (RLayout(..), RPane(..), Renderable(..), RenderableNode, RenderableTree)+import Chiasma.Ui.Data.Tree (Tree(..))+import qualified Chiasma.Ui.Data.Tree as Tree (Node(..))+import Chiasma.Ui.Data.ViewGeometry (ViewGeometry(minSize, maxSize, fixedSize))+import Chiasma.Ui.Data.ViewState (ViewState(ViewState))+import Chiasma.Ui.Measure.Balance (balanceSizes)+import Chiasma.Ui.Measure.Weights (viewWeights)++minimizedSizeOrDefault :: ViewGeometry -> Float+minimizedSizeOrDefault = fromMaybe 2 . minSize++effectiveFixedSize :: ViewState -> ViewGeometry -> Maybe Float+effectiveFixedSize (ViewState minimized) viewGeom =+ if minimized then Just (minimizedSizeOrDefault viewGeom) else fixedSize viewGeom++actualSize :: (ViewGeometry -> Maybe Float) -> ViewState -> ViewGeometry -> Maybe Float+actualSize getter viewState viewGeom =+ orElse (getter viewGeom) (effectiveFixedSize viewState viewGeom)++actualMinSizes :: NonEmpty (ViewState, ViewGeometry) -> NonEmpty Float+actualMinSizes =+ fmap (fromMaybe 0.0 . uncurry (actualSize minSize))++actualMaxSizes :: NonEmpty (ViewState, ViewGeometry) -> NonEmpty (Maybe Float)+actualMaxSizes =+ fmap (uncurry $ actualSize maxSize)++isMinimized :: ViewState -> ViewGeometry -> Bool+isMinimized (ViewState minimized) _ = minimized++subMeasureData :: RenderableNode -> (ViewState, ViewGeometry)+subMeasureData (Tree.Sub (Tree (Renderable s g _) _)) = (s, g)+subMeasureData (Tree.Leaf (Renderable s g _)) = (s, g)++measureLayoutViews :: Float -> NonEmpty RenderableNode -> NonEmpty Int+measureLayoutViews total views =+ balanceSizes minSizes maxSizes weights minimized cells+ where+ measureData = fmap subMeasureData views+ paneSpacers = int2Float (length views) - 1.0+ cells = total - paneSpacers+ sizesInCells s = if s > 1 then s else s * cells+ minSizes = fmap sizesInCells (actualMinSizes measureData)+ maxSizes = fmap (fmap sizesInCells) (actualMaxSizes measureData)+ minimized = fmap (uncurry isMinimized) measureData+ weights = viewWeights measureData++measureSub :: Int -> Int -> Bool -> RenderableNode -> Int -> MeasureTreeSub+measureSub width height vertical (Tree.Sub tree) size =+ Tree.Sub $ measureLayout tree newWidth newHeight vertical+ where+ (newWidth, newHeight) = if vertical then (width, size) else (size, height)+measureSub _ _ vertical (Tree.Leaf (Renderable _ _ (RPane paneId top left))) size =+ Tree.Leaf (Measured size (MPane paneId (if vertical then top else left) (if vertical then left else top)))++measureLayout :: RenderableTree -> Int -> Int -> Bool -> MeasureTree+measureLayout (Tree (Renderable _ _ (RLayout (RPane refId refTop refLeft) vertical)) sub) width height parentVertical =+ Tree (Measured sizeInParent (MLayout refId mainPos offPos vertical)) measuredSub+ where+ sizeInParent = if parentVertical then height else width+ mainPos = if parentVertical then refTop else refLeft+ offPos = if parentVertical then refLeft else refTop+ subTotalSize = if vertical then height else width+ sizes = measureLayoutViews (int2Float subTotalSize) sub+ measuredSub = uncurry (measureSub width height vertical) <$> NonEmpty.zip sub sizes++measureTree :: RenderableTree -> Int -> Int -> MeasureTree+measureTree tree width height =+ measureLayout tree width height False
+ lib/Chiasma/Ui/Measure/Balance.hs view
@@ -0,0 +1,157 @@+module Chiasma.Ui.Measure.Balance where++import Data.List (zipWith3)+import qualified Data.List.NonEmpty as NonEmpty (+ filter,+ toList,+ zip,+ zipWith,+ )+import GHC.Float (float2Int, int2Float)+import GHC.Float.RealFracMethods (floorFloatInt)++import Chiasma.Ui.Measure.Weights (+ amendAndNormalizeWeights,+ normalizeWeights,+ )++zipWith3NE :: (a -> b -> c -> d) -> NonEmpty a -> NonEmpty b -> NonEmpty c -> NonEmpty d+zipWith3NE z ~(a :| as) ~(b :| bs) ~(c :| cs) =+ z a b c :| zipWith3 z as bs cs++data Balance =+ Balance {+ balanceMin :: NonEmpty Float,+ balanceMax :: NonEmpty (Maybe Float),+ balanceWeights :: NonEmpty Float,+ balanceMinimized :: NonEmpty Bool,+ balanceTotal :: Float+ }++reverseWeights :: NonEmpty Float -> NonEmpty Float+reverseWeights weights =+ if norm > 0 then fmap (/ norm) r else r+ where+ r = fmap (1 -) weights+ norm = sum r++cutSizes :: Balance -> NonEmpty Float+cutSizes (Balance min' _ weights _ total) =+ fmap addDist cut+ where+ surplus = sum min' - total+ dist = fmap (surplus *) (reverseWeights weights)+ cut = fmap (uncurry (-)) (NonEmpty.zip min' dist)+ negOrZero a = if a < 0 then a else 0+ neg = fmap negOrZero cut+ negTotal = sum neg+ negCount = length (NonEmpty.filter (< 0) neg)+ dist2 = negTotal / int2Float (length min' - negCount)+ addDist a = if a < 0 then 0 else a + dist2++distributeOnUnbounded :: Balance -> NonEmpty Float+distributeOnUnbounded (Balance min' max' weights _ total) =+ NonEmpty.zipWith addWeights initial newWeights+ where+ initial = NonEmpty.zipWith fromMaybe min' max'+ newWeights = normalizeWeights $ NonEmpty.zipWith weightOrZeroIfMax weights max'+ addWeights i w = i + (w * surplus)+ surplus = total - sum initial+ weightOrZeroIfMax w = maybe w (const 0)++weightsWithoutMinimized :: Balance -> NonEmpty Float+weightsWithoutMinimized (Balance _ _ weights minimized _) =+ normalizeWeights zeroIfMinimizedWeights+ where+ zeroIfMinimizedWeights = NonEmpty.zipWith zeroIfMinimized weights minimized+ zeroIfMinimized w m = if m then 0 else w++trimWeights :: NonEmpty Bool -> NonEmpty Float -> NonEmpty Float+trimWeights unsat withoutMinimized =+ amendAndNormalizeWeights onlyUnsat+ where+ onlyUnsat = NonEmpty.zipWith weightIfUnsat unsat withoutMinimized+ weightIfUnsat s w = if s then Just w else Nothing++distRest :: Balance -> Float -> NonEmpty Float -> NonEmpty Float -> NonEmpty Float+distRest balance rest sizes effectiveMax =+ NonEmpty.zipWith addRestWeights sizes restW+ where+ unsat = NonEmpty.zipWith (>) effectiveMax sizes+ unsatLeft = or unsat+ withoutMinimized = weightsWithoutMinimized balance+ restW =+ if unsatLeft+ then trimWeights unsat withoutMinimized+ else withoutMinimized+ addRestWeights s w = s + w * rest++saturate :: NonEmpty Float -> NonEmpty Float -> NonEmpty Float -> Float -> NonEmpty Float+saturate initial max' initialWeights total =+ loop initial initialWeights+ where+ loop current weights =+ if new == current || rest <= 0 then new else loop new newWeights+ where+ rest = total - sum current+ unsatWeights = zipWith3NE (\s m w -> if s >= m then 0 else w) current max' weights+ newWeights = normalizeWeights unsatWeights+ new = zipWith3NE (\l h w -> min (l + w * rest) h) current max' newWeights++distributeOnAll :: Balance -> NonEmpty Float+distributeOnAll balance@(Balance min' max' weights _ total) =+ if rest <= 0 then sizes else distRest balance rest sizes effectiveMax+ where+ effectiveMax = fromMaybe 1e6 <$> max'+ sizes = saturate min' effectiveMax weights total+ rest = total - sum sizes++hasUnbounded :: Balance -> Bool+hasUnbounded =+ any isNothing . balanceMax++distributeSizes :: Balance -> NonEmpty Float+distributeSizes balance =+ handler balance+ where+ handler =+ if (maxTotal < balanceTotal balance) && hasUnbounded balance+ then distributeOnUnbounded+ else distributeOnAll+ maxTotal = sum (catMaybes $ NonEmpty.toList $ balanceMax balance)++roundSizes :: NonEmpty Float -> NonEmpty Int+roundSizes (head' :| tail') =+ roundedHead + (float2Int surplus) :| roundedTail+ where+ (surplus, roundedTail) = mapAccumL folder diff0 tail'+ (roundedHead, diff0) = diff head'+ folder z a =+ (z + z1, a1)+ where+ (a1, z1) = diff a+ diff a = (floorFloatInt a, a - int2Float (floor a))++ensureMinimum2 :: NonEmpty Float -> NonEmpty Float+ensureMinimum2 sizes =+ choose <$> positives+ where+ positive = max 0+ positives = positive <$> sizes+ positivesCount = length $ NonEmpty.filter (>= 2) sizes+ unders = amountUnderTwo <$> positives+ sub = sum unders / int2Float positivesCount+ amountUnderTwo a = positive (2 - a)+ choose a = max 2 (a - sub)++rectifySizes :: NonEmpty Float -> NonEmpty Int+rectifySizes =+ roundSizes . ensureMinimum2++-- FIXME need to round manually, keeping track of the surplus, in order to achieve determinism+balanceSizes :: NonEmpty Float -> NonEmpty (Maybe Float) -> NonEmpty Float -> NonEmpty Bool -> Float -> NonEmpty Int+balanceSizes minSizes maxSizes weights minimized total =+ rectifySizes (fit balance)+ where+ fit = if sum minSizes > total then cutSizes else distributeSizes+ balance = Balance minSizes maxSizes weights minimized total
+ lib/Chiasma/Ui/Measure/Weights.hs view
@@ -0,0 +1,38 @@+module Chiasma.Ui.Measure.Weights(+ viewWeights,+ normalizeWeights,+ amendAndNormalizeWeights,+) where++import qualified Data.List.NonEmpty as NonEmpty (toList, filter)+import GHC.Float (int2Float)++import Chiasma.Ui.Data.ViewGeometry (ViewGeometry(ViewGeometry))+import Chiasma.Ui.Data.ViewState (ViewState(ViewState))++effectiveWeight :: ViewState -> ViewGeometry -> Maybe Float+effectiveWeight (ViewState minimized) (ViewGeometry _ _ fixedSize _ weight _) =+ if isJust fixedSize || minimized then Just 0 else weight++amendWeights :: NonEmpty (Maybe Float) -> NonEmpty Float+amendWeights weights =+ fmap (fromMaybe emptyWeight) weights+ where+ total = sum (catMaybes $ NonEmpty.toList weights)+ normTotal = if total == 0 then 1 else total+ empties = length (NonEmpty.filter isNothing weights)+ normEmpties = if empties == 0 then 1 else empties+ emptyWeight = normTotal / int2Float normEmpties++normalizeWeights :: NonEmpty Float -> NonEmpty Float+normalizeWeights weights =+ fmap (/ normTotal) weights+ where+ total = sum weights+ normTotal = if total == 0 then 1 else total++amendAndNormalizeWeights :: NonEmpty (Maybe Float) -> NonEmpty Float+amendAndNormalizeWeights = normalizeWeights . amendWeights++viewWeights :: NonEmpty (ViewState, ViewGeometry) -> NonEmpty Float+viewWeights = amendAndNormalizeWeights . fmap (uncurry effectiveWeight)
+ lib/Chiasma/Ui/Pane.hs view
@@ -0,0 +1,17 @@+module Chiasma.Ui.Pane(+ paneToggleOpen,+ paneSetOpen,+) where++import Chiasma.Ui.Data.View (View(View), PaneView, Pane(Pane))+import Chiasma.Ui.Data.ViewState (ViewState(ViewState))++paneToggleOpen :: PaneView -> PaneView+paneToggleOpen (View i s g (Pane False pin cwd)) =+ View i s g (Pane True pin cwd)+paneToggleOpen (View i (ViewState m) g e) =+ View i (ViewState (not m)) g e++paneSetOpen :: PaneView -> PaneView+paneSetOpen (View i s g (Pane _ pin cwd)) =+ View i s g (Pane True pin cwd)
+ lib/Chiasma/Ui/ShowTree.hs view
@@ -0,0 +1,41 @@+module Chiasma.Ui.ShowTree where++import Chiasma.Data.Ident (identText)+import Chiasma.Ui.Data.View (+ LayoutView,+ Pane(Pane),+ PaneView,+ Tree(Tree),+ TreeSub(TreeNode, TreeLeaf),+ View(View),+ ViewTree,+ )++formatLayout :: LayoutView -> Text+formatLayout (View ident _ _ _) = "l: " <> identText ident++formatPane :: PaneView -> Text+formatPane (View ident _ _ (Pane open _ _)) =+ "p: " <> identText ident <> openFrag+ where+ openFrag = " " <> if open then "open" else "closed"++formatViewTree :: ViewTree -> Tree Text Text+formatViewTree = bimap formatLayout formatPane++indent :: [Text] -> [Text]+indent = fmap (" " <>)++showTreeSub :: TreeSub Text Text -> [Text]+showTreeSub (TreeNode tree) = showTree tree+showTreeSub (TreeLeaf pane) = [pane]++showTree :: Tree Text Text -> [Text]+showTree (Tree l sub) =+ l : indent (sub >>= showTreeSub)++showViewTree :: ViewTree -> [Text]+showViewTree = showTree . formatViewTree++printViewTree :: MonadIO m => ViewTree -> m ()+printViewTree = liftIO . traverse_ putStrLn . fmap toString . showViewTree
+ lib/Chiasma/Ui/ViewTree.hs view
@@ -0,0 +1,314 @@+module Chiasma.Ui.ViewTree where++import Chiasma.Data.Ident (Ident)+import Chiasma.Lens.Tree (+ LeafIndexTree(..),+ _litTree,+ leafDataTraversal,+ )+import Control.Lens (+ Traversal,+ Traversal',+ anyOf,+ cosmos,+ filtered,+ has,+ ix,+ mapMOf,+ over,+ transformM,+ )+import Control.Monad.Error.Class (throwError)+import Control.Monad.Trans.Writer (WriterT, runWriterT, tell)+import Data.Composition ((.:))++import Chiasma.Ui.Data.TreeModError (TreeModError(PaneMissing, AmbiguousPane, LayoutMissing, AmbiguousLayout))+import Chiasma.Ui.Data.View (+ Pane(Pane),+ PaneView,+ Tree(Tree),+ TreeSub(TreeNode, TreeLeaf),+ View(View),+ ViewTree,+ ViewTreeSub,+ )+import qualified Chiasma.Ui.Data.View as Pane (open)+import qualified Chiasma.Ui.Data.View as TreeSub (leafData)+import qualified Chiasma.Ui.Data.View as View (extra)+import Chiasma.Ui.Data.ViewState (ViewState(ViewState))+import Chiasma.Ui.Pane (paneSetOpen, paneToggleOpen)++modCounted :: Monad m => (a -> m a) -> a -> WriterT (Sum Int) m a+modCounted f a = do+ tell (Sum 1)+ lift $ f a++treeToggleOpen :: ViewTree -> ViewTree+treeToggleOpen (Tree l sub) =+ Tree l (snd $ mapAccumL toggle False sub)+ where+ toggle False (TreeLeaf p) = (True, TreeLeaf (paneToggleOpen p))+ toggle a b = (a, b)++modifyTreeUniqueM :: Monad m => (ViewTree -> m ViewTree) -> Ident -> ViewTree -> ExceptT TreeModError m ViewTree+modifyTreeUniqueM f ident tree = do+ let st = (transformM $ mapMOf (ix ident) (modCounted f)) tree+ (result, Sum count) <- lift $ runWriterT st+ case count of+ 1 -> return result+ 0 -> throwError $ LayoutMissing ident+ n -> throwError $ AmbiguousLayout ident n++toggleLayout1 :: Ident -> ViewTree -> Either TreeModError ViewTree+toggleLayout1 ident tree =+ runIdentity $ runExceptT $ modifyTreeUniqueM (Identity . treeToggleOpen) ident tree++modifyPaneUniqueM :: Monad m => (PaneView -> m PaneView) -> Ident -> ViewTree -> ExceptT TreeModError m ViewTree+modifyPaneUniqueM f ident tree = do+ let st = (transformM $ mapMOf (ix ident) (modCounted f)) (LeafIndexTree tree)+ (result, Sum count) <- lift $ runWriterT st+ case count of+ 1 -> return $ litTree result+ 0 -> throwError $ PaneMissing ident+ n -> throwError $ AmbiguousPane ident n++modifyPane :: (PaneView -> PaneView) -> Ident -> ViewTree -> Either TreeModError ViewTree+modifyPane modification ident tree =+ runIdentity $ runExceptT $ modifyPaneUniqueM (Identity . modification) ident tree++openPane :: Ident -> ViewTree -> Either TreeModError ViewTree+openPane =+ modifyPane paneSetOpen++hasOpenPanes :: ViewTree -> Bool+hasOpenPanes tree =+ has (cosmos . _litTree . leafDataTraversal . filtered isOpen) (LeafIndexTree tree)+ where+ isOpen (View _ _ _ (Pane open _ _)) = open++depthTraverseTree ::+ ∀ a.+ Monoid a =>+ (a -> ViewTree -> (a, ViewTree)) ->+ (PaneView -> (a, PaneView)) ->+ ViewTree ->+ (a, ViewTree)+depthTraverseTree transformNode transformLeaf =+ recur+ where+ recur :: ViewTree -> (a, ViewTree)+ recur (Tree l sub) =+ uncurry transformNode . bimap fold (Tree l) . unzip $ (recSub <$> sub)+ recSub :: ViewTreeSub -> (a, ViewTreeSub)+ recSub (TreeNode t) =+ second TreeNode $ recur t+ recSub (TreeLeaf l) =+ second TreeLeaf $ transformLeaf l++data ToggleStatus =+ Minimized+ |+ Opened+ |+ Pristine+ |+ Multiple Int+ |+ Consistent+ deriving (Eq, Show)++instance Semigroup ToggleStatus where+ Pristine <> a = a+ a <> Pristine = a+ Multiple a <> Multiple b = Multiple (a + b)+ Multiple a <> _ = Multiple (a + 1)+ _ <> Multiple a = Multiple (a + 1)+ _ <> _ = Multiple 2++instance Monoid ToggleStatus where+ mempty = Pristine++data ToggleResult a =+ Success a+ |+ NotFound+ |+ Ambiguous Int+ deriving (Eq, Show, Functor)++instance Semigroup (ToggleResult a) where+ NotFound <> a = a+ a <> NotFound = a+ Ambiguous a <> Ambiguous b = Ambiguous (a + b)+ Ambiguous a <> _ = Ambiguous (a + 1)+ _ <> Ambiguous a = Ambiguous (a + 1)+ _ <> _ = Ambiguous 2++instance Monoid (ToggleResult a) where+ mempty = NotFound++instance Applicative ToggleResult where+ pure = Success+ (Success f) <*> fa = fmap f fa+ NotFound <*> _ = NotFound+ Ambiguous n <*> _ = Ambiguous n++instance Monad ToggleResult where+ Success a >>= f = f a+ NotFound >>= _ = NotFound+ Ambiguous n >>= _ = Ambiguous n++openPinnedSubs :: ToggleStatus -> ViewTree -> (ToggleStatus, ViewTree)+openPinnedSubs Pristine t =+ (Pristine, t)+openPinnedSubs Opened (Tree l sub) =+ (Opened, Tree l (openPinnedPane <$> sub))+ where+ openPinnedPane :: ViewTreeSub -> ViewTreeSub+ openPinnedPane (TreeLeaf (View i s g (Pane False True cwd))) =+ TreeLeaf $ View i s g (Pane True True cwd)+ openPinnedPane v =+ v+openPinnedSubs a t =+ (a, t)++checkToggleResult ::+ ToggleStatus ->+ a ->+ ToggleResult a+checkToggleResult =+ checkResult+ where+ checkResult Pristine _ = NotFound+ checkResult (Multiple n) _ = Ambiguous n+ checkResult _ result = Success result++togglePaneView :: Ident -> PaneView -> (ToggleStatus, PaneView)+togglePaneView ident (View i s g (Pane False p c)) | ident == i =+ (Opened, View i s g (Pane True p c))+togglePaneView ident (View i (ViewState minimized) g (Pane True p c)) | ident == i =+ (Minimized, View i (ViewState (not minimized)) g (Pane False p c))+togglePaneView _ v =+ (Pristine, v)++togglePaneNode :: Ident -> ViewTreeSub -> (ToggleStatus, ViewTreeSub)+togglePaneNode ident (TreeLeaf v) =+ second TreeLeaf (togglePaneView ident v)+togglePaneNode _ t =+ (Pristine, t)++togglePane :: Ident -> ViewTree -> ToggleResult ViewTree+togglePane ident =+ uncurry checkToggleResult . depthTraverseTree openPinnedSubs (togglePaneView ident)++togglePaneOpenTraversal' ::+ Traversal' a ViewTree ->+ Ident ->+ a ->+ ToggleResult a+togglePaneOpenTraversal' lens =+ mapMOf lens . togglePane++ensurePaneViewOpen :: Ident -> PaneView -> (ToggleStatus, PaneView)+ensurePaneViewOpen ident (View i s g (Pane False p c)) | ident == i =+ (Opened, View i s g (Pane True p c))+ensurePaneViewOpen ident v@(View i _ _ _) | ident == i =+ (Consistent, v)+ensurePaneViewOpen _ v =+ (Pristine, v)++ensurePaneOpen :: Ident -> ViewTree -> ToggleResult ViewTree+ensurePaneOpen ident =+ uncurry checkToggleResult . depthTraverseTree openPinnedSubs (ensurePaneViewOpen ident)++ensurePaneOpenTraversal ::+ Traversal a (ToggleResult a) ViewTree (ToggleResult ViewTree) ->+ Ident ->+ a ->+ ToggleResult a+ensurePaneOpenTraversal lens =+ over lens . ensurePaneOpen++ensurePaneOpenTraversal' ::+ Traversal' a ViewTree ->+ Ident ->+ a ->+ ToggleResult a+ensurePaneOpenTraversal' lens =+ mapMOf lens . ensurePaneOpen++skipFold ::+ Traversable t =>+ (a -> (ToggleStatus, a)) ->+ ToggleStatus ->+ t a ->+ (ToggleStatus, t a)+skipFold f =+ mapAccumL skipper+ where+ skipper Pristine a =+ f a+ skipper status a =+ (status, a)++isOpenPaneNode :: ViewTreeSub -> Bool+isOpenPaneNode =+ anyOf (TreeSub.leafData . View.extra . Pane.open) id++openPinnedPaneView :: PaneView -> (ToggleStatus, PaneView)+openPinnedPaneView (View i s g (Pane False True c)) =+ (Opened, View i s g (Pane True True c))+openPinnedPaneView v =+ (Pristine, v)++openFirstPinnedPaneNode :: ViewTreeSub -> (ToggleStatus, ViewTreeSub)+openFirstPinnedPaneNode (TreeLeaf v) =+ second TreeLeaf (openPinnedPaneView v)+openFirstPinnedPaneNode a =+ (Pristine, a)++openPaneView :: PaneView -> (ToggleStatus, PaneView)+openPaneView (View i s g (Pane False p c)) =+ (Opened, View i s g (Pane True p c))+openPaneView v =+ (Pristine, v)++openFirstPaneNode :: ViewTreeSub -> (ToggleStatus, ViewTreeSub)+openFirstPaneNode (TreeLeaf v) =+ second TreeLeaf (openPaneView v)+openFirstPaneNode a =+ (Pristine, a)++-- TODO recurse when opening pane+toggleLayoutNode :: Ident -> ToggleStatus -> ViewTree -> (ToggleStatus, ViewTree)+toggleLayoutNode ident previous (Tree v@(View i (ViewState minimized) g l) sub) | ident == i =+ first (previous <>) (if open then toggleMinimized else openPane')+ where+ open =+ any isOpenPaneNode sub+ toggleMinimized =+ (Minimized, Tree (View i (ViewState (not minimized)) g l) sub)+ openPane' =+ second (Tree v) (uncurry regularIfPristine openFirstPinned)+ openFirstPinned =+ skipFold openFirstPinnedPaneNode Pristine sub+ openFirstRegular =+ skipFold openFirstPaneNode Pristine sub+ regularIfPristine Pristine _ =+ openFirstRegular+ regularIfPristine status a =+ (status, a)+toggleLayoutNode _ a t =+ (a, t)++toggleLayout :: Ident -> ViewTree -> ToggleResult ViewTree+toggleLayout ident =+ uncurry checkToggleResult . depthTraverseTree (uncurry openPinnedSubs .: toggleLayoutNode ident) (Pristine,)++toggleLayoutOpenTraversal' ::+ Traversal' a ViewTree ->+ Ident ->+ a ->+ ToggleResult a+toggleLayoutOpenTraversal' lens =+ mapMOf lens . toggleLayout
+ lib/Chiasma/View.hs view
@@ -0,0 +1,103 @@+{-# LANGUAGE RankNTypes #-}++module Chiasma.View where++import Chiasma.Data.Ident (Ident, identText, sameIdent)+import Chiasma.Data.TmuxId (PaneId, SessionId, WindowId)+import Chiasma.Data.View (View(View), viewIdent)+import Chiasma.Data.Views (Views, ViewsError(..))+import qualified Chiasma.Data.Views as Views (log, panes, sessions, windows)+import Chiasma.Lens.Where (where1)+import Control.Lens (Lens', over)+import qualified Control.Lens as Lens (over, set, view)+import Data.Text.Prettyprint.Doc (Doc, pretty)+import Data.Text.Prettyprint.Doc.Render.Terminal (AnsiStyle)++sameId :: Eq a => a -> View a -> Bool+sameId id' (View _ (Just vid)) = id' == vid+sameId _ _ = False++view :: Lens' Views [View a] -> (Ident -> ViewsError) -> Ident -> Views -> Either ViewsError (View a)+view viewsL consError ident =+ maybeToRight (consError ident) . find (sameIdent ident) . Lens.view viewsL++viewById :: Eq a => Lens' Views [View a] -> a -> Views -> Maybe (View a)+viewById viewsL id' =+ find (sameId id') . Lens.view viewsL++insertView :: Lens' Views [View a] -> View a -> Views -> Views+insertView viewsL newView = Lens.over viewsL (newView :)++updateView :: Lens' Views [View a] -> (Ident -> ViewsError) -> View a -> Views -> Views+updateView viewsL _ newView =+ Lens.set (viewsL . where1 (sameIdent (viewIdent newView))) newView++session :: Ident -> Views -> Either ViewsError (View SessionId)+session = view Views.sessions NoSuchSession++sessionById :: SessionId -> Views -> Maybe (View SessionId)+sessionById = viewById Views.sessions++insertSession :: View SessionId -> Views -> Views+insertSession = insertView Views.sessions++updateSession :: View SessionId -> Views -> Views+updateSession = updateView Views.sessions NoSuchSession++window :: Ident -> Views -> Either ViewsError (View WindowId)+window = view Views.windows NoSuchWindow++windowById :: WindowId -> Views -> Maybe (View WindowId)+windowById = viewById Views.windows++insertWindow :: View WindowId -> Views -> Views+insertWindow = insertView Views.windows++updateWindow :: View WindowId -> Views -> Views+updateWindow = updateView Views.windows NoSuchWindow++pane :: Ident -> Views -> Either ViewsError (View PaneId)+pane = view Views.panes NoSuchPane++paneById :: PaneId -> Views -> Maybe (View PaneId)+paneById = viewById Views.panes++paneId :: Ident -> Views -> Either ViewsError PaneId+paneId paneIdent views =+ pane paneIdent views >>= trans+ where+ trans (View _ (Just paneId')) = Right paneId'+ trans _ = Left $ NoPaneId paneIdent++insertPane :: View PaneId -> Views -> Views+insertPane = insertView Views.panes++updatePane :: View PaneId -> Views -> Views+updatePane = updateView Views.panes NoSuchPane++type Getter a = Ident -> Views -> Either ViewsError (View a)+type Setter a = View a -> Views -> Views++addView :: MonadDeepState s Views m => Setter a -> Ident -> m (View a)+addView setter ident = do+ modify $ setter newView+ viewsLogS $ "added tmux view " <> identText ident+ return newView+ where+ newView = View ident Nothing++findOrCreateView :: (MonadDeepState s Views m) => Getter a -> Setter a -> Ident -> m (View a)+findOrCreateView getter setter ident = do+ existing <- gets $ getter ident+ either (const $ addView setter ident) return existing++viewsLog :: MonadDeepState s Views m => Doc AnsiStyle -> m ()+viewsLog message =+ modify f+ where+ f :: Views -> Views+ f = over Views.log (message :)++viewsLogS :: MonadDeepState s Views m => Text -> m ()+viewsLogS =+ viewsLog . pretty
+ lib/Chiasma/View/State.hs view
@@ -0,0 +1,17 @@+module Chiasma.View.State where++import Chiasma.Data.Ident (Ident)+import Chiasma.Data.TmuxId (PaneId)+import Control.Monad.DeepError (MonadDeepError, hoistEither)+import Control.Monad.DeepState (MonadDeepState, gets)++import Chiasma.Data.Views (Views, ViewsError)+import qualified Chiasma.View as Views (paneId)++paneId ::+ (MonadDeepState s Views m, MonadDeepError e ViewsError m) =>+ Ident ->+ m PaneId+paneId paneIdent = do+ pid <- gets $ Views.paneId paneIdent+ hoistEither pid
+ lib/Chiasma/Window.hs view
@@ -0,0 +1,225 @@+module Chiasma.Window where++import qualified Chiasma.Codec.Data as Codec (Pane(Pane, paneId), Window(Window, windowId))+import qualified Chiasma.Codec.Data.PaneDetail as Codec (PaneDetail(PaneDetail))+import qualified Chiasma.Codec.Data.PaneDetail as PaneDetail (PaneDetail(..))+import qualified Chiasma.Command.Pane as Cmd (closePane, firstWindowPane, windowPanesAs)+import qualified Chiasma.Command.Window as Cmd (newWindow, splitWindowAs, window)+import Chiasma.Data.Ident (Ident, identText, identify)+import Chiasma.Data.Maybe (findMaybe, maybeExcept, orElse)+import Chiasma.Data.RenderError (RenderError)+import qualified Chiasma.Data.RenderError as RenderError (RenderError(NoPrincipal))+import Chiasma.Data.TmuxId (PaneId, SessionId, WindowId)+import Chiasma.Data.TmuxThunk (TmuxThunk)+import qualified Chiasma.Data.View as Tmux (View(View))+import Chiasma.Data.Views (Views)+import Chiasma.Data.WindowState (WindowState(..))+import Chiasma.Pane (addPane)+import Chiasma.Ui.Data.RenderableTree (+ RLayout(..),+ RPane(..),+ Renderable(..),+ RenderableNode,+ RenderableTree,+ )+import qualified Chiasma.Ui.Data.Tree as Tree (Node(Sub, Leaf), Tree(Tree))+import Chiasma.Ui.Data.View (Tree(..), TreeSub(..), ViewTree, ViewTreeSub)+import qualified Chiasma.Ui.Data.View as Ui (Layout(..), Pane(Pane), PaneView, View(View))+import Chiasma.Ui.Data.ViewGeometry (ViewGeometry(ViewGeometry, position))+import Chiasma.Ui.Data.ViewState (ViewState)+import Chiasma.View (findOrCreateView, viewsLog, viewsLogS)+import qualified Chiasma.View as Views (insertPane, insertWindow, pane, paneById, updatePane, updateWindow, window)+import Control.Monad.Error.Class (MonadError)+import Control.Monad.Free.Class (MonadFree)+import qualified Data.List.NonEmpty as NonEmpty (head, nonEmpty)+import Data.Text.Prettyprint.Doc (line, pretty, vsep, (<+>))++findOrCreateWindow ::+ (MonadDeepState s Views m) =>+ Ident ->+ m (Tmux.View WindowId)+findOrCreateWindow =+ findOrCreateView Views.window Views.insertWindow++registerWindowId ::+ (MonadDeepState s Views m) =>+ Ident ->+ WindowId ->+ m ()+registerWindowId ident windowId =+ modify $ Views.updateWindow $ Tmux.View ident (Just windowId)++spawnWindow ::+ (MonadDeepState s Views m, MonadFree TmuxThunk m) =>+ SessionId ->+ Ident ->+ m Codec.Window+spawnWindow sid ident = do+ win@(Codec.Window windowId _ _) <- Cmd.newWindow sid ident+ registerWindowId ident windowId+ viewsLogS $ "spawned window in session " <> show sid <> " with id " <> show windowId+ return win++findPrincipalSub :: ViewTreeSub -> Maybe Ui.PaneView+findPrincipalSub (TreeNode t) = findPrincipal t+findPrincipalSub (TreeLeaf p@(Ui.View _ _ _ (Ui.Pane True _ _))) = Just p+findPrincipalSub _ = Nothing++findPrincipal :: ViewTree -> Maybe Ui.PaneView+findPrincipal (Tree _ sub) =+ findMaybe findPrincipalSub sub++principalPane ::+ (MonadDeepState s Views m, MonadError RenderError m) =>+ ViewTree ->+ m (Ui.PaneView, Tmux.View PaneId)+principalPane tree = do+ uiPane@(Ui.View uiPaneIdent _ _ _) <- maybeExcept (RenderError.NoPrincipal $ identify tree) $ findPrincipal tree+ existingTmuxPane <- gets $ Views.pane uiPaneIdent+ tmuxPane <- either (const $ addPane uiPaneIdent) return existingTmuxPane+ return (uiPane, tmuxPane)++syncPrincipal ::+ (MonadDeepState s Views m, MonadFree TmuxThunk m, MonadError RenderError m) =>+ WindowId ->+ ViewTree ->+ m ()+syncPrincipal windowId tree@(Tree (Ui.View layoutIdent _ _ _) _) = do+ (Codec.Pane paneId _ _) <- Cmd.firstWindowPane windowId+ existing <- gets (Views.paneById paneId)+ case existing of+ Nothing -> do+ (_, Tmux.View paneIdent _) <- principalPane tree+ viewsLog $ "setting principal of layout" <+> pretty layoutIdent <+> " to pane " <+> pretty paneIdent <+> "/" <+>+ pretty paneId+ modify $ Views.updatePane (Tmux.View paneIdent (Just paneId))+ _ -> return ()++ensureWindow ::+ (MonadDeepState s Views m, MonadFree TmuxThunk m, MonadError RenderError m) =>+ SessionId ->+ Tmux.View WindowId ->+ Maybe WindowId ->+ ViewTree ->+ m Codec.Window+ensureWindow sid (Tmux.View ident mayWid) newSessionWid tree = do+ preexisting <- join <$> traverse Cmd.window (orElse newSessionWid mayWid)+ window <- maybe (spawnWindow sid ident) return preexisting+ syncPrincipal (Codec.windowId window) tree+ return window++findOrCreatePane :: MonadDeepState s Views m => Ident -> m (Tmux.View PaneId)+findOrCreatePane =+ findOrCreateView Views.pane Views.insertPane++nativePane ::+ MonadFree TmuxThunk m =>+ WindowId ->+ Tmux.View PaneId ->+ m (Maybe Codec.PaneDetail)+nativePane windowId (Tmux.View _ (Just paneId)) =+ find sameId <$> Cmd.windowPanesAs windowId+ where+ sameId (Codec.PaneDetail i _ _ _ _) = i == paneId+nativePane _ _ = return Nothing++openPane ::+ (MonadDeepState s Views m, MonadFree TmuxThunk m) =>+ FilePath ->+ WindowId ->+ m Codec.PaneDetail+openPane dir windowId = do+ detail <- Cmd.splitWindowAs dir windowId+ viewsLogS $ "opened pane " <> show (PaneDetail.paneId detail) <> " in window " <> show windowId+ return detail++ensurePaneOpen ::+ (MonadDeepState s Views m, MonadFree TmuxThunk m) =>+ FilePath ->+ Maybe Codec.PaneDetail ->+ WindowId ->+ m Codec.PaneDetail+ensurePaneOpen _ (Just detail) _ =+ return detail+ensurePaneOpen dir Nothing windowId =+ openPane dir windowId++ensurePaneClosed ::+ (MonadDeepState s Views m, MonadFree TmuxThunk m) =>+ Maybe Codec.PaneDetail ->+ m ()+ensurePaneClosed (Just (Codec.PaneDetail i _ _ _ _)) = do+ viewsLogS $ "closing pane " <> show i+ Cmd.closePane i+ensurePaneClosed _ = return ()++ensurePane ::+ (MonadDeepState s Views m, MonadFree TmuxThunk m) =>+ FilePath ->+ WindowId ->+ Ui.PaneView ->+ m (Maybe RenderableNode)+ensurePane cwd windowId (Ui.View paneIdent vState geometry (Ui.Pane open _ customDir)) = do+ tmuxPane <- findOrCreatePane paneIdent+ existingPane <- nativePane windowId tmuxPane+ updatedPane <-+ if open then Just <$> ensurePaneOpen dir existingPane windowId+ else Nothing <$ ensurePaneClosed existingPane+ modify $ Views.updatePane (Tmux.View paneIdent (PaneDetail.paneId <$> updatedPane))+ return $ cons <$> updatedPane+ where+ dir = fromMaybe cwd customDir+ cons (Codec.PaneDetail i _ _ top left) =+ Tree.Leaf . Renderable vState geometry $ RPane i top left++refPane :: RenderableNode -> RPane+refPane (Tree.Sub (Tree.Tree (Renderable _ _ (RLayout ref _)) _)) = ref+refPane (Tree.Leaf (Renderable _ _ pane)) = pane++renderableTree ::+ ViewState ->+ ViewGeometry ->+ Bool ->+ [RenderableNode] ->+ Maybe RenderableTree+renderableTree vState geometry vertical sub = do+ sub' <- NonEmpty.nonEmpty sub+ return $ Tree.Tree (Renderable vState geometry (RLayout (refPane $ NonEmpty.head sub') vertical)) sub'++viewPosition :: ViewTreeSub -> Float+viewPosition (TreeNode (Tree (Ui.View _ _ ViewGeometry { position = pos } _) _)) =+ fromMaybe 0.5 pos+viewPosition (TreeLeaf (Ui.View _ _ ViewGeometry { position = pos } _)) =+ fromMaybe 0.5 pos++ensureView ::+ (MonadDeepState s Views m, MonadFree TmuxThunk m) =>+ FilePath ->+ WindowId ->+ ViewTree ->+ m (Maybe RenderableTree)+ensureView cwd windowId =+ ensureTree+ where+ ensureTree (Tree (Ui.View layoutIdent vState geometry (Ui.Layout vertical)) sub) = do+ ensuredSub <- traverse ensureNode sortedSub+ viewsLog $ pretty ("new sub for layout `" <> identText layoutIdent <> "`:") <> line <>+ vsep (pretty <$> ensuredSub)+ return $ renderableTree vState geometry vertical $ catMaybes ensuredSub+ where+ sortedSub = sortOn viewPosition sub+ ensureNode (TreeNode t) = do+ newTree <- ensureTree t+ return $ Tree.Sub <$> newTree+ ensureNode (TreeLeaf v) =+ ensurePane cwd windowId v++windowState ::+ (MonadDeepState s Views m, MonadFree TmuxThunk m) =>+ Ident ->+ Codec.Window ->+ RenderableTree ->+ m WindowState+windowState windowIdent window tree = do+ nativeRef <- Cmd.firstWindowPane (Codec.windowId window)+ return $ WindowState window nativeRef windowIdent tree (Codec.paneId nativeRef)
+ lib/Prelude.hs view
@@ -0,0 +1,5 @@+module Prelude (+ module Chiasma.Prelude,+) where++import Chiasma.Prelude
+ readme.md view
@@ -0,0 +1,3 @@+# Intro++**chiasma** is a tmux api client for Haskell.
+ test/Chiasma/Test/CodecTest.hs view
@@ -0,0 +1,24 @@+module Chiasma.Test.CodecTest where++import Chiasma.Codec (TmuxCodec(decode, query), TmuxQuery(TmuxQuery))+import Chiasma.Data.TmuxId (PaneId(..), WindowId(..))+import Hedgehog ((===))++import Chiasma.Test.Util (UnitTest)++data Dat =+ Dat {+ paneId :: PaneId,+ windowId :: WindowId+ }+ deriving (Eq, Show, Generic)++instance TmuxCodec Dat++test_decode :: UnitTest+test_decode =+ Right (Dat (PaneId 1) (WindowId 2)) === decode " %1 @2 "++test_query :: UnitTest+test_query =+ TmuxQuery "#{pane_id} #{window_id}" === query @Dat
+ test/Chiasma/Test/LensTest.hs view
@@ -0,0 +1,102 @@+module Chiasma.Test.LensTest where++import Chiasma.Data.Ident (Ident(Str))+import Chiasma.Lens.Tree (leafByIdent, modifyLeafByIdent, treesAndSubs)+import Chiasma.Ui.Data.View (+ Pane(Pane),+ PaneView,+ Tree(Tree),+ TreeSub(TreeNode, TreeLeaf),+ View(View),+ ViewTree,+ ViewTreeSub,+ consLayout,+ consPane,+ )+import qualified Chiasma.Ui.Data.View as View (_ident, ident)+import Chiasma.Ui.Data.ViewState (ViewState(ViewState))+import Chiasma.Ui.ViewTree (togglePane)+import qualified Chiasma.Ui.ViewTree as ToggleResult (ToggleResult(..))+import Control.Lens (transformM)+import qualified Control.Lens as Lens (set)+import Hedgehog ((===))+import Test.Tasty (TestTree, testGroup)+import Chiasma.Test.Util (UnitTest, unitTest)++id0, id1, id2, id3, id4 :: Ident+id0 = Str "0"+id1 = Str "1"+id2 = Str "2"+id3 = Str "3"+id4 = Str "4"++tree :: ViewTree+tree =+ Tree (consLayout id0) [subtree, TreeLeaf (consPane id2)]+ where+ subtree = st id2 subtree2+ subtree2 = st id3 subtree3+ subtree3 = st id4 (TreeLeaf openPane)+ openPane = View id1 (ViewState False) def (Pane True False Nothing)+ st i s =+ TreeNode $ Tree (consLayout i) [s]++test_modify :: UnitTest+test_modify = do+ let+ ident = Str "changed"+ modded = modifyLeafByIdent id1 (Lens.set View.ident ident) tree+ Nothing === leafByIdent ident tree+ Just ident === (View._ident <$> leafByIdent ident modded)++failOnPaneIdent :: Ident -> ViewTree -> Maybe ViewTree+failOnPaneIdent target t@(Tree _ sub) =+ t <$ traverse match sub+ where+ match (TreeLeaf (View i _ _ _)) = if target == i then Nothing else Just ()+ match _ = Just ()++test_monadicModify :: UnitTest+test_monadicModify = do+ Nothing === (transformM (failOnPaneIdent id2) tree)+ Just tree === (transformM (failOnPaneIdent id4) tree)++insertPane :: Ident -> PaneView -> ViewTree -> ViewTree+insertPane targetLayout pane (Tree l sub) =+ if View._ident l == targetLayout then Tree l (TreeLeaf pane : sub) else Tree l sub++ensurePaneUnique :: Ident -> ViewTreeSub -> Maybe ViewTreeSub+ensurePaneUnique paneIdent (TreeLeaf (View ident _ _ _)) | ident == paneIdent = Nothing+ensurePaneUnique _ n = Just n++subtreesTarget :: ViewTree+subtreesTarget =+ Tree (consLayout id0) [subtree, TreeLeaf (consPane id2)]+ where+ subtree = TreeNode $ Tree (consLayout id2) [TreeLeaf $ consPane id4, subtree2]+ subtree2 = TreeNode $ Tree (consLayout id3) [subtree3]+ subtree3 = TreeNode $ Tree (consLayout id4) [TreeLeaf openPane]+ openPane = View id1 (ViewState False) def (Pane True False Nothing)++test_subtrees :: UnitTest+test_subtrees =+ Just subtreesTarget === treesAndSubs (Just . insertPane id2 (consPane id4)) (ensurePaneUnique id4) tree++togglePaneTree :: ViewTree+togglePaneTree =+ Tree (consLayout id0) [TreeLeaf (consPane id0), TreeLeaf (consPane id0), TreeLeaf (consPane id2)]++test_togglePane :: UnitTest+test_togglePane = do+ ToggleResult.Ambiguous 2 === togglePane id0 togglePaneTree+ ToggleResult.NotFound === togglePane id1 togglePaneTree+ ToggleResult.Success (1 :: Int) === (1 <$ togglePane id2 togglePaneTree)++test_lenses :: TestTree+test_lenses =+ testGroup "lenses" [+ unitTest "modify leaves by ident" test_modify,+ unitTest "monadically transform leaves" test_monadicModify,+ unitTest "traverse all subtrees" test_subtrees,+ unitTest "toggle a pane" test_togglePane+ ]
+ test/Chiasma/Test/OutputParseTest.hs view
@@ -0,0 +1,29 @@+module Chiasma.Test.OutputParseTest where++import Chiasma.Native.Parse (resultLines)+import qualified Data.Text as T (unlines)+import Hedgehog ((===))++import Chiasma.Test.Util (UnitTest)++paneLine :: Text+paneLine = "%0 100 100"++tmuxOutput :: Text+tmuxOutput = T.unlines [+ "%begin 123",+ "%end 123",+ "%session-changed $0 0",+ "%begin 234",+ paneLine,+ "b",+ "%end 234",+ "%begin 345",+ "c",+ "d",+ "%end 345"+ ]++test_outputParse :: UnitTest+test_outputParse =+ Right [[], [paneLine, "b"], ["c", "d"]] === resultLines tmuxOutput
+ test/Chiasma/Test/PinTest.hs view
@@ -0,0 +1,98 @@+module Chiasma.Test.PinTest where++import Chiasma.Data.Ident (Ident(Str))+import Chiasma.Ui.Data.View (+ Pane(Pane),+ Tree(Tree),+ TreeSub(TreeNode, TreeLeaf),+ View(View),+ ViewTree,+ ViewTreeSub,+ consLayout,+ )+import Chiasma.Ui.ViewTree (toggleLayout, togglePane)+import qualified Chiasma.Ui.ViewTree as ToggleResult (ToggleResult(..))+import Hedgehog ((===))+import Test.Tasty (TestTree, testGroup)++import Chiasma.Test.Util (UnitTest, unitTest)++node :: ViewTreeSub -> View Pane -> ViewTreeSub+node sub p =+ TreeNode $ Tree (consLayout "l") [sub, TreeLeaf p]++paneWith :: Bool -> Text -> ViewTreeSub+paneWith open i = TreeLeaf $ View (Str i) def def (Pane open False Nothing)++pane :: Text -> ViewTreeSub+pane =+ paneWith False++ppaneWithIdent :: Text -> Bool -> View Pane+ppaneWithIdent name open =+ View (Str name) def def (Pane open True Nothing)++ppaneWith :: Bool -> View Pane+ppaneWith =+ ppaneWithIdent "pin"++ppane :: View Pane+ppane =+ ppaneWith False++subtree4 :: ViewTreeSub+subtree4 = node subtree5 ppane++subtree5 :: ViewTreeSub+subtree5 = node subtree6 ppane++subtree6 :: ViewTreeSub+subtree6 = TreeNode $ Tree (consLayout (Str "l")) [pane "p2"]++tree :: ViewTree+tree =+ Tree (consLayout (Str "root")) [subtree4, subtree1, subtree4]+ where+ subtree1 = node subtree2 ppane+ subtree2 = node subtree3 ppane+ subtree3 = TreeNode $ Tree (consLayout (Str "l1")) [pane "p1"]++target :: ViewTree+target =+ Tree (consLayout (Str "root")) [subtree4, subtree1, subtree4]+ where+ subtree1 = node subtree2 (ppaneWith True)+ subtree2 = node subtree3 (ppaneWith True)+ subtree3 = TreeNode $ Tree (consLayout (Str "l1")) [TreeLeaf $ View (Str "p1") def def (Pane True False Nothing)]++test_pinOpenNonpinned :: UnitTest+test_pinOpenNonpinned =+ ToggleResult.Success target === togglePane (Str "p1") tree++test_layoutPinOpenNonpinned :: UnitTest+test_layoutPinOpenNonpinned =+ ToggleResult.Success target === toggleLayout (Str "l1") tree++pinnedTree :: ViewTree+pinnedTree =+ Tree (consLayout (Str "root")) [pane "left", subtree]+ where+ subtree = TreeNode $ Tree (consLayout (Str "l1")) [pane "p2", TreeLeaf $ ppaneWithIdent "p1" False]++pinnedTarget :: ViewTree+pinnedTarget =+ Tree (consLayout (Str "root")) [pane "left", subtree]+ where+ subtree = TreeNode $ Tree (consLayout (Str "l1")) [paneWith False "p2", TreeLeaf $ ppaneWithIdent "p1" True]++test_pinOpenPinned :: UnitTest+test_pinOpenPinned =+ ToggleResult.Success pinnedTarget === toggleLayout (Str "l1") pinnedTree++test_pin :: TestTree+test_pin =+ testGroup "pin" [+ unitTest "open an unpinned pane" test_pinOpenNonpinned,+ unitTest "open an unpinned layout" test_layoutPinOpenNonpinned,+ unitTest "open a pinned pane" test_pinOpenPinned+ ]
+ test/Chiasma/Test/StreamParseTest.hs view
@@ -0,0 +1,30 @@+module Chiasma.Test.StreamParseTest where++import Chiasma.Native.StreamParse (TmuxOutputBlock(Success), parseConduit)+import Conduit+import Data.ByteString.Internal (packChars)+import Data.Conduit.List+import qualified Data.Text as T (unpack)+import Hedgehog ((===))++import Chiasma.Test.Util (UnitTest)++paneLine :: Text+paneLine = "%0 100 100"++tmuxOutput :: [Text]+tmuxOutput = [+ "%begin 123\n",+ "%end 123\n",+ "%session-changed $0 0\n%begin 234\n",+ paneLine <> "\nb\n%end 234\n",+ "%begin 345\n",+ "c\n",+ "d\n",+ "%end 345\n"+ ]++test_streamParse :: UnitTest+test_streamParse = do+ r <- runConduit $ sourceList tmuxOutput .| mapC (packChars . T.unpack) .| parseConduit .| sinkList+ [Success [], Success [paneLine, "b"], Success ["c", "d"]] === r
+ test/Chiasma/Test/Util.hs view
@@ -0,0 +1,14 @@+module Chiasma.Test.Util where++import Hedgehog (TestT, withTests, property, test)+import Test.Tasty (TestName, TestTree)+import Test.Tasty.Hedgehog (testProperty)++type UnitTest = TestT IO ()++unitTest ::+ TestName ->+ UnitTest ->+ TestTree+unitTest desc =+ testProperty desc . withTests 1 . property . test
+ test/Main.hs view
@@ -0,0 +1,24 @@+module Main where++import Chiasma.Test.CodecTest (test_decode, test_query)+import Chiasma.Test.LensTest (test_lenses)+import Chiasma.Test.OutputParseTest (test_outputParse)+import Chiasma.Test.PinTest (test_pin)+import Chiasma.Test.StreamParseTest (test_streamParse)+import Chiasma.Test.Util (unitTest)+import Test.Tasty (TestTree, defaultMain, testGroup)++tests :: TestTree+tests =+ testGroup "all" [+ unitTest "tmux-decode a value" test_decode,+ unitTest "tmux-encode a query" test_query,+ test_lenses,+ unitTest "parse tmux output" test_outputParse,+ test_pin,+ unitTest "parse tmux output in stream" test_streamParse+ ]++main :: IO ()+main =+ defaultMain tests
− test/u/BufferedSpec.hs
@@ -1,45 +0,0 @@-{-# OPTIONS_GHC -F -pgmF htfpp #-}--module BufferedSpec(- htf_thisModulesTests-) where--import Test.Framework-import Chiasma.Native.Api (TmuxNative(..))-import Chiasma.Data.Pane (Pane(Pane), PaneId(..))-import Chiasma.Data.Window (Window(Window), WindowId(..))-import Chiasma.Data.TmuxThunk (TmuxError)-import Chiasma.Monad.Buffered (runTmux)-import Chiasma.Monad.Tmux (TmuxProg)-import qualified Chiasma.Monad.Tmux as Tmux (read, write)-import Chiasma.Test.Tmux (tmuxSpec)--prog :: TmuxProg ([Pane], [Pane], [Window])-prog = do- panes1 <- Tmux.read "list-panes" ["-t", "%0"]- Tmux.write "new-window" []- Tmux.write "new-window" []- wins <- Tmux.read @Window "list-windows" []- panes <- Tmux.read "list-panes" ["-a"]- return (panes1, panes, wins)--p :: Int -> Pane-p i = Pane (PaneId i) 1000 999--w :: Int -> Window-w i = Window (WindowId i) 1000 999--runProg :: TmuxNative -> IO (Either TmuxError ([Pane], [Pane], [Window]))-runProg api = runTmux api prog--test_buffered :: IO ()-test_buffered = do- result <- tmuxSpec runProg- assertEqual (Right ([p0], [p0, p1, p2], [w0, w1, w2])) result- where- p0 = p 0- p1 = p 1- p2 = p 2- w0 = w 0- w1 = w 1- w2 = w 2
− test/u/CodecSpec.hs
@@ -1,27 +0,0 @@-{-# OPTIONS_GHC -F -pgmF htfpp #-}--module CodecSpec(- htf_thisModulesTests,-) where-import GHC.Generics (Generic)-import Test.Framework-import Chiasma.Data.Pane (PaneId(..))-import Chiasma.Data.Window (WindowId(..))-import Chiasma.Codec (TmuxCodec(decode, query), TmuxQuery(TmuxQuery))--data Dat =- Dat {- paneId :: PaneId,- windowId :: WindowId- }- deriving (Eq, Show, Generic)--instance TmuxCodec Dat--test_decode :: IO ()-test_decode =- assertEqual (Right $ Dat (PaneId 1) (WindowId 2)) $ decode ["%1", "@2"]--test_query :: IO ()-test_query =- assertEqual (TmuxQuery "#{pane_id} #{window_id}") (query @Dat)
− test/u/OutputParseSpec.hs
@@ -1,30 +0,0 @@-{-# OPTIONS_GHC -F -pgmF htfpp #-}--module OutputParseSpec(- htf_thisModulesTests-) where--import Test.Framework-import Chiasma.Native.Parse (resultLines)--paneLine :: String-paneLine = "%0 100 100"--tmuxOutput :: String-tmuxOutput = unlines [- "%begin 123",- "%end 123",- "%session-changed $0 0",- "%begin 234",- paneLine,- "b",- "%end 234",- "%begin 345",- "c",- "d",- "%end 345"- ]--test_outputParse :: IO ()-test_outputParse =- assertEqual (Right [[], [paneLine, "b"], ["c", "d"]]) (resultLines tmuxOutput)
− test/u/SimpleSpec.hs
@@ -1,32 +0,0 @@-{-# OPTIONS_GHC -F -pgmF htfpp #-}--module SimpleSpec(- htf_thisModulesTests-) where---- import Data.Either (isLeft)-import Test.Framework--- import UnliftIO (try)--- import Chiasma.Data.TmuxThunk (TmuxError)--- import Chiasma.Monad.Simple (runTmux)--- import Chiasma.Monad.Tmux (TmuxProg)--- import qualified Chiasma.Monad.Tmux as Tmux (read, write)---- number :: TmuxProg a String--- number = return "1"---- prog :: TmuxProg a [String]--- prog = do--- a <- number--- out <- Tmux.read "list-panes" ["-t", "%" ++ a]--- Tmux.write "new-windowXXX" []--- return out---- runProg :: IO [String]--- runProg = runTmux prog--test_simple :: IO ()-test_simple =- return ()- -- result <- try runProg- -- assertEqual True (isLeft (result :: Either TmuxError [String]))
− test/u/SpecMain.hs
@@ -1,12 +0,0 @@-{-# OPTIONS_GHC -F -pgmF htfpp #-}--module Main where--import {-@ HTF_TESTS @-} BufferedSpec-import {-@ HTF_TESTS @-} OutputParseSpec-import {-@ HTF_TESTS @-} CodecSpec-import Test.Framework-import Test.Framework.BlackBoxTest ()--main :: IO ()-main = htfMain htf_importedTests