{-# LANGUAGE DataKinds #-} -- | Finding files. -- Lifted from Stack. module Path.Find ( findFileUp ) where import Control.Monad.Catch import Control.Monad.IO.Class import Data.List import Path import Path.IO -- | Find the location of a file matching the given predicate. findFileUp :: (MonadIO m, MonadThrow m) => Path Abs Dir -- ^ Start here. -> (Path Abs File -> Bool) -- ^ Predicate to match the file. -> Maybe (Path Abs Dir) -- ^ Do not ascend above this directory. -> m (Maybe (Path Abs File)) -- ^ Absolute file path. findFileUp = findPathUp snd -- | Find the location of a path matching the given predicate. findPathUp :: (MonadIO m, MonadThrow m) => (([Path Abs Dir], [Path Abs File]) -> [Path Abs t]) -- ^ Choose path type from pair. -> Path Abs Dir -- ^ Start here. -> (Path Abs t -> Bool) -- ^ Predicate to match the path. -> Maybe (Path Abs Dir) -- ^ Do not ascend above this directory. -> m (Maybe (Path Abs t)) -- ^ Absolute path. findPathUp pathType dir p upperBound = do entries <- listDir dir case find p (pathType entries) of Just path -> return (Just path) Nothing | Just dir == upperBound -> return Nothing | parent dir == dir -> return Nothing | otherwise -> findPathUp pathType (parent dir) p upperBound