filepather-0.4.0: src/System/FilePath/FilePather/Find.hs
{-# OPTIONS_GHC -Wall #-}
{-# LANGUAGE NoImplicitPrelude #-}
module System.FilePath.FilePather.Find(
findFiles
, always
, findFilesAlways
) where
import Control.Applicative ( Applicative(liftA2, pure) )
import Control.Category ( Category(id) )
import Control.Lens ( view )
import Control.Monad ( join, Monad((>>=)) )
import System.FilePath.FilePather.Posix
( (</>), FilePath, dropTrailingPathSeparator )
import System.IO ( IO )
import Data.Bool ( Bool(True), bool )
import Data.Function(($))
import Data.Functor ( Functor(fmap) )
import Data.Traversable ( Traversable(traverse) )
import Data.Semigroup ( Semigroup((<>)) )
import System.Directory(doesDirectoryExist, listDirectory)
import System.FilePath.FilePather.ReadFilePath
( ReadFilePathT(..), readFilePath )
findFiles ::
ReadFilePathT IO Bool
-> ReadFilePathT IO [FilePath]
findFiles (ReadFilePathT test) =
let bool' ::
Monad f =>
f a
-> f a
-> f Bool
-> f a
bool' f t p =
p >>= bool f t
partitionM ::
Applicative m =>
(a -> m Bool)
-> [a]
-> m ([a], [a])
partitionM _ [] =
pure ([], [])
partitionM f (x:xs) =
liftA2
(\res (as, bs) ->
let onres p q =
bool p q res
in (onres id (x:) as, onres (x:) id bs)
)
(f x)
(partitionM f xs)
findFiles' base dx =
bool'
(pure [])
(
let findFiles'' dir =
let dir' =
base </> dir
in do (dirs,files) <- listDirectory dir' >>= partitionM (\d -> doesDirectoryExist (dir' </> d))
rest <- fmap join (traverse (\d -> findFiles'' (dir </> d)) dirs)
pure (fmap (dir </>) files <> rest)
in findFiles'' dx
)
(test $ view readFilePath dropTrailingPathSeparator dx)
in ReadFilePathT (`findFiles'` "")
always ::
Applicative f =>
ReadFilePathT f Bool
always =
ReadFilePathT (pure (pure True))
findFilesAlways ::
ReadFilePathT IO [FilePath]
findFilesAlways =
findFiles always