{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE UndecidableInstances #-}
module Cli.Extras.Types where
import Control.Concurrent.MVar (MVar)
import Control.Monad.Catch (MonadCatch, MonadMask, MonadThrow)
import Control.Monad.Fail (MonadFail)
import Control.Monad.Log (LoggingT(..), MonadLog, Severity (..), WithSeverity (..))
import Control.Monad.Reader (MonadIO, ReaderT (..), MonadReader (..), ask)
import Control.Monad.Writer (WriterT)
import Control.Monad.State (StateT)
import Control.Monad.Except (ExceptT, MonadError (..))
import Control.Monad.Trans (MonadTrans, lift)
import Data.IORef (IORef)
import Data.Text (Text)
import Cli.Extras.TerminalString (TerminalString)
import Cli.Extras.Theme (CliTheme)
import Cli.Extras.SubExcept
data Output
= Output_Log (WithSeverity Text)
| Output_LogRaw (WithSeverity Text)
| Output_Write [TerminalString]
| Output_Overwrite [TerminalString]
| Output_ClearLine
deriving (Eq, Show, Ord)
type CliLog m = MonadLog Output m
type CliThrow e m = MonadError e m
data CliConfig = CliConfig
{
_cliConfig_logLevel :: IORef Severity
,
_cliConfig_noColor :: Bool
,
_cliConfig_noSpinner :: Bool
,
_cliConfig_lock :: MVar Bool
,
_cliConfig_tipDisplayed :: IORef Bool
,
_cliConfig_spinnerStack :: IORef ([Bool], [TerminalString])
,
_cliConfig_theme :: CliTheme
}
class Monad m => HasCliConfig m where
getCliConfig :: m CliConfig
instance HasCliConfig m => HasCliConfig (ReaderT r m) where
getCliConfig = lift getCliConfig
instance (Monoid w, HasCliConfig m) => HasCliConfig (WriterT w m) where
getCliConfig = lift getCliConfig
instance HasCliConfig m => HasCliConfig (StateT s m) where
getCliConfig = lift getCliConfig
instance HasCliConfig m => HasCliConfig (ExceptT e m) where
getCliConfig = lift getCliConfig
instance HasCliConfig m => HasCliConfig (SubExceptT e eSub m) where
getCliConfig = lift getCliConfig
newtype CliT e m a = CliT
{ unCliT :: ReaderT CliConfig (LoggingT Output (ExceptT e m)) a
}
deriving
( Functor, Applicative, Monad, MonadIO, MonadFail
, MonadThrow, MonadCatch, MonadMask
, MonadLog Output
, MonadError e
)
instance MonadTrans (CliT e) where
lift = CliT . lift . lift . lift
instance Monad m => HasCliConfig (CliT e m)where
getCliConfig = CliT ask