pathwalk 0.2.1.0 → 0.3.0.0
raw patch · 5 files changed
+78/−25 lines, 5 filesdep ~base
Dependency ranges changed: base
Files
- examples/basic/Main.hs +15/−0
- examples/example/Main.hs +0/−15
- examples/lazy/Main.hs +16/−0
- pathwalk.cabal +14/−4
- src/System/Directory/PathWalk.hs +33/−6
+ examples/basic/Main.hs view
@@ -0,0 +1,15 @@+module Main (main) where++import Control.Monad (forM_)+import System.Directory.PathWalk (pathWalk)+import System.Environment (getArgs)++main :: IO ()+main = do+ rawArgs <- getArgs+ let args = if rawArgs == [] then ["."] else rawArgs+ forM_ args $ \arg -> do+ pathWalk arg $ \root dirs files -> do+ putStrLn root+ putStrLn $ " dirs: " ++ show dirs+ putStrLn $ " files: " ++ show files
− examples/example/Main.hs
@@ -1,15 +0,0 @@-module Main (main) where--import Control.Monad (forM_)-import System.Directory.PathWalk (pathWalk)-import System.Environment (getArgs)--main :: IO ()-main = do- rawArgs <- getArgs- let args = if rawArgs == [] then ["."] else rawArgs- forM_ args $ \arg -> do- pathWalk arg $ \root dirs files -> do- putStrLn root- putStrLn $ " dirs: " ++ show dirs- putStrLn $ " files: " ++ show files
+ examples/lazy/Main.hs view
@@ -0,0 +1,16 @@+module Main (main) where++import Control.Monad (forM_)+import System.Directory.PathWalk (pathWalkLazy)+import System.Environment (getArgs)++main :: IO ()+main = do+ rawArgs <- getArgs+ let args = if rawArgs == [] then ["."] else rawArgs+ forM_ args $ \arg -> do+ results <- pathWalkLazy arg+ forM_ results $ \(root, dirs, files) -> do+ putStrLn root+ putStrLn $ " dirs: " ++ show dirs+ putStrLn $ " files: " ++ show files
pathwalk.cabal view
@@ -1,5 +1,5 @@ name: pathwalk-version: 0.2.1.0+version: 0.3.0.0 synopsis: Path walking utilities for Haskell programs description: Simple directory tree walking utilities. license: MIT@@ -44,16 +44,26 @@ default-language: Haskell2010 ghc-options: -Wall -executable example+test-suite basic+ type: exitcode-stdio-1.0 main-is: Main.hs build-depends: base, pathwalk- hs-source-dirs: examples/example+ hs-source-dirs: examples/basic default-language: Haskell2010 ghc-options: -Wall -executable stoprecursing+test-suite stoprecursing+ type: exitcode-stdio-1.0 main-is: Main.hs build-depends: base, pathwalk hs-source-dirs: examples/stoprecursing+ default-language: Haskell2010+ ghc-options: -Wall++test-suite lazy+ type: exitcode-stdio-1.0+ main-is: Main.hs+ build-depends: base, pathwalk+ hs-source-dirs: examples/lazy default-language: Haskell2010 ghc-options: -Wall
src/System/Directory/PathWalk.hs view
@@ -5,18 +5,21 @@ , pathWalk , WalkStatus(..) , pathWalkInterruptible+ , pathWalkLazy ) where -import Control.Monad (forM_, filterM)+import Control.Monad (forM, forM_, filterM)+import Control.Monad.IO.Class (MonadIO, liftIO) import System.Directory (doesDirectoryExist, doesFileExist, getDirectoryContents) import System.FilePath ((</>)) import Control.Monad.Trans.Maybe (MaybeT(..), runMaybeT)+import System.IO.Unsafe (unsafeInterleaveIO) -- | Called with a directory, list of relative subdirectories, and a -- list of file names. If using 'pathWalk', the callback always -- returns '()'. If using 'pathWalkInterruptible', it returns whether -- to continue, prevent recursing further, or stop traversal entirely.-type Callback a = FilePath -> [FilePath] -> [FilePath] -> IO a+type Callback m a = FilePath -> [FilePath] -> [FilePath] -> m a -- | 'pathWalk' recursively enumerates the given root directory, -- calling callback once per directory with the traversed directory@@ -31,7 +34,7 @@ -- when ("Test.hs" \`isSuffixOf\` file) $ do -- registerTestFile $ dir \</\> file -- @-pathWalk :: FilePath -> Callback () -> IO ()+pathWalk :: MonadIO m => FilePath -> Callback m () -> m () pathWalk root callback = do pathWalkInterruptible root $ \dir dirs files -> do callback dir dirs files@@ -45,14 +48,20 @@ | Stop -- ^ Stop recursing entirely. deriving (Show, Eq) -pathWalkInternal :: FilePath -> Callback WalkStatus -> IO (Maybe ())-pathWalkInternal root callback = do+readDirsAndFiles :: FilePath -> IO ([FilePath], [FilePath])+readDirsAndFiles root = do names <- getDirectoryContents root let properNames = filter (`notElem` [".", ".."]) names dirs <- filterM (\n -> doesDirectoryExist $ root </> n) properNames files <- filterM (\n -> doesFileExist $ root </> n) properNames+ + return (dirs, files) +pathWalkInternal :: MonadIO m => FilePath -> Callback m WalkStatus -> m (Maybe ())+pathWalkInternal root callback = do+ (dirs, files) <- liftIO $ readDirsAndFiles root+ result <- callback root dirs files case result of Continue -> do@@ -67,7 +76,25 @@ -- | Traverses a directory tree, just like 'pathWalk', except that -- the callback can determine whether to continue traversal. See -- 'WalkStatus'.-pathWalkInterruptible :: FilePath -> Callback WalkStatus -> IO ()+pathWalkInterruptible :: MonadIO m => FilePath -> Callback m WalkStatus -> m () pathWalkInterruptible root callback = do _ <- pathWalkInternal root callback return ()++-- | The lazy version of 'pathWalk'. Instead of running a callback+-- per directory, it returns a lazy list that reads from the+-- filesystem as the list is evaluated.+--+-- 'pathWalkLazy' does not allow selective recursion. For richer+-- functionality, see the directory-tree package at+-- https://hackage.haskell.org/package/directory-tree+pathWalkLazy :: MonadIO m => FilePath -> m [(FilePath, [FilePath], [FilePath])]+pathWalkLazy root = liftIO $ unsafeInterleaveIO $ do+ (dirs, files) <- readDirsAndFiles root++ next <- unsafeInterleaveIO $ do+ allsubs <- forM dirs $ \dir -> do+ pathWalkLazy $ root </> dir+ return $ concat allsubs+ + return $ (root, dirs, files) : next