    {-# LANGUAGE FlexibleContexts #-}

    -- | Some additional functions on top of "System.FSNotify".
    --
    -- Example of compiling scss files with compass
    --
    -- @
    -- compass :: WatchManager -> FilePath -> m ()
    -- compass man dir = do
    --  putStrLn $ "compass " ++ encodeString dir
    --  treeExtExists man dir "scss" $ \fp ->
    --    when ("deploy" `notElem` splitDirectories fp) $ do
    --     let d = encodeString $ head (splitDirectories rel)
    --     system "cd " ++ d ++ "&& bundle exec compass compile"
    --  return ()
    -- @

    {-# LANGUAGE NamedFieldPuns #-}

    module System.FSNotify.Devel (
      treeExtAny
      , treeExtExists
      , doAllEvents
      , allEvents
      , existsEvents
      ) where

    import Data.Text
    import Prelude hiding (FilePath)
    import System.FSNotify
    import System.FSNotify.Path (hasThisExtension)
    import System.FilePath

    -- | In the given directory tree, watch for any 'Added' and 'Modified'
    -- events (but ignore 'Removed' events) for files with the given file
    -- extension
    treeExtExists :: WatchManager
                  -> FilePath -- ^ Directory to watch
                  -> Text -- ^ extension
                  -> (FilePath -> IO ()) -- ^ action to run on file
                  -> IO StopListening
    treeExtExists :: WatchManager
    -> FilePath -> Text -> (FilePath -> IO ()) -> IO (IO ())
    treeExtExists WatchManager
    man FilePath
    dir Text
    ext FilePath -> IO ()
    action =
      WatchManager -> FilePath -> ActionPredicate -> Action -> IO (IO ())
    watchTree WatchManager
    man FilePath
    dir ((FilePath -> Bool) -> ActionPredicate
    existsEvents ((FilePath -> Bool) -> ActionPredicate)
    -> (FilePath -> Bool) -> ActionPredicate
    forall a b. (a -> b) -> a -> b
    $ (FilePath -> Text -> Bool) -> Text -> FilePath -> Bool
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip FilePath -> Text -> Bool
    hasThisExtension Text
    ext) ((FilePath -> IO ()) -> Action
    forall (m :: * -> *).
    Monad m =>
    (FilePath -> m ()) -> Event -> m ()
    doAllEvents FilePath -> IO ()
    action)

    -- | In the given directory tree, watch for any events for files with the
    -- given file extension
    treeExtAny :: WatchManager
               -> FilePath -- ^ Directory to watch
               -> Text -- ^ extension
               -> (FilePath -> IO ()) -- ^ action to run on file
               -> IO StopListening
    treeExtAny :: WatchManager
    -> FilePath -> Text -> (FilePath -> IO ()) -> IO (IO ())
    treeExtAny WatchManager
    man FilePath
    dir Text
    ext FilePath -> IO ()
    action =
      WatchManager -> FilePath -> ActionPredicate -> Action -> IO (IO ())
    watchTree WatchManager
    man FilePath
    dir ((FilePath -> Bool) -> ActionPredicate
    allEvents ((FilePath -> Bool) -> ActionPredicate)
    -> (FilePath -> Bool) -> ActionPredicate
    forall a b. (a -> b) -> a -> b
    $ (FilePath -> Text -> Bool) -> Text -> FilePath -> Bool
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip FilePath -> Text -> Bool
    hasThisExtension Text
    ext) ((FilePath -> IO ()) -> Action
    forall (m :: * -> *).
    Monad m =>
    (FilePath -> m ()) -> Event -> m ()
    doAllEvents FilePath -> IO ()
    action)

    -- | Turn a 'FilePath' callback into an 'Event' callback that ignores the
    -- 'Event' type and timestamp
    doAllEvents :: Monad m => (FilePath -> m ()) -> Event -> m ()
    doAllEvents :: forall (m :: * -> *).
    Monad m =>
    (FilePath -> m ()) -> Event -> m ()
    doAllEvents FilePath -> m ()
    action = FilePath -> m ()
    action (FilePath -> m ()) -> (Event -> FilePath) -> Event -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Event -> FilePath
    eventPath

    -- | Turn a 'FilePath' predicate into an 'Event' predicate that accepts
    -- only 'Added', 'Modified', and 'ModifiedAttributes' event types
    existsEvents :: (FilePath -> Bool) -> (Event -> Bool)
    existsEvents :: (FilePath -> Bool) -> ActionPredicate
    existsEvents FilePath -> Bool
    filt Event
    event =
      case Event
    event of
        Added {FilePath
    eventPath :: Event -> FilePath
    eventPath :: FilePath
    eventPath} -> FilePath -> Bool
    filt FilePath
    eventPath
        Modified {FilePath
    eventPath :: Event -> FilePath
    eventPath :: FilePath
    eventPath} -> FilePath -> Bool
    filt FilePath
    eventPath
        ModifiedAttributes {FilePath
    eventPath :: Event -> FilePath
    eventPath :: FilePath
    eventPath} -> FilePath -> Bool
    filt FilePath
    eventPath
        Event
    _ -> Bool
    False

    -- | Turn a 'FilePath' predicate into an 'Event' predicate that accepts
    -- any event types
    allEvents :: (FilePath -> Bool) -> (Event -> Bool)
    allEvents :: (FilePath -> Bool) -> ActionPredicate
    allEvents FilePath -> Bool
    filt = FilePath -> Bool
    filt (FilePath -> Bool) -> (Event -> FilePath) -> ActionPredicate
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Event -> FilePath
    eventPath