{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# 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
deriving instance MonadFail m => MonadFail (LoggingT Output 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