streamly-fsnotify: Folder watching as a Streamly stream.

[ bsd3, library, streamly, system ] [ Propose Tags ]

Provides Streamly streams for both single-level and recursive folder watching. Also contains a principled and compositional system for filtering file system events.

[Skip to Readme]


[Index] [Quick Jump]


Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees


Versions [RSS],,,,
Change log
Dependencies base (>=4.9 && <5), filepath (>= && <1.5), fsnotify (>= && <0.4), semirings (>=0.5.2 && <0.6), streamly (>=0.7.0 && <0.8), text (>= && <1.3), time (>=1.6 && <1.10) [details]
License BSD-3-Clause
Author Koz Ross, George Thomas
Maintainer George Thomas
Category Streamly, System
Home page
Uploaded by GeorgeThomas at 2020-05-27T10:25:01Z
Distributions NixOS:
Reverse Dependencies 2 direct, 0 indirect [details]
Downloads 1189 total (13 in the last 30 days)
Rating 2.0 (votes: 1) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs uploaded by user
Build status unknown [no reports yet]

Readme for streamly-fsnotify-

[back to package description]

What's the deal with this library?

streamly is an undoubtedly awesome library - fast, flexible, and well-documented. File system watching is a natural fit for a streaming library, and this is exactly what streamly-fsnotify provides you.

As an example, here is a program which watches /home/koz/c-project/ and any of its subdirectories for added or modified C source files (which we take to be anything with a .c extension). This program then writes that the event occurred, to what file, and when, forever.

{-# LANGUAGE LambdaCase #-}

import System.FilePath ((</>))
import Streamly.FSNotify (EventPredicate, hasExtension, isDirectory, invert, isDeletion, conj, watchTree)
import qualified Streamly.Prelude as SP

-- conj -> both must be true
-- invert -> true when the argument would be false and vice versa
isCSourceFile :: EventPredicate
isCSourceFile = hasExtension "c" `conj` invert isDirectory

notDeletion :: EventPredicate
notDeletion = invert isDeletion

srcPath :: FilePath
srcPath = "home" </> "koz" </> "c-project"

-- first value given by watchTree stops the watcher
-- we don't use it here, but if you want to, just call it
main :: IO ()
main = do
    (_, stream) <- watchTree srcPath $ isCSourceFile `conj` notDeletion
    SP.drain . SP.mapM go $ stream
    go = \case
        Added p t _ -> putStrLn $ "Created: " ++ show p ++ " at " ++ show t
        Modified p t _ -> putStrLn $ "Modified: " ++ show p ++ " at " ++ show t
        _ -> pure ()

That seems pretty cool! What kind of features can I expect?

  • Cross-platform - should work anywhere both streamly and fsnotify do.
  • Efficient (event-driven, so won't shred your CPU or load your RAM).
  • Able to do one-level and recursive watching.
  • Compositional and principled treatment of event filtering predicates.
  • Extensive set of filtering predicates, so you don't have to see events you don't care about!

Sounds good? Can I use it?

We've test-built this library for GHCs 8.6.5 through 8.10.1 on GNU/Linux. In theory, streamly-fsnotify should work everywhere both streamly and fsnotify will, which includes other OSes (such as Windows). However, we haven't tried it ourselves - let us know if you do!