packages feed

JuicyPixels-blp-0.4.0.0: blp2any/File.hs

module File(
    forEachFile
  , tryAll
  ) where

import Control.Exception
import Control.Monad
import System.Directory
import System.FilePath

-- | Fold over the files of a directory that pass a predicate, breadth first.
forEachFile :: Bool -- ^ Whether to descend into subdirectories
  -> FilePath -- ^ Directory to traverse
  -> (FilePath -> Bool) -- ^ File selector
  -> (a -> FilePath -> IO a) -- ^ Step, called once per file
  -> a -- ^ Initial accumulator
  -> IO a
forEachFile recurse path predf f acc = go acc path
  where
    go a dir = do
      names <- fmap (dir </>) <$> listDirectory dir
      files <- filter predf <$> filterM doesFileExist names
      a' <- foldM f a files
      if recurse
        then filterM doesDirectoryExist names >>= foldM go a'
        else return a'

-- | Run an action, turning any synchronous exception into 'Left'.
-- Asynchronous exceptions (such as Ctrl+C) are rethrown.
tryAll :: IO a -> IO (Either String a)
tryAll action = do
  result <- try action
  case result of
    Right a -> return (Right a)
    Left e
      | Just async <- fromException e -> throwIO (async :: SomeAsyncException)
      | otherwise -> return . Left $ displayException (e :: SomeException)