module Talash.Files (
Conf (..) , FindConf (..) , FindInDirs (..) , FileTree (..)
, defConf , withExts , ignoreExts , findWithExts , findFilesInDirs , executables
, dirContentsWith , fileTreeWith , minify , flatten , ext) where
import Control.Exception
import qualified Data.ByteString.Char8 as B
import qualified Data.HashSet as S
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import qualified Data.Vector as V
import Intro
import System.Posix.Directory.ByteString
import System.Posix.Env.ByteString
import System.Posix.Files.ByteString
data Conf = Conf {
Conf -> FileStatus -> ByteString -> IO Bool
includeFile :: FileStatus -> ByteString -> IO Bool ,
Conf -> ByteString -> Bool
filterPath :: ByteString -> Bool }
data FindConf = Find !(S.HashSet ByteString) | Ignore !(S.HashSet ByteString) deriving Int -> FindConf -> ShowS
[FindConf] -> ShowS
FindConf -> String
(Int -> FindConf -> ShowS)
-> (FindConf -> String) -> ([FindConf] -> ShowS) -> Show FindConf
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [FindConf] -> ShowS
$cshowList :: [FindConf] -> ShowS
show :: FindConf -> String
$cshow :: FindConf -> String
showsPrec :: Int -> FindConf -> ShowS
$cshowsPrec :: Int -> FindConf -> ShowS
Show
data FindInDirs = FindInDirs {
FindInDirs -> FindConf
confLocal :: FindConf ,
FindInDirs -> [ByteString]
dirsLocal :: [ByteString]}
data FileTree a = Dir { FileTree a -> a
rootDir :: a
, FileTree a -> Vector a
dirFiles :: (V.Vector a)
, FileTree a -> Vector (FileTree a)
subDirs :: (V.Vector (FileTree a))}
deriving (FileTree a -> FileTree a -> Bool
(FileTree a -> FileTree a -> Bool)
-> (FileTree a -> FileTree a -> Bool) -> Eq (FileTree a)
forall a. Eq a => FileTree a -> FileTree a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: FileTree a -> FileTree a -> Bool
$c/= :: forall a. Eq a => FileTree a -> FileTree a -> Bool
== :: FileTree a -> FileTree a -> Bool
$c== :: forall a. Eq a => FileTree a -> FileTree a -> Bool
Eq , Int -> FileTree a -> ShowS
[FileTree a] -> ShowS
FileTree a -> String
(Int -> FileTree a -> ShowS)
-> (FileTree a -> String)
-> ([FileTree a] -> ShowS)
-> Show (FileTree a)
forall a. Show a => Int -> FileTree a -> ShowS
forall a. Show a => [FileTree a] -> ShowS
forall a. Show a => FileTree a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [FileTree a] -> ShowS
$cshowList :: forall a. Show a => [FileTree a] -> ShowS
show :: FileTree a -> String
$cshow :: forall a. Show a => FileTree a -> String
showsPrec :: Int -> FileTree a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> FileTree a -> ShowS
Show)
defConf :: Conf
defConf :: Conf
defConf = (FileStatus -> ByteString -> IO Bool)
-> (ByteString -> Bool) -> Conf
Conf ((ByteString -> IO Bool) -> FileStatus -> ByteString -> IO Bool
forall a b. a -> b -> a
const ((ByteString -> IO Bool) -> FileStatus -> ByteString -> IO Bool)
-> (IO Bool -> ByteString -> IO Bool)
-> IO Bool
-> FileStatus
-> ByteString
-> IO Bool
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. IO Bool -> ByteString -> IO Bool
forall a b. a -> b -> a
const (IO Bool -> FileStatus -> ByteString -> IO Bool)
-> IO Bool -> FileStatus -> ByteString -> IO Bool
forall a b. (a -> b) -> a -> b
$ Bool -> IO Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True) (Bool -> ByteString -> Bool
forall a b. a -> b -> a
const Bool
True)
{-# INLINEABLE dirContentsWith #-}
dirContentsWith :: Conf -> ByteString -> IO (V.Vector (Either ByteString ByteString))
dirContentsWith :: Conf -> ByteString -> IO (Vector (Either ByteString ByteString))
dirContentsWith Conf
c ByteString
d = IO DirStream
-> (DirStream -> IO ())
-> (DirStream -> IO (Vector (Either ByteString ByteString)))
-> IO (Vector (Either ByteString ByteString))
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket (ByteString -> IO DirStream
openDirStream ByteString
d) DirStream -> IO ()
closeDirStream ((DirStream -> IO (Maybe (Either ByteString ByteString, DirStream)))
-> DirStream -> IO (Vector (Either ByteString ByteString))
forall (m :: * -> *) b a.
Monad m =>
(b -> m (Maybe (a, b))) -> b -> m (Vector a)
V.unfoldrM (\DirStream
s -> (Either ByteString ByteString
-> Maybe (Either ByteString ByteString, DirStream))
-> IO (Either ByteString ByteString)
-> IO (Maybe (Either ByteString ByteString, DirStream))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map (\Either ByteString ByteString
d -> if Either ByteString ByteString
d Either ByteString ByteString
-> Either ByteString ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString -> Either ByteString ByteString
forall a b. a -> Either a b
Left ByteString
"" then Maybe (Either ByteString ByteString, DirStream)
forall a. Maybe a
Nothing else (Either ByteString ByteString, DirStream)
-> Maybe (Either ByteString ByteString, DirStream)
forall a. a -> Maybe a
Just (Either ByteString ByteString
d , DirStream
s)) (IO (Either ByteString ByteString)
-> IO (Maybe (Either ByteString ByteString, DirStream)))
-> (DirStream -> IO (Either ByteString ByteString))
-> DirStream
-> IO (Maybe (Either ByteString ByteString, DirStream))
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. DirStream -> IO (Either ByteString ByteString)
go (DirStream -> IO (Maybe (Either ByteString ByteString, DirStream)))
-> DirStream
-> IO (Maybe (Either ByteString ByteString, DirStream))
forall a b. (a -> b) -> a -> b
$ DirStream
s))
where
go :: DirStream -> IO (Either ByteString ByteString)
go DirStream
s = ByteString -> IO (Either ByteString ByteString)
nm (ByteString -> IO (Either ByteString ByteString))
-> IO ByteString -> IO (Either ByteString ByteString)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< DirStream -> IO ByteString
readDirStream DirStream
s
where
nm :: ByteString -> IO (Either ByteString ByteString)
nm ByteString
f
| ByteString
f ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
"" = Either ByteString ByteString -> IO (Either ByteString ByteString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ByteString -> Either ByteString ByteString
forall a b. a -> Either a b
Left ByteString
"")
| Bool
otherwise = FileStatus -> IO (Either ByteString ByteString)
hr (FileStatus -> IO (Either ByteString ByteString))
-> IO FileStatus -> IO (Either ByteString ByteString)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< ByteString -> IO FileStatus
getSymbolicLinkStatus ByteString
f
where
hr :: FileStatus -> IO (Either ByteString ByteString)
hr FileStatus
fs
| FileStatus -> Bool
isDirectory FileStatus
fs = IO (Either ByteString ByteString)
hd
| Bool
otherwise = IO Bool
-> IO (Either ByteString ByteString)
-> IO (Either ByteString ByteString)
-> IO (Either ByteString ByteString)
forall (m :: * -> *) a. Monad m => m Bool -> m a -> m a -> m a
ifM (Conf -> FileStatus -> ByteString -> IO Bool
includeFile Conf
c FileStatus
fs ByteString
f) (Either ByteString ByteString -> IO (Either ByteString ByteString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either ByteString ByteString -> IO (Either ByteString ByteString))
-> (ByteString -> Either ByteString ByteString)
-> ByteString
-> IO (Either ByteString ByteString)
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. ByteString -> Either ByteString ByteString
forall a b. a -> Either a b
Left (ByteString -> IO (Either ByteString ByteString))
-> ByteString -> IO (Either ByteString ByteString)
forall a b. (a -> b) -> a -> b
$ ByteString
f) (DirStream -> IO (Either ByteString ByteString)
go DirStream
s)
hd :: IO (Either ByteString ByteString)
hd
| Conf -> ByteString -> Bool
filterPath Conf
c ByteString
f Bool -> Bool -> Bool
&& ByteString
f ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
/= ByteString
"." Bool -> Bool -> Bool
&& ByteString
f ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
/= ByteString
".." = IO Bool
-> IO (Either ByteString ByteString)
-> IO (Either ByteString ByteString)
-> IO (Either ByteString ByteString)
forall (m :: * -> *) a. Monad m => m Bool -> m a -> m a -> m a
ifM (ByteString -> Bool -> Bool -> Bool -> IO Bool
fileAccess ByteString
f Bool
True Bool
False Bool
False) (Either ByteString ByteString -> IO (Either ByteString ByteString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either ByteString ByteString -> IO (Either ByteString ByteString))
-> (ByteString -> Either ByteString ByteString)
-> ByteString
-> IO (Either ByteString ByteString)
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. ByteString -> Either ByteString ByteString
forall a b. b -> Either a b
Right (ByteString -> IO (Either ByteString ByteString))
-> ByteString -> IO (Either ByteString ByteString)
forall a b. (a -> b) -> a -> b
$ ByteString
f) (DirStream -> IO (Either ByteString ByteString)
go DirStream
s)
| Bool
otherwise = DirStream -> IO (Either ByteString ByteString)
go DirStream
s
{-# INLINEABLE fileTreeWith #-}
fileTreeWith :: Conf -> ByteString -> IO (FileTree Text)
fileTreeWith :: Conf -> ByteString -> IO (FileTree Text)
fileTreeWith Conf
c ByteString
d = IO ByteString
-> (ByteString -> IO ())
-> (ByteString -> IO (FileTree Text))
-> IO (FileTree Text)
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket IO ByteString
getWorkingDirectory ByteString -> IO ()
changeWorkingDirectory (IO (FileTree Text) -> ByteString -> IO (FileTree Text)
forall a b. a -> b -> a
const (IO (FileTree Text) -> ByteString -> IO (FileTree Text))
-> IO (FileTree Text) -> ByteString -> IO (FileTree Text)
forall a b. (a -> b) -> a -> b
$ ByteString -> IO ()
changeWorkingDirectory ByteString
d IO () -> IO (FileTree Text) -> IO (FileTree Text)
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> (Vector (Either ByteString ByteString) -> IO (FileTree Text)
go (Vector (Either ByteString ByteString) -> IO (FileTree Text))
-> IO (Vector (Either ByteString ByteString)) -> IO (FileTree Text)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Conf -> ByteString -> IO (Vector (Either ByteString ByteString))
dirContentsWith Conf
c ByteString
"."))
where
go :: Vector (Either ByteString ByteString) -> IO (FileTree Text)
go Vector (Either ByteString ByteString)
v = (\(Vector Text
a , Vector ByteString
b) -> Text -> Vector Text -> Vector (FileTree Text) -> FileTree Text
forall a. a -> Vector a -> Vector (FileTree a) -> FileTree a
Dir (ByteString -> Text
T.decodeUtf8 ByteString
d) Vector Text
a (Vector (FileTree Text) -> FileTree Text)
-> IO (Vector (FileTree Text)) -> IO (FileTree Text)
forall (m :: * -> *) a b. Monad m => (a -> b) -> m a -> m b
<$!> (ByteString -> IO (FileTree Text))
-> Vector ByteString -> IO (Vector (FileTree Text))
forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> Vector a -> m (Vector b)
V.mapM (Conf -> ByteString -> IO (FileTree Text)
fileTreeWith Conf
c) Vector ByteString
b) ((Vector Text, Vector ByteString) -> IO (FileTree Text))
-> (Vector (Either ByteString ByteString)
-> (Vector Text, Vector ByteString))
-> Vector (Either ByteString ByteString)
-> IO (FileTree Text)
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Either ByteString ByteString -> Either Text ByteString)
-> Vector (Either ByteString ByteString)
-> (Vector Text, Vector ByteString)
forall a b c. (a -> Either b c) -> Vector a -> (Vector b, Vector c)
V.partitionWith ((ByteString -> Text)
-> Either ByteString ByteString -> Either Text ByteString
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first ByteString -> Text
T.decodeUtf8) (Vector (Either ByteString ByteString) -> IO (FileTree Text))
-> Vector (Either ByteString ByteString) -> IO (FileTree Text)
forall a b. (a -> b) -> a -> b
$ Vector (Either ByteString ByteString)
v
{-# INLINEABLE minify #-}
minify :: FileTree Text -> FileTree Text
minify :: FileTree Text -> FileTree Text
minify (Dir Text
d Vector Text
f Vector (FileTree Text)
t)
| Vector Text
f Vector Text -> Vector Text -> Bool
forall a. Eq a => a -> a -> Bool
== Vector Text
forall a. Vector a
V.empty Bool -> Bool -> Bool
&& Vector (FileTree Text) -> Int
forall a. Vector a -> Int
V.length Vector (FileTree Text)
t Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1 = (\(Dir Text
d' Vector Text
f' Vector (FileTree Text)
t') -> Text -> Vector Text -> Vector (FileTree Text) -> FileTree Text
forall a. a -> Vector a -> Vector (FileTree a) -> FileTree a
Dir (Text
d Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
d') Vector Text
f' Vector (FileTree Text)
t') (Vector (FileTree Text) -> FileTree Text
forall a. Vector a -> a
V.unsafeHead Vector (FileTree Text)
t)
| Bool
otherwise = Text -> Vector Text -> Vector (FileTree Text) -> FileTree Text
forall a. a -> Vector a -> Vector (FileTree a) -> FileTree a
Dir Text
d Vector Text
f (Vector (FileTree Text) -> FileTree Text)
-> (Vector (FileTree Text) -> Vector (FileTree Text))
-> Vector (FileTree Text)
-> FileTree Text
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (FileTree Text -> FileTree Text)
-> Vector (FileTree Text) -> Vector (FileTree Text)
forall a b. (a -> b) -> Vector a -> Vector b
V.map FileTree Text -> FileTree Text
minify (Vector (FileTree Text) -> FileTree Text)
-> Vector (FileTree Text) -> FileTree Text
forall a b. (a -> b) -> a -> b
$ Vector (FileTree Text)
t
{-# INLINEABLE flatten #-}
flatten :: FileTree Text -> V.Vector Text
flatten :: FileTree Text -> Vector Text
flatten (Dir Text
d Vector Text
f Vector (FileTree Text)
t) = (FileTree Text -> Vector Text)
-> Vector (FileTree Text) -> Vector Text
forall a b. (a -> Vector b) -> Vector a -> Vector b
V.concatMap FileTree Text -> Vector Text
go Vector (FileTree Text)
t Vector Text -> Vector Text -> Vector Text
forall a. Semigroup a => a -> a -> a
<> (Text -> Text) -> Vector Text -> Vector Text
forall a b. (a -> b) -> Vector a -> Vector b
V.map ((Text
d Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"/") Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>) Vector Text
f
where
go :: FileTree Text -> Vector Text
go (Dir Text
d' !Vector Text
f' Vector (FileTree Text)
t') = FileTree Text -> Vector Text
flatten (Text -> Vector Text -> Vector (FileTree Text) -> FileTree Text
forall a. a -> Vector a -> Vector (FileTree a) -> FileTree a
Dir (Text
d Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"/" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
d') Vector Text
f' Vector (FileTree Text)
t')
{-# INLINABLE withExts #-}
withExts :: [ByteString]
-> FindConf
withExts :: [ByteString] -> FindConf
withExts = HashSet ByteString -> FindConf
Find (HashSet ByteString -> FindConf)
-> ([ByteString] -> HashSet ByteString) -> [ByteString] -> FindConf
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. [ByteString] -> HashSet ByteString
forall a. (Eq a, Hashable a) => [a] -> HashSet a
S.fromList
{-# INLINABLE ignoreExts #-}
ignoreExts :: [ByteString]
-> FindConf
ignoreExts :: [ByteString] -> FindConf
ignoreExts = HashSet ByteString -> FindConf
Ignore (HashSet ByteString -> FindConf)
-> ([ByteString] -> HashSet ByteString) -> [ByteString] -> FindConf
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. [ByteString] -> HashSet ByteString
forall a. (Eq a, Hashable a) => [a] -> HashSet a
S.fromList
{-# INLINABLE ext #-}
ext :: ByteString -> ByteString
ext :: ByteString -> ByteString
ext ByteString
c = if ByteString
e ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
c then ByteString
forall a. Monoid a => a
mempty else ByteString
e
where
e :: ByteString
e = (ByteString, ByteString) -> ByteString
forall a b. (a, b) -> b
snd ((ByteString, ByteString) -> ByteString)
-> (ByteString -> (ByteString, ByteString))
-> ByteString
-> ByteString
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Char -> Bool) -> ByteString -> (ByteString, ByteString)
B.spanEnd (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'.') (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ ByteString
c
{-# INLINE findWithExts #-}
findWithExts :: FindInDirs -> IO (V.Vector (FileTree Text))
findWithExts :: FindInDirs -> IO (Vector (FileTree Text))
findWithExts (FindInDirs FindConf
c [ByteString]
d) = (ByteString -> IO (FileTree Text))
-> Vector ByteString -> IO (Vector (FileTree Text))
forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> Vector a -> m (Vector b)
V.mapM (Conf -> ByteString -> IO (FileTree Text)
fileTreeWith Conf
ch) (Vector ByteString -> IO (Vector (FileTree Text)))
-> ([ByteString] -> Vector ByteString)
-> [ByteString]
-> IO (Vector (FileTree Text))
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. [ByteString] -> Vector ByteString
forall a. [a] -> Vector a
V.fromList ([ByteString] -> IO (Vector (FileTree Text)))
-> [ByteString] -> IO (Vector (FileTree Text))
forall a b. (a -> b) -> a -> b
$ [ByteString]
d
where
ch :: Conf
ch
| Find HashSet ByteString
es <- FindConf
c = Conf
defConf {includeFile :: FileStatus -> ByteString -> IO Bool
includeFile = \ !FileStatus
s !ByteString
n -> Bool -> IO Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Bool -> IO Bool) -> Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$ FileStatus -> Bool
isRegularFile FileStatus
s Bool -> Bool -> Bool
&& ByteString -> HashSet ByteString -> Bool
forall a. (Eq a, Hashable a) => a -> HashSet a -> Bool
S.member (ByteString -> ByteString
ext ByteString
n) HashSet ByteString
es}
| Ignore HashSet ByteString
es <- FindConf
c = Conf
defConf {includeFile :: FileStatus -> ByteString -> IO Bool
includeFile = \ !FileStatus
s !ByteString
n -> Bool -> IO Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Bool -> IO Bool) -> Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$ FileStatus -> Bool
isRegularFile FileStatus
s Bool -> Bool -> Bool
&& Bool -> Bool
not (ByteString -> HashSet ByteString -> Bool
forall a. (Eq a, Hashable a) => a -> HashSet a -> Bool
S.member (ByteString -> ByteString
ext ByteString
n) HashSet ByteString
es)}
{-# INLINABLE findFilesInDirs #-}
findFilesInDirs :: [FindInDirs] -> IO (V.Vector (FileTree Text))
findFilesInDirs :: [FindInDirs] -> IO (Vector (FileTree Text))
findFilesInDirs = (FindInDirs
-> IO (Vector (FileTree Text)) -> IO (Vector (FileTree Text)))
-> IO (Vector (FileTree Text))
-> [FindInDirs]
-> IO (Vector (FileTree Text))
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\FindInDirs
a IO (Vector (FileTree Text))
t -> IO (Vector (FileTree Text))
t IO (Vector (FileTree Text))
-> IO (Vector (FileTree Text)) -> IO (Vector (FileTree Text))
forall a. Semigroup a => a -> a -> a
<> FindInDirs -> IO (Vector (FileTree Text))
findWithExts FindInDirs
a) (Vector (FileTree Text) -> IO (Vector (FileTree Text))
forall (f :: * -> *) a. Applicative f => a -> f a
pure Vector (FileTree Text)
forall a. Monoid a => a
mempty)
executables :: IO (V.Vector Text)
executables :: IO (Vector Text)
executables = (ByteString -> IO (Vector Text) -> IO (Vector Text))
-> IO (Vector Text) -> [ByteString] -> IO (Vector Text)
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\ByteString
a IO (Vector Text)
t -> IO (Vector Text)
t IO (Vector Text) -> IO (Vector Text) -> IO (Vector Text)
forall a. Semigroup a => a -> a -> a
<> (FileTree Text -> Vector Text)
-> IO (FileTree Text) -> IO (Vector Text)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map ((Text -> Text) -> Vector Text -> Vector Text
forall a b. (a -> b) -> Vector a -> Vector b
V.map ((Char -> Bool) -> Text -> Text
T.takeWhileEnd (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'/')) (Vector Text -> Vector Text)
-> (FileTree Text -> Vector Text) -> FileTree Text -> Vector Text
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. FileTree Text -> Vector Text
flatten) (Conf -> ByteString -> IO (FileTree Text)
fileTreeWith Conf
cl ByteString
a)) (Vector Text -> IO (Vector Text)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Vector Text
forall a. Vector a
V.empty) ([ByteString] -> IO (Vector Text))
-> (ByteString -> [ByteString]) -> ByteString -> IO (Vector Text)
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Char -> ByteString -> [ByteString]
B.split Char
':' (ByteString -> IO (Vector Text))
-> IO ByteString -> IO (Vector Text)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< ByteString -> ByteString -> IO ByteString
getEnvDefault ByteString
"PATH" ByteString
""
where
cl :: Conf
cl = Conf
defConf { filterPath :: ByteString -> Bool
filterPath = Bool -> ByteString -> Bool
forall a b. a -> b -> a
const Bool
False , includeFile :: FileStatus -> ByteString -> IO Bool
includeFile = \ FileStatus
s ByteString
p -> (Bool -> Bool) -> IO Bool -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map ((FileStatus -> Bool
isRegularFile FileStatus
s Bool -> Bool -> Bool
|| FileStatus -> Bool
isSymbolicLink FileStatus
s) Bool -> Bool -> Bool
&&) (IO Bool -> IO Bool) -> (Bool -> IO Bool) -> Bool -> IO Bool
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. ByteString -> Bool -> Bool -> Bool -> IO Bool
fileAccess ByteString
p Bool
False Bool
False (Bool -> IO Bool) -> Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$ Bool
True}