{-# 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 forall a b. (a -> b) -> a -> b
$ forall a b c. (a -> b -> c) -> b -> a -> c
flip FilePath -> Text -> Bool
hasThisExtension Text
ext) (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 forall a b. (a -> b) -> a -> b
$ forall a b c. (a -> b -> c) -> b -> a -> c
flip FilePath -> Text -> Bool
hasThisExtension Text
ext) (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 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 :: FilePath
eventPath :: Event -> FilePath
eventPath} -> FilePath -> Bool
filt FilePath
eventPath
    Modified {FilePath
eventPath :: FilePath
eventPath :: Event -> FilePath
eventPath} -> FilePath -> Bool
filt FilePath
eventPath
    ModifiedAttributes {FilePath
eventPath :: FilePath
eventPath :: Event -> 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 forall b c a. (b -> c) -> (a -> b) -> a -> c
. Event -> FilePath
eventPath