-- | A streaming wrapper around System.FSNotify.

module System.FSNotify.Streaming
  ( System.FSNotify.Streaming.watchTree
    -- * Re-exports
  , Event(..)
  , WatchManager
  , WatchConfig(..)
  , Debounce(..)
  , defaultConfig
  ) where

import Control.Concurrent.Chan
import Control.Exception (bracket)
import Control.Monad
import Control.Monad.Managed
import Streaming
import Streaming.Prelude (yield)
import System.FSNotify

watchTree
  :: WatchConfig -> FilePath -> (Event -> Bool) -> Stream (Of Event) Managed a
watchTree :: forall a.
WatchConfig
-> FilePath -> (Event -> Bool) -> Stream (Of Event) Managed a
watchTree WatchConfig
config FilePath
path Event -> Bool
predicate = do
  Chan Event
chan <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a. IO (Chan a)
newChan

  WatchManager
manager <- forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (forall (m :: * -> *) a.
MonadManaged m =>
(forall r. (a -> IO r) -> IO r) -> m a
managed (forall a. WatchConfig -> (WatchManager -> IO a) -> IO a
withManagerConf WatchConfig
config))

  forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (forall (m :: * -> *).
MonadManaged m =>
(forall r. IO r -> IO r) -> m ()
managed_ (forall a.
WatchManager
-> FilePath -> (Event -> Bool) -> Chan Event -> IO a -> IO a
withTreeChan WatchManager
manager FilePath
path Event -> Bool
predicate Chan Event
chan))

  forall (f :: * -> *) a b. Applicative f => f a -> f b
forever (forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (forall a. Chan a -> IO a
readChan Chan Event
chan) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (m :: * -> *) a. Monad m => a -> Stream (Of a) m ()
yield)

withTreeChan
  :: WatchManager -> FilePath -> ActionPredicate -> EventChannel -> IO a -> IO a
withTreeChan :: forall a.
WatchManager
-> FilePath -> (Event -> Bool) -> Chan Event -> IO a -> IO a
withTreeChan WatchManager
manager FilePath
path Event -> Bool
predicate Chan Event
chan IO a
act =
  forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket
    (WatchManager
-> FilePath -> (Event -> Bool) -> Chan Event -> IO StopListening
watchTreeChan WatchManager
manager FilePath
path Event -> Bool
predicate Chan Event
chan)
    forall a. a -> a
id
    (\StopListening
_ -> IO a
act)