Haskell library to "union mount" a bunch of folders onto an in-memory data structure, and keeping the latter in sync as the files change over time. Used in Ema and Emanote.
Both the mount
and unionMount
functions return a tuple value of type Dynamic, giving direct access to the initial value as well as the updater function that may be run in a separate thread. See how Ema uses it for an illustration.
Here's a simple example of loading Markdown files onto a TVar of Map FilePath Text
(file contents keyed by path).
import System.UnionMount qualified as UM
import Data.Map.Strict qualified as Map
main :: IO ()
main = do
runStdoutLoggingT $ do
let baseDir = "/Users/srid/Documents/Notebook"
(model0, modelF) <- UM.mount baseDir (one ((), "*.md")) [] mempty (const $ handlePathUpdate baseDir)
modelVar <- newTVarIO model0
modelF $ \newModel -> do
atomically $ writeTVar modelVar newModel
handlePathUpdate ::
(MonadIO m) =>
FilePath -> FilePath -> UM.FileAction () -> m (Map FilePath Text -> Map FilePath Text)
handlePathUpdate baseDir path action = do
case action of
UM.Refresh _ _ -> do
s <- decodeUtf8 <$> readFileBS (baseDir </> path)
pure $ Map.insert path s
UM.Delete -> do
pure $ Map.delete path
See this example illustrating mounting a directory of Markdown files into (effectively) a Map FilePath String
. A more involved example from Emanote demonstrates the "union" aspect of the library.