{-# LANGUAGE TupleSections#-} -- | Abstract notifier definitions. module System.Hiernotify (Difference, DifferenceP (..), Configuration (..), Notifier (..) ) where import Data.Monoid (Monoid (..), mempty, mappend) import Data.List ((\\), nub, intersect) import Data.Int -- | Difference datatype containing a difference as three sets of paths. This datatype is the core content of a notification of changes in a hierarchy. data DifferenceP a = DifferenceP { created :: [a], -- ^ Files appeared deleted :: [a], -- ^ Files disappeared modified :: [a] -- ^ Files modified } deriving (Show, Eq) instance Functor DifferenceP where fmap f (DifferenceP xs ys zs) = DifferenceP (map f xs) (map f ys) (map f zs) type Difference = DifferenceP FilePath -- half correct instance. It forces files which have been deleted and created to be marked as modifications. It's not correct as a delete after a create is not a modification. But correcting this bug involves mostly comparing timestamps correctly, because it can happen inside one element of the mappend. instance Eq a => Monoid (DifferenceP a) where DifferenceP n d m `mappend` DifferenceP n' d' m' = let mm = nub $ m ++ m' nn = nub $ n ++ n' dd = nub $ d ++ d' in DifferenceP ((nn \\ dd) \\ mm) ((dd \\ nn) \\ mm) (nub $ mm ++ intersect nn dd) mempty = DifferenceP [] [] [] -- | Configuration for notifiers. Minimal configuration to build a notifier. data Configuration = Configuration { top :: FilePath -- ^ directory at the top of the hierarchy under control , silence :: Int64 -- ^ minimum time lapse in seconds where nothing changes before a difference is released , select :: FilePath -> Bool -- ^ filter for file paths, positive must be included } -- | Abstract notifiers. A Notifier is an object controlling a hierarchy. -- -- Its difference method will block until a Difference is available and at least a time of peace has elapsed. -- -- Reading a difference must result internally in deleting the difference and updating the list of paths. -- The list of paths read together with the difference is always the list of paths to which the difference will be applied. data Notifier = Notifier { difference :: IO (Difference,[FilePath]) -- ^ block until next difference , stop :: IO () -- ^ stop the notification daemon }