-- File created: 2008-01-12 16:06:32 -- |Holds the 'Rule' and 'Coadjute' types and relevant functions which act on -- them. For user code, the important parts here are the 'rule' family of -- functions. module Coadjute.Rule( Rule(..), Coadjute, runCoadjute, getUserArgs, rule, ruleM, rule', ruleM' ) where import Control.Arrow (first) import Control.Monad.State (StateT(..), modify, gets) import Control.Monad.Trans (MonadIO, liftIO) import qualified Data.Set as Set import Coadjute.CoData import Coadjute.Task (Task(..), Source, Target) data Rule = Rule { rName :: String , rTasks :: [Task] } data RuleList = RL [Rule] addRule :: Rule -> RuleList -> RuleList addRule r (RL rs) = RL (r:rs) -- |Coadjute is the main monad you'll be working in. You can use the 'rule' -- family of functions to add rules whilst within this monad, and you can have -- a look at what arguments were given to you with 'getUserArgs'. -- -- For your convenience, a 'MonadIO' instance is provided. newtype Coadjute a = Co { unCo :: StateT (RuleList, [String]) CoData a } instance Monad Coadjute where return = Co . return (Co rs) >>= f = Co (rs >>= unCo.f) instance MonadIO Coadjute where liftIO = Co . liftIO runCoadjute :: Coadjute a -> CoData ([Rule], a) runCoadjute (Co st) = do ua <- asks coUserArgs (ret, (RL l, _)) <- runStateT st (RL [], ua) return (reverse l, ret) -- | You should use this instead of 'System.Environment.getArgs', to let -- Coadjute handle its own command line arguments first. getUserArgs :: Coadjute [String] getUserArgs = Co $ gets snd -- |A rule for building targets individually. rule :: String -> [String] -> ([Source] -> Target -> IO ()) -> [([Source],Target)] -> Coadjute () rule name args action = Co . modify . first . addRule . Rule name . map (\(d,t) -> Task name (Set.fromList args) [t] d (action d t)) -- |A rule for building multiple targets at once. ruleM :: String -> [String] -> ([Source] -> [Target] -> IO ()) -> [([Source],[Target])] -> Coadjute () ruleM name args action = Co . modify . first . addRule . Rule name . map (\(d,t) -> Task name (Set.fromList args) t d (action d t)) -- | > rule' = flip rule [] rule' :: String -> ([Source] -> Target -> IO ()) -> [([Source],Target)] -> Coadjute () rule' = flip rule [] -- | > ruleM' = flip ruleM [] ruleM' :: String -> ([Source] -> [Target] -> IO ()) -> [([Source],[Target])] -> Coadjute () ruleM' = flip ruleM []