diff --git a/hbs2-cli/hbs2-cli.cabal b/hbs2-cli/hbs2-cli.cabal index 9ce78e61..a2767111 100644 --- a/hbs2-cli/hbs2-cli.cabal +++ b/hbs2-cli/hbs2-cli.cabal @@ -93,6 +93,7 @@ common shared-properties , random , vector , unix + , split library diff --git a/hbs2-cli/lib/Data/Config/Suckless/Script/File.hs b/hbs2-cli/lib/Data/Config/Suckless/Script/File.hs index 9c01135a..503569fe 100644 --- a/hbs2-cli/lib/Data/Config/Suckless/Script/File.hs +++ b/hbs2-cli/lib/Data/Config/Suckless/Script/File.hs @@ -18,6 +18,8 @@ import UnliftIO import Control.Concurrent.STM qualified as STM import Streaming.Prelude qualified as S +import Data.List.Split (chunksOf) + glob :: forall m . MonadIO m => [FilePattern] -- ^ search patterns -> [FilePattern] -- ^ ignore patterns @@ -28,21 +30,39 @@ glob :: forall m . MonadIO m glob pat ignore dir action = do let seed = [dir] - flip fix seed $ \next items -> do - case items of - [] -> pure () - (p:rest) -> do - isD <- liftIO (doesDirectoryExist p) - if isD && not (skip p) then do - content <- liftIO (try @_ @IOError $ listDirectory p) - <&> fromRight mempty - let found = [ p x | x <- content ] - next (rest <> found) - else do - isF <- liftIO (doesFileExist p) - when (isF && matches pat p ) do - void $ action p - next rest + q <- newTQueueIO + + a <- liftIO $ async do + flip fix seed $ \next items -> do + case items of + [] -> atomically (writeTQueue q Nothing) + (p:rest) -> do + isD <- liftIO (doesDirectoryExist p) + if isD && not (skip p) then do + content <- liftIO (try @_ @IOError $ listDirectory p) + <&> fromRight mempty + + let found = [ p x | x <- content ] + + forConcurrently_ found $ \f -> do + glob pat ignore f $ \fn -> do + atomically $ writeTQueue q (Just fn) + pure True + + next [] + + else do + isF <- liftIO (doesFileExist p) + when (isF && matches pat p ) do + atomically (writeTQueue q (Just p)) + + next rest + + fix \next -> do + r <- atomically (readTQueue q) + case r of + Nothing -> pure () + Just e -> void (action e) >> next where matches p f = or [ i ?== f | i <- p ]