{-# OPTIONS_GHC -Wall #-}
{-# LANGUAGE NoImplicitPrelude #-}

module System.FilePath.FilePather.Find(
  findWith
, findWith'
, findAllDirectories
, findAll
, findAllFiles
) where

import Control.Applicative ( Applicative(pure) )
import Control.Category ( Category((.)) )
import Control.Exception ( Exception )
import Control.Lens ( view, _Wrapped, _1, _2 )
import Control.Monad ( Monad((>>=)), filterM )
import Control.Monad.IO.Class ( MonadIO(liftIO) )
import Control.Monad.Reader
    ( MonadReader(local, ask) )
import Data.Bool ( Bool(True), bool )
import Data.Foldable ( fold )
import Data.Functor ( Functor(fmap), (<$>) )
import Data.Maybe ( Maybe(..), catMaybes )
import Data.Semigroup ( Semigroup((<>)) )
import Data.Traversable ( Traversable(traverse) )
import System.FilePath ( FilePath, (</>) )
import System.FilePath.FilePather.Directory
    ( listDirectory, doesFileExist, doesDirectoryExist )
import System.FilePath.FilePather.ReadFilePath ( ReadFilePathT )
import System.IO ( IO )
import System.IO.Unsafe( unsafeInterleaveIO )

findWith ::
  Exception e =>
  ReadFilePathT e IO (Maybe b)
  -> ReadFilePathT e IO [b]
findWith :: forall e b.
Exception e =>
ReadFilePathT e IO (Maybe b) -> ReadFilePathT e IO [b]
findWith ReadFilePathT e IO (Maybe b)
p =
  let setl :: FilePath -> ReadFilePathT e IO a -> ReadFilePathT e IO a
setl =
        forall r (m :: * -> *) a. MonadReader r m => (r -> r) -> m a -> m a
local forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall (f :: * -> *) a. Applicative f => a -> f a
pure
      mapMaybeM :: (a -> f (Maybe a)) -> [a] -> f [a]
mapMaybeM a -> f (Maybe a)
f [a]
xs =
        forall a. [Maybe a] -> [a]
catMaybes forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse a -> f (Maybe a)
f [a]
xs
  in  do  FilePath
z <- forall r (m :: * -> *). MonadReader r m => m r
ask
          [FilePath]
a <- forall e. Exception e => ReadFilePathT e IO [FilePath]
listDirectory
          let y :: [FilePath]
y = (FilePath
z FilePath -> FilePath -> FilePath
</>) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [FilePath]
a
          [(b, FilePath)]
b <- forall {f :: * -> *} {a} {a}.
Applicative f =>
(a -> f (Maybe a)) -> [a] -> f [a]
mapMaybeM (\FilePath
fp -> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\b
s -> (b
s, FilePath
fp))) (FilePath
fp forall {a}.
FilePath -> ReadFilePathT e IO a -> ReadFilePathT e IO a
`setl` ReadFilePathT e IO (Maybe b)
p)) [FilePath]
y
          [FilePath]
d <- forall (m :: * -> *) a.
Applicative m =>
(a -> m Bool) -> [a] -> m [a]
filterM (forall {a}.
FilePath -> ReadFilePathT e IO a -> ReadFilePathT e IO a
`setl` forall e. ReadFilePathT e IO Bool
doesDirectoryExist) (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall s t a b. Field2 s t a b => Lens s t a b
_2) [(b, FilePath)]
b)
          let bs :: [b]
bs = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall s t a b. Field1 s t a b => Lens s t a b
_1) [(b, FilePath)]
b
          case [FilePath]
d of
            [] ->
              forall (f :: * -> *) a. Applicative f => a -> f a
pure [b]
bs
            [FilePath]
_ ->
              do  [b]
n <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (forall a. IO a -> IO a
unsafeInterleaveIO (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (t :: * -> *) m. (Foldable t, Monoid m) => t m -> m
fold) (forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
_Wrapped (forall e b.
Exception e =>
ReadFilePathT e IO (Maybe b) -> ReadFilePathT e IO [b]
findWith ReadFilePathT e IO (Maybe b)
p)) [FilePath]
d)))
                  forall (f :: * -> *) a. Applicative f => a -> f a
pure ([b]
bs forall a. Semigroup a => a -> a -> a
<> [b]
n)
{-# INLINE findWith #-}

findWith' ::
  Exception e =>
  ReadFilePathT e IO Bool
  -> ReadFilePathT e IO [FilePath]
findWith' :: forall e.
Exception e =>
ReadFilePathT e IO Bool -> ReadFilePathT e IO [FilePath]
findWith' ReadFilePathT e IO Bool
s =
  forall e b.
Exception e =>
ReadFilePathT e IO (Maybe b) -> ReadFilePathT e IO [b]
findWith (forall r (m :: * -> *). MonadReader r m => m r
ask forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \FilePath
d -> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a. a -> a -> Bool -> a
bool forall a. Maybe a
Nothing (forall a. a -> Maybe a
Just FilePath
d)) ReadFilePathT e IO Bool
s)
{-# INLINE findWith' #-}

findAllDirectories ::
  Exception e =>
  ReadFilePathT e IO [FilePath]
findAllDirectories :: forall e. Exception e => ReadFilePathT e IO [FilePath]
findAllDirectories =
  forall e.
Exception e =>
ReadFilePathT e IO Bool -> ReadFilePathT e IO [FilePath]
findWith' forall e. ReadFilePathT e IO Bool
doesDirectoryExist
{-# INLINE findAllDirectories #-}

findAll ::
  Exception e =>
  ReadFilePathT e IO [FilePath]
findAll :: forall e. Exception e => ReadFilePathT e IO [FilePath]
findAll =
  forall e.
Exception e =>
ReadFilePathT e IO Bool -> ReadFilePathT e IO [FilePath]
findWith' (forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True)
{-# INLINE findAll #-}

findAllFiles ::
  Exception e =>
  ReadFilePathT e IO [FilePath]
findAllFiles :: forall e. Exception e => ReadFilePathT e IO [FilePath]
findAllFiles =
  forall e. Exception e => ReadFilePathT e IO [FilePath]
findAll forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (m :: * -> *) a.
Applicative m =>
(a -> m Bool) -> [a] -> m [a]
filterM (\FilePath
p -> forall r (m :: * -> *) a. MonadReader r m => (r -> r) -> m a -> m a
local (forall (f :: * -> *) a. Applicative f => a -> f a
pure FilePath
p) forall e. ReadFilePathT e IO Bool
doesFileExist)
{-# INLINE findAllFiles #-}