{-# Language DeriveDataTypeable, ExistentialQuantification, RankNTypes, FlexibleContexts, TypeFamilies #-} ----------------------------------------------------------------------------- -- -- Module : Base.PluginTypes -- Copyright : Juergen Nicklisch-Franken -- License : LGPL -- -- Maintainer : maintainer@leksah.org -- Stability : provisional -- Portability : portabel -- -- | Types module for Plugins -- ----------------------------------------------------------------------------- module Base.PluginTypes where import Base.Event import Base.State import Base.Selector import Data.Version (showVersion, Version(..)) import Data.Typeable (Typeable) import Control.Monad.IO.Class (MonadIO(..)) import Data.IORef (newIORef) import qualified Data.Map as Map (empty) import Control.Monad (when) -- | The type of event this base component can trigger data MessageLevel = Debug | Info | Warning | Error deriving(Eq,Ord,Show,Read) type BaseEvent = EventChannel BaseEventValue data BaseEventValue = StartUp | BaseLog MessageLevel String data PluginInterface event = PluginInterface { piInit1 :: BaseEvent -> EventChannel event -> StateM (), piInit2 :: BaseEvent -> EventChannel event -> StateM (), piEvent :: EventChannel event, piName :: String, piVersion :: Version} data GenInterfaceM = forall alpha . GenInterfaceM (StateM (PluginInterface alpha)) data GenInterface = forall event . GenInterface (PluginInterface event) -- | A PluginConfig is a configuration for an app, which is composed of plugins data PluginConfig = PluginConfig { cfName :: String, -- ^ name of the config cfVersion :: Version, -- ^ version of the config cfPlugins :: [Prerequisite], -- ^ plugins to load cfChoices :: [Prerequisite], -- ^ other plugins cfSynopsis :: String} -- ^ comment for this configuration deriving (Eq,Ord,Show,Typeable) type PluginName = String -- | A plugin has -- * a unique name -- * a version -- * a list of prerequisites -- * maybe a comment -- * a module and function name for getting a PluginConfig data Plugin = Plugin { plName :: PluginName, plVersion :: Version, plPrerequisites :: [Prerequisite], plChoices :: [Prerequisite], plModule :: String, plInterface :: String, plSynopsis :: String} deriving (Eq,Ord,Show, Read, Typeable) -- | Get the name of the plugin, which includes its version getPluginName :: Plugin -> String getPluginName Plugin{plName = name, plVersion = version} = name ++ "-" ++ showVersion version -- | An upper and a lower bound for versions, which may be omitted type VersionBounds = (Maybe Version, Maybe Version) -- | A prerequisite is a pair of a plugin and version bounds type Prerequisite = (PluginName, VersionBounds) type LoadList = [Plugin] data BaseEventSel = BaseEventSel deriving (Eq,Ord,Show,Typeable) instance Selector BaseEventSel where type ValueType BaseEventSel = EventChannel BaseEventValue -- | ConfigPathSel | MessageLevelSel triggerBaseEvent :: BaseEventValue -> StateM(BaseEventValue) triggerBaseEvent = triggerEvent BaseEventSel getBaseEvent :: StateM (BaseEvent) getBaseEvent = getEvent BaseEventSel registerBaseEvent :: Handler BaseEventValue -> StateM HandlerID registerBaseEvent handler = getBaseEvent >>= \e -> registerEvent e handler data ConfigPathSel = ConfigPathSel deriving (Eq,Ord,Show,Typeable) instance Selector ConfigPathSel where type ValueType ConfigPathSel = FilePath setCurrentConfigPath :: FilePath -> StateM () setCurrentConfigPath = setState ConfigPathSel getCurrentConfigPath :: StateM FilePath getCurrentConfigPath = getState ConfigPathSel registerCurrentConfigPath :: FilePath -> StateM (Maybe String) registerCurrentConfigPath = registerState ConfigPathSel data MessageLevelSel = MessageLevelSel deriving (Eq,Ord,Show,Read,Typeable) instance Selector MessageLevelSel where type ValueType MessageLevelSel = MessageLevel setMessageLevel :: MessageLevel -> StateM () setMessageLevel = setState MessageLevelSel getMessageLevel :: StateM MessageLevel getMessageLevel = getState MessageLevelSel registerMessageLevel :: MessageLevel -> StateM (Maybe String) registerMessageLevel = registerState MessageLevelSel -- -- | Outputs a message. Triggers the BaseEvent BaseLog, which is in this -- package handled to ~BaseLog level str -> liftIO $ putStrLn (show level ++ " " ++ str)~ message :: MessageLevel -> String -> StateM () message level str = do fromLevel <- getMessageLevel when (level >= fromLevel) $ do triggerBaseEvent (BaseLog level str) >> return () messageR :: MessageLevel -> String -> StateRef -> IO () messageR level str = reflectState (message level str)