{-# LANGUAGE NoImplicitPrelude #-}
module Headroom.FileSystem
(
findFiles
, findFilesByExts
, findFilesByTypes
, listFiles
, loadFile
, doesFileExist
, getCurrentDirectory
, createDirectory
, fileExtension
, excludePaths
)
where
import Headroom.FileType ( listExtensions )
import Headroom.Regex ( compile'
, joinPatterns
, match'
)
import Headroom.Types ( FileType
, HeadersConfig(..)
)
import RIO
import RIO.Directory ( createDirectory
, doesDirectoryExist
, doesFileExist
, getCurrentDirectory
, getDirectoryContents
)
import RIO.FilePath ( isExtensionOf
, takeExtension
, (</>)
)
import qualified RIO.List as L
import qualified RIO.Text as T
findFiles :: MonadIO m
=> FilePath
-> (FilePath -> Bool)
-> m [FilePath]
findFiles path predicate = fmap (filter predicate) (listFiles path)
findFilesByExts :: MonadIO m
=> FilePath
-> [Text]
-> m [FilePath]
findFilesByExts path exts = findFiles path predicate
where predicate p = any (`isExtensionOf` p) (fmap T.unpack exts)
findFilesByTypes :: MonadIO m
=> HeadersConfig
-> [FileType]
-> FilePath
-> m [FilePath]
findFilesByTypes headersConfig types path =
findFilesByExts path (types >>= listExtensions headersConfig)
listFiles :: MonadIO m
=> FilePath
-> m [FilePath]
listFiles fileOrDir = do
isDir <- doesDirectoryExist fileOrDir
if isDir then listDirectory fileOrDir else pure [fileOrDir]
where
listDirectory dir = do
names <- getDirectoryContents dir
let filteredNames = filter (`notElem` [".", ".."]) names
paths <- forM filteredNames $ \name -> do
let path = dir </> name
isDirectory <- doesDirectoryExist path
if isDirectory then listFiles path else pure [path]
pure $ concat paths
fileExtension :: FilePath -> Maybe Text
fileExtension path = case takeExtension path of
'.' : xs -> Just $ T.pack xs
_ -> Nothing
loadFile :: MonadIO m
=> FilePath
-> m Text
loadFile = readFileUtf8
excludePaths :: [Text]
-> [FilePath]
-> [FilePath]
excludePaths _ [] = []
excludePaths [] paths = paths
excludePaths patterns paths = go $ compile' <$> joinPatterns patterns
where
go Nothing = paths
go (Just regex) = L.filter (isNothing . match' regex . T.pack) paths