packages feed

chiasma-0.2.0.0: lib/Chiasma/View.hs

{-# 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