hi3status-0.1.0.0: lib-src/Hi3Status/Block/Internal.hs
{-|
Module : Hi3Status.Block.Internal
License : MIT
Maintainer : Josh Kirklin (jjvk2@cam.ac.uk)
Stability : experimental
-}
{-# LANGUAGE OverloadedStrings #-}
module Hi3Status.Block.Internal where
import Control.Concurrent
import Control.Concurrent.Chan
import Control.Concurrent.MVar
import Control.Monad.IO.Class
import qualified Data.Text as T
import Data.String
import qualified Data.Aeson as A
import Data.Aeson ((.=))
data BlockUpdate = BlockUpdate
{ blockUpdatePosition :: Int
, blockUpdateDescription :: BlockDescription
}
data UpdateSignal = UpdateSignal
-- | 'BlockM' is a monad responsible for controlling the operation of a block. Each block has two lines of communication with the main status line:
--
-- * The status line can tell the block that it needs updating.
-- * The block can push updates in the form of 'BlockDescription's to the status line, which will then be processed and submitted to i3bar.
data BlockM a = BlockM
{ runBlockM :: Int -> MVar UpdateSignal -> Chan BlockUpdate -> IO a }
instance Functor BlockM where
fmap f blockm = BlockM $ \p u c -> fmap f $ runBlockM blockm p u c
instance Applicative BlockM where
pure a = BlockM $ \_ _ _ -> return a
(BlockM f) <*> (BlockM a) = BlockM $ \p u c -> (f p u c) <*> (a p u c)
instance Monad BlockM where
BlockM a >>= m = BlockM $ \p u c -> do
a' <- a p u c
runBlockM (m a') p u c
return = pure
fail e = BlockM $ \_ _ _ -> fail e
instance MonadIO BlockM where
liftIO io = BlockM $ \_ _ _ -> io
update u = tryPutMVar u UpdateSignal >> return ()
data BlockAlign = AlignLeft | AlignCenter | AlignRight
instance A.ToJSON BlockAlign where
toJSON AlignLeft = A.String "left"
toJSON AlignCenter = A.String "center"
toJSON AlignRight = A.String "right"
-- | A 'BlockDescription' contains everything needed by i3bar to properly render a block. This includes things like the text of a block, and the color of the text. For more information about each field, see the i3bar protocol at <http://i3wm.org/docs/i3bar-protocol.html>.
data BlockDescription = BlockDescription
{ full_text :: T.Text
, short_text :: Maybe T.Text
, color :: Maybe T.Text
, min_width :: Maybe Int
, align :: Maybe BlockAlign
, name :: Maybe T.Text
, instanc :: Maybe T.Text
, urgent :: Maybe Bool
, separator :: Maybe Bool
, separator_block_width :: Maybe Int
, markup :: Maybe T.Text
}
instance A.ToJSON BlockDescription where
toJSON d = A.object . filter ((/= A.Null) . snd) $
[ "full_text" .= full_text d
, "short_text" .= short_text d
, "color" .= color d
, "min_width" .= min_width d
, "align" .= align d
, "name" .= name d
, "instance" .= instanc d
, "urgent" .= urgent d
, "separator" .= separator d
, "separator_block_width" .= separator_block_width d
, "markup" .= markup d
]
instance IsString BlockDescription where
fromString str = emptyBlockDescription { full_text = fromString str }
-- | An empty block description, i.e. one with @full_text = ""@, and everything else equal to @Nothing@.
emptyBlockDescription =
BlockDescription
""
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing