{-# LANGUAGE NoImplicitPrelude #-}
module Headroom.FileSystem
( fileExtension
, findFiles
, findFilesByExts
, findFilesByTypes
, listFiles
, loadFile
)
where
import Headroom.FileType ( FileType
, listExtensions
)
import RIO
import RIO.Directory ( doesDirectoryExist
, getDirectoryContents
)
import RIO.FilePath ( isExtensionOf
, takeExtension
, (</>)
)
import qualified RIO.Text as T
fileExtension :: FilePath -> Maybe Text
fileExtension :: FilePath -> Maybe Text
fileExtension path :: FilePath
path = case FilePath -> FilePath
takeExtension FilePath
path of
'.' : xs :: FilePath
xs -> Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ FilePath -> Text
T.pack FilePath
xs
_ -> Maybe Text
forall a. Maybe a
Nothing
findFiles :: MonadIO m
=> FilePath
-> (FilePath -> Bool)
-> m [FilePath]
findFiles :: FilePath -> (FilePath -> Bool) -> m [FilePath]
findFiles path :: FilePath
path predicate :: FilePath -> Bool
predicate = ([FilePath] -> [FilePath]) -> m [FilePath] -> m [FilePath]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((FilePath -> Bool) -> [FilePath] -> [FilePath]
forall a. (a -> Bool) -> [a] -> [a]
filter FilePath -> Bool
predicate) (FilePath -> m [FilePath]
forall (m :: * -> *). MonadIO m => FilePath -> m [FilePath]
listFiles FilePath
path)
findFilesByExts :: MonadIO m
=> FilePath
-> [Text]
-> m [FilePath]
findFilesByExts :: FilePath -> [Text] -> m [FilePath]
findFilesByExts path :: FilePath
path exts :: [Text]
exts = FilePath -> (FilePath -> Bool) -> m [FilePath]
forall (m :: * -> *).
MonadIO m =>
FilePath -> (FilePath -> Bool) -> m [FilePath]
findFiles FilePath
path FilePath -> Bool
predicate
where predicate :: FilePath -> Bool
predicate p :: FilePath
p = (FilePath -> Bool) -> [FilePath] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (FilePath -> FilePath -> Bool
`isExtensionOf` FilePath
p) ((Text -> FilePath) -> [Text] -> [FilePath]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Text -> FilePath
T.unpack [Text]
exts)
findFilesByTypes :: MonadIO m
=> FilePath
-> [FileType]
-> m [FilePath]
findFilesByTypes :: FilePath -> [FileType] -> m [FilePath]
findFilesByTypes path :: FilePath
path types :: [FileType]
types = FilePath -> [Text] -> m [FilePath]
forall (m :: * -> *).
MonadIO m =>
FilePath -> [Text] -> m [FilePath]
findFilesByExts FilePath
path ([FileType]
types [FileType] -> (FileType -> [Text]) -> [Text]
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= FileType -> [Text]
listExtensions)
listFiles :: MonadIO m
=> FilePath
-> m [FilePath]
listFiles :: FilePath -> m [FilePath]
listFiles fileOrDir :: FilePath
fileOrDir = do
Bool
isDir <- FilePath -> m Bool
forall (m :: * -> *). MonadIO m => FilePath -> m Bool
doesDirectoryExist FilePath
fileOrDir
if Bool
isDir then FilePath -> m [FilePath]
forall (m :: * -> *). MonadIO m => FilePath -> m [FilePath]
listDirectory FilePath
fileOrDir else [FilePath] -> m [FilePath]
forall (f :: * -> *) a. Applicative f => a -> f a
pure [FilePath
fileOrDir]
where
listDirectory :: FilePath -> m [FilePath]
listDirectory dir :: FilePath
dir = do
[FilePath]
names <- FilePath -> m [FilePath]
forall (m :: * -> *). MonadIO m => FilePath -> m [FilePath]
getDirectoryContents FilePath
dir
let filteredNames :: [FilePath]
filteredNames = (FilePath -> Bool) -> [FilePath] -> [FilePath]
forall a. (a -> Bool) -> [a] -> [a]
filter (FilePath -> [FilePath] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [".", ".."]) [FilePath]
names
[[FilePath]]
paths <- [FilePath] -> (FilePath -> m [FilePath]) -> m [[FilePath]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [FilePath]
filteredNames ((FilePath -> m [FilePath]) -> m [[FilePath]])
-> (FilePath -> m [FilePath]) -> m [[FilePath]]
forall a b. (a -> b) -> a -> b
$ \name :: FilePath
name -> do
let path :: FilePath
path = FilePath
dir FilePath -> FilePath -> FilePath
</> FilePath
name
Bool
isDirectory <- FilePath -> m Bool
forall (m :: * -> *). MonadIO m => FilePath -> m Bool
doesDirectoryExist FilePath
path
if Bool
isDirectory then FilePath -> m [FilePath]
forall (m :: * -> *). MonadIO m => FilePath -> m [FilePath]
listFiles FilePath
path else [FilePath] -> m [FilePath]
forall (f :: * -> *) a. Applicative f => a -> f a
pure [FilePath
path]
[FilePath] -> m [FilePath]
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([FilePath] -> m [FilePath]) -> [FilePath] -> m [FilePath]
forall a b. (a -> b) -> a -> b
$ [[FilePath]] -> [FilePath]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[FilePath]]
paths
loadFile :: MonadIO m
=> FilePath
-> m Text
loadFile :: FilePath -> m Text
loadFile = FilePath -> m Text
forall (m :: * -> *). MonadIO m => FilePath -> m Text
readFileUtf8