Skip to content

Instantly share code, notes, and snippets.

@voidlizard
Created August 2, 2024 15:50
Show Gist options
  • Save voidlizard/9d2254cd5787fc6e218b149588da18f3 to your computer and use it in GitHub Desktop.
Save voidlizard/9d2254cd5787fc6e218b149588da18f3 to your computer and use it in GitHub Desktop.
glob :: forall m . MonadIO m
=> [FilePattern] -- ^ search patterns
-> [FilePattern] -- ^ ignore patterns
-> FilePath -- ^ directory
-> (FilePath -> m Bool) -- ^ file action
-> m ()
glob pat ignore dir action = do
q <- newTQueueIO
void $ liftIO (async $ go q dir >> atomically (writeTQueue q Nothing))
fix $ \next -> do
atomically (readTQueue q) >>= \case
Nothing -> pure ()
Just x -> do
r <- action x
when r next
where
matches p f = or [ i ?== f | i <- p ]
skip p = or [ i ?== p | i <- ignore ]
go q f = do
isD <- doesDirectoryExist f
if not isD then do
isF <- doesFileExist f
when (isF && matches pat f) do
atomically $ writeTQueue q (Just f)
else do
co' <- (try @_ @IOError $ listDirectory f)
<&> fromRight mempty
let co = [ normalise (f </> x) | x <- co' ]
& filter (not . skip)
forConcurrently_ co (go q)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment