packages feed

chiasma-0.2.0.0: lib/Chiasma/Command/Pane.hs

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"])