{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving #-} module HackMail.Data.MainTypes ( module HackMail.Data.Path , module HackMail.Data.Email , Options (..), getOpts , Config (..) , Filter (..), runFilter) where import Control.Arrow import Control.Applicative import Control.Monad import Control.Monad.Reader import Data.List import Data.Typeable -- TODO: Export Deliverable from here to? import HackMail.Control.Misc import HackMail.Data.Path import HackMail.Data.Email import HackMail.Data.ParseEmail data SortOpt a = EqOpt a | RegOpt a deriving Show data Options = Opt { daemonMode :: Bool , incomingMailLoc :: Maybe FilePath -- only needed if daemonMode |- True , altFMainLoc :: Maybe FilePath -- not currently used. } deriving (Eq, Show) -- |A type mostly used in Hackmain.hs, stores some information about paths. Only here to avoid nasty -- mutually recursive modules. (TODO: Move this and associated functions another module?) data Config = Conf { inboxLoc :: Path , filterMainLoc :: FilePath , filterMain :: Filter () } -- what exactly do I need to store in the config? deriving (Typeable) instance Show Config where show (Conf inbox filterMain _) = "Conf | inbox :=" ++ (show inbox) ++ " FilterMain := " ++ filterMain getOpts = parseOpts <<< map optNormalForm <<< pairToList <<< (dupe map) (EqOpt, RegOpt) <<< (copy filter) (eqOpt, regOpt) where -- catches if an option is of the form -x=blah eqOpt = any (=='=') -- catches options of the form "-d foo" regOpt = not . eqOpt isOpt (c:_) = (c `elem` "+-") optNormalForm :: SortOpt String -> (String, String) optNormalForm (EqOpt s) = both tail . break (=='=') $ s optNormalForm (RegOpt s) = both tail . break (==' ') $ s parseOpts :: [(String, String)] -> Options parseOpts s = Opt dMode incMailLoc altFMain where dMode = maybeToBool . findOpt "d" $ s incMailLoc = findOpt "i" s altFMain = findOpt "c" s findOpt :: String -> [(String, String)] -> Maybe String findOpt b s = snd <$> find (\(x,y) -> x == b) s -- has to be here, otherwise it cycles imports. -- |A simple type to contain the email context. May become bigger, to store configuration details, -- etc. newtype Filter a = Filter (ReaderT (Config, Email) IO a) deriving (Monad, Functor, Typeable, MonadReader (Config, Email), MonadIO) runFilter :: Filter a -> (Config, Email) -> IO a runFilter (Filter f) = runReaderT f --- Typable instance time.