packages feed

find-conduit 0.2.2 → 0.2.3

raw patch · 3 files changed

+199/−37 lines, 3 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Data.Conduit.Find: (=~) :: FilePath -> Text -> Bool

Files

Data/Conduit/Find.hs view
@@ -1,43 +1,65 @@ {-# LANGUAGE RankNTypes #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ViewPatterns #-}  module Data.Conduit.Find-    ( FileEntry(..)-    , Predicate-    , HasFileInfo(..)-    , consider-    , entryPath-    , matchAll-    , ignoreAll+    (+    -- * Introduction+    -- $intro++    -- ** Basic comparison with GNU find+    -- $gnufind++    -- ** Performance+    -- $performance++    -- ** Other notes+    -- $notes++    -- * Finding functions+      find+    , find'+    , lfind+    , lfind'+    , findWithPreFilter+    , readPaths+    , stat+    , lstat+    , test++    -- * File path predicates     , ignoreVcs     , regex     , glob-    , stat-    , lstat-    , regular-    , hasMode-    , executable     , filename_     , filenameS_     , filepath_     , filepathS_+    , withPath+    , entryPath++    -- * File entry predicates (uses stat information)+    , regular+    , hasMode+    , executable     , depth     , lastAccessed     , lastModified-    , withPath     , withStatus-    , prune-    , test-    , find-    , find'-    , lfind-    , lfind'-    , findWithPreFilter-    , readPaths++    -- * Predicate combinators     , or_     , and_     , not_+    , prune+    , matchAll+    , ignoreAll+    , consider+    , (=~)++    -- * Types and type classes+    , FileEntry(..)+    , Predicate+    , HasFileInfo(..)     ) where  import Conduit@@ -55,8 +77,126 @@ import Prelude hiding (FilePath) import System.Posix.Files import System.Posix.Types-import Text.Regex.Posix ((=~))+import qualified Text.Regex.Posix as R ((=~)) +{- $intro++**find-conduit** is essentially a souped version of GNU find for Haskell,+using a DSL to provide both ease of us, and extensive flexbility.++In its simplest form, let's compare some uses of find to find-conduit.  Bear+in mind that the result of the find function is a conduit, so you're expected+to either sink it to a list, or operate on the file paths as they are yielded.+-}++{- $gnufind++A typical find command:++@+find src -name '*.hs' -type f -print+@++Would in find-conduit be:++@+find "src" (glob "*.hs" \<\> regular) $$ mapM_C (liftIO . print)+@++The 'glob' predicate matches the file basename against the globbing pattern,+while the 'regular' predicate matches plain files.++A more complicated example:++@+find . -size +100M -perm 644 -mtime 1+@++Now in find-conduit:++@+let megs = 1024 * 1024+    days = 86400+now <- liftIO getCurrentTime+find \".\" ( fileSize (> 100*megs)+        \<\> hasMode 0o644+        \<\> lastModified (> addUTCTime now (-(1*days)))+         )+@++Appending predicates like this expressing an "and" relationship.  Use '<|>' to+express "or".  You can also negate any predicate:++@+find \".\" (not_ (hasMode 0o644))+@++By default, predicates, whether matching or not, will allow recursion into+directories.  In order to express that matching predicate should disallow+recursion, use 'prune':++@+find \".\" (prune (depth (> 2)))+@++This is the same as using '-maxdepth 2' in find.++@+find \".\" (prune (filename_ (== "dist")))+@++This is the same as:++@+find . \\( -name dist -prune \\) -o -print+@+-}++{- $performance++find-conduit strives to make file-finding a well performing operation.  To+this end, a composed Predicate will only call stat once per entry being+considered; and if you prune a directory, it is not traversed at all.++By default, 'find' calls stat for every file before it applies the predicate,+in order to ensure that only one such call is needed.  Sometimes, however, you+know just from the FilePath that you don't want to consider a certain file, or+you want to prune a directory tree.++To support these types of optimized queries, a variant of find is provided+called 'findWithPreFilter'.  This takes two predicates: one that is applied to+only the FilePath, before stat (or lstat) is called; and one that is applied+to the full file information after the stat.+-}++{- $notes++Predicates form a Category and an Arrow, so you can use Arrow-style+composition rather than Monoids if you wish.  They also form an Applicative, a+Monad and a MonadPlus.++In the Monad, the value bound over is whatever the predicate chooses to return+(most Predicates return the same FilePath they examined, however, making the+Monad less value).  Here's an example Monad: If the find takes longer than 5+minutes, abort.  We could have used 'timeout', but this is for illustration.++@+start <- liftIO getCurrentTime+find \".\" $ do+    glob \"*.hs\"++    end <- liftIO getCurrentTime+    if diffUTCTIme end start > 300+        then ignoreAll+        else matchAll+@++The Predicate Monad is a short-circuiting monad, meaning we stop as soon as it+can be determined that the user is not interested in a given file.  To access+the current file, simply bind the result value from any Predicate.  To change+the file being matched against,for whatever reason, use 'consider'.+-}+ data FileInfo = FileInfo     { infoPath  :: FilePath     , infoDepth :: Int@@ -98,9 +238,23 @@   where     vcsDirs = [ ".git", "CVS", "RCS", "SCCS", ".svn", ".hg", "_darcs" ] --- | Find every entry whose filename part matching the given regular expression. regex :: (Monad m, HasFileInfo e) => Text -> Predicate m e-regex pat = filenameS_ (=~ unpack pat)+regex pat = filename_ (=~ pat)++-- | This is a re-export of 'Text.Regex.Posix.=~', with the types changed for+--   ease of use with this module.  For example, you can simply say:+--+-- @+--    filename_ (=~ "\\.hs$")+-- @+--+-- Which is the same thing as:+--+-- @+--    regex "\\.hs$"+-- @+(=~) :: FilePath -> Text -> Bool+str =~ pat = encodeString str R.=~ unpack pat  -- | Find every entry whose filename part matching the given filename globbing --   expression.  For example: @glob "*.hs"@.
Data/Conduit/Find/Looped.hs view
@@ -103,7 +103,7 @@             KeepAndRecurse b _ -> runLooped (k b) a  instance Monad m => Category (Looped m) where-    id = let x = Looped $ \a -> return $ KeepAndRecurse a x in x+    id = matchAll     Looped f . Looped g = Looped $ \a -> do           r <- g a           case r of@@ -139,15 +139,15 @@  -- | Within a predicate block, 'consider' a different item than what is --   currently being predicated upon.  This makes it possible to write custom---   logic within the Monad instance for Looped, such as in this contrived---   example:+--   logic within the Monad instance for a predicate, such as in this+--   contrived example: -- -- @---   flip runLooped "bar.hs" $ do---       x <- filename_ (== "foo.hs")---       when (x /= "") $---           consider "baz.hs" $---               filename_ (== "baz.hs")    -- passes+--   flip runLooped \"bar.hs\" $ do+--       x <- filename_ (== \"foo.hs\")+--       when (x /= \"\") $+--           consider \"baz.hs\" $+--               filename_ (== \"baz.hs\") -- @ consider :: a -> Looped m a b -> Looped m a b consider x l = Looped $ const $ runLooped l x@@ -242,7 +242,7 @@     f `mappend` g = f <> g  instance Monad m => MonadPlus (Looped m a) where-    mzero = Looped $ const $ return Ignore+    mzero = ignoreAll     Looped f `mplus` Looped g = Looped $ \a -> do         r <- f a         case r of@@ -251,11 +251,18 @@             RecurseOnly _ -> g a             KeepAndRecurse b m -> return $ KeepAndRecurse b m +-- | 'matchAll' is id in the 'Predicate' Category. matchAll :: Monad m => Predicate m a matchAll = Looped $ \entry -> return $ KeepAndRecurse entry matchAll +-- | 'ignore' rejects the current entry, but allows recursion.+ignore :: Monad m => Looped m a b+ignore = Looped $ const $ return $ RecurseOnly ignore++-- | 'ignoreAll' rejects every entry, and does not recurse.  This is the same+--   as 'mzero'. ignoreAll :: Monad m => Looped m a b-ignoreAll = Looped $ const $ return $ RecurseOnly ignoreAll+ignoreAll = Looped $ const $ return Ignore  -- | 'not_' reverse the meaning of the given predicate, preserving recursion. not_ :: MonadIO m => Predicate m a -> Predicate m a
find-conduit.cabal view
@@ -1,5 +1,5 @@ Name:                find-conduit-Version:             0.2.2+Version:             0.2.3 Synopsis:            A file-finding conduit that allows user control over traversals. License-file:        LICENSE License:             MIT@@ -9,7 +9,8 @@ Cabal-Version:       >=1.10 Category:            System Description:-  A file-finding conduit that allows user control over traversals.+  A file-finding conduit that allows user control over traversals.  Please see+  the module 'Data.Conduit.Find' for more information.  Source-repository head   type: git