packages feed

halive 0.1.1 → 0.1.2

raw patch · 4 files changed

+84/−16 lines, 4 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Halive.FileListener: forkEventListenerThread :: FilePath -> ShouldReadFile -> TChan (Either Event String) -> TVar (Maybe UTCTime) -> IO (MVar ())
+ Halive.FileListener: eventListenerForDirectory :: MonadIO m => FilePath -> [String] -> m FileEventListener
+ Halive.FileListener: forkDirectoryListenerThread :: FilePath -> [String] -> TChan (Either Event String) -> IO (MVar ())
+ Halive.FileListener: forkFileListenerThread :: FilePath -> ShouldReadFile -> TChan (Either Event String) -> TVar (Maybe UTCTime) -> IO (MVar ())
+ Halive.FileListener: modifiedWithExtensionPredicate :: [String] -> Event -> Bool
+ Halive.Recompiler: RecompilerConfig :: Maybe (FilePath, [String]) -> String -> FilePath -> Bool -> RecompilerConfig
+ Halive.Recompiler: [rccCompileImmediately] :: RecompilerConfig -> Bool
+ Halive.Recompiler: [rccExpression] :: RecompilerConfig -> String
+ Halive.Recompiler: [rccFilePath] :: RecompilerConfig -> FilePath
+ Halive.Recompiler: [rccWatchAll] :: RecompilerConfig -> Maybe (FilePath, [String])
+ Halive.Recompiler: data RecompilerConfig
+ Halive.Recompiler: recompilerWithConfig :: MonadIO m => TChan CompilationRequest -> RecompilerConfig -> m Recompiler
- Halive.FileListener: eventListenerForFile :: (MonadIO m) => FilePath -> ShouldReadFile -> m FileEventListener
+ Halive.FileListener: eventListenerForFile :: MonadIO m => FilePath -> ShouldReadFile -> m FileEventListener
- Halive.FileListener: killFileEventListener :: (MonadIO m) => FileEventListener -> m ()
+ Halive.FileListener: killFileEventListener :: MonadIO m => FileEventListener -> m ()

Files

exec/HaliveMain.hs view
@@ -44,7 +44,15 @@             -- , gscCompilationMode = Compiled             , gscCompilationMode = Interpreted             })-    recompiler <- recompilerForExpression ghc mainFileName "main" True++    let fileTypes = ["hs", "pd", "frag", "vert"]++    recompiler <- recompilerWithConfig ghc RecompilerConfig+        { rccWatchAll = Just (".", fileTypes)+        , rccExpression = "main"+        , rccFilePath = mainFileName+        , rccCompileImmediately = True+        }      mainThreadId <- myThreadId 
halive.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/  name:                halive-version:             0.1.1+version:             0.1.2 synopsis:            A live recompiler description:   Live recompiler for Haskell
src/Halive/FileListener.hs view
@@ -43,12 +43,12 @@     Modified path _ -> path == fileName     _               -> False -eventListenerForFile :: (MonadIO m) => FilePath -> ShouldReadFile -> m FileEventListener+eventListenerForFile :: MonadIO m => FilePath -> ShouldReadFile -> m FileEventListener eventListenerForFile fileName shouldReadFile = liftIO $ do     eventChan        <- newTChanIO     ignoreEventsNear <- newTVarIO Nothing -    stopMVar <- forkEventListenerThread fileName shouldReadFile eventChan ignoreEventsNear+    stopMVar <- forkFileListenerThread fileName shouldReadFile eventChan ignoreEventsNear      return FileEventListener         { felEventTChan = eventChan@@ -56,15 +56,54 @@         , felStopMVar = stopMVar         } -killFileEventListener :: (MonadIO m) => FileEventListener -> m ()+eventListenerForDirectory :: MonadIO m => FilePath -> [String] -> m FileEventListener+eventListenerForDirectory watchDirectory fileTypes = liftIO $ do+    eventChan        <- newTChanIO+    ignoreEventsNear <- newTVarIO Nothing++    stopMVar <- forkDirectoryListenerThread watchDirectory fileTypes eventChan++    return FileEventListener+        { felEventTChan = eventChan+        , felIgnoreNextEventsNear = ignoreEventsNear+        , felStopMVar = stopMVar+        }++killFileEventListener :: MonadIO m => FileEventListener -> m () killFileEventListener eventListener = liftIO $ putMVar (felStopMVar eventListener) () -forkEventListenerThread :: FilePath-                        -> ShouldReadFile-                        -> TChan (Either FSNotify.Event String)-                        -> TVar (Maybe UTCTime)-                        -> IO (MVar ())-forkEventListenerThread fileName shouldReadFile eventChan ignoreEventsNear = do+-- Pass a list like ["hs", "pd", "frag", "vert"] to match only those filetypes,+-- or an empty list to match all+modifiedWithExtensionPredicate :: [String] -> FSNotify.Event -> Bool+modifiedWithExtensionPredicate fileTypes event = case event of+    Modified path _ -> null fileTypes || drop 1 (takeExtension path) `elem` fileTypes+    _               -> False++forkDirectoryListenerThread :: FilePath+                            -> [String]+                            -> TChan (Either FSNotify.Event String)+                            -> IO (MVar ())+forkDirectoryListenerThread watchDirectory fileTypes eventChan = do+    let predicate = modifiedWithExtensionPredicate fileTypes++    -- Configures debounce time for fsnotify+    let watchConfig = defaultConfig+            { confDebounce = Debounce 0.1 }+    stopMVar <- newEmptyMVar+    _ <- forkIO . withManagerConf watchConfig $ \manager -> do++        stop <- watchTree manager watchDirectory predicate $ \e -> do+            writeTChanIO eventChan (Left e)+        () <- takeMVar stopMVar+        stop+    return stopMVar++forkFileListenerThread :: FilePath+                       -> ShouldReadFile+                       -> TChan (Either FSNotify.Event String)+                       -> TVar (Maybe UTCTime)+                       -> IO (MVar ())+forkFileListenerThread fileName shouldReadFile eventChan ignoreEventsNear = do     predicate        <- fileModifiedPredicate <$> canonicalizePath fileName     -- If an ignore time is set, ignore file changes for the next 100 ms     let ignoreTime = 0.1
src/Halive/Recompiler.hs view
@@ -78,22 +78,43 @@                         -> String                         -> Bool                         -> m Recompiler-recompilerForExpression ghcChan filePath expressionString compileOnce = liftIO $ do+recompilerForExpression ghcChan filePath expressionString compileImmediately =+    recompilerWithConfig ghcChan RecompilerConfig+        { rccWatchAll = Nothing+        , rccExpression = expressionString+        , rccFilePath = filePath+        , rccCompileImmediately = compileImmediately+        }++data RecompilerConfig = RecompilerConfig+    { rccWatchAll :: Maybe (FilePath, [String]) -- if Nothing, just watch given file+    , rccExpression :: String+    , rccFilePath :: FilePath+    , rccCompileImmediately :: Bool+    }++recompilerWithConfig :: MonadIO m+                     => TChan CompilationRequest+                     -> RecompilerConfig+                     -> m Recompiler+recompilerWithConfig ghcChan RecompilerConfig{..} = liftIO $ do     resultTChan <- newTChanIO     let compilationRequest = CompilationRequest-            { crFilePath         = filePath-            , crExpressionString = expressionString+            { crFilePath         = rccFilePath+            , crExpressionString = rccExpression             , crResultTChan      = resultTChan             , crFileContents     = Nothing             }       -- Compile for the first time immediately-    when compileOnce $+    when rccCompileImmediately $         writeTChanIO ghcChan compilationRequest      -- Recompile on file event notifications-    fileEventListener <- eventListenerForFile filePath JustReportEvents+    fileEventListener <- case rccWatchAll of +        Nothing -> eventListenerForFile rccFilePath JustReportEvents+        Just (watchDir, fileTypes) -> eventListenerForDirectory watchDir fileTypes     listenerThread <- forkIO . forever $ do         _ <- readFileEvent fileEventListener         writeTChanIO ghcChan compilationRequest