packages feed

filepather (empty) → 0.3.0

raw patch · 10 files changed

+817/−0 lines, 10 filesdep +basedep +comonaddep +comonad-transformerssetup-changed

Dependencies added: base, comonad, comonad-transformers, data-lens, directory, filepath, mtl, transformers

Files

+ LICENSE view
@@ -0,0 +1,27 @@+Copyright 2012-2014 Tony Morris++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:+1. Redistributions of source code must retain the above copyright+   notice, this list of conditions and the following disclaimer.+2. Redistributions in binary form must reproduce the above copyright+   notice, this list of conditions and the following disclaimer in the+   documentation and/or other materials provided with the distribution.+3. Neither the name of the author nor the names of his contributors+   may be used to endorse or promote products derived from this software+   without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,3 @@+import Distribution.Simple+main = defaultMain+
+ filepather.cabal view
@@ -0,0 +1,48 @@+Name:               filepather+Version:            0.3.0+Author:             Tony Morris <ʇǝu˙sıɹɹoɯʇ@ןןǝʞsɐɥ>+Maintainer:         Tony Morris <ʇǝu˙sıɹɹoɯʇ@ןןǝʞsɐɥ>+Copyright:          Tony Morris+License:            BSD3+License-File:       LICENSE+Synopsis:           Functions on System.FilePath+Category:           System+Description:+  Functions over @System.FilePath@ including a find function for recursing down directories.+Homepage:           https://github.com/tonymorris/filepather+Cabal-version:      >= 1.6+Build-Type:         Simple++Flag                small_base+  Description:      Choose the new, split-up base package.++Library+  Build-Depends:+                    base < 5 && >= 3,+                    directory >= 1.1,+                    filepath >= 1.2,+                    mtl >= 2,+                    comonad >= 1.1,+                    transformers >= 0.2,+                    data-lens >= 2.9,+                    comonad-transformers >= 2++  GHC-Options:+                    -Wall++  Hs-Source-Dirs:+                    src++  Exposed-Modules:+                    System.FilePath.FilePather+                    System.FilePath.FilePather.FileType+                    System.FilePath.FilePather.RecursePredicate+                    System.FilePath.FilePather.FilterPredicate+                    System.FilePath.FilePather.FilePathPredicate+                    System.FilePath.FilePather.Find+                    System.FilePath.FilePather.LiftI++Source-Repository  head+  type: git+  location: git@github.com:tonymorris/filepather.git+
+ src/System/FilePath/FilePather.hs view
@@ -0,0 +1,9 @@+module System.FilePath.FilePather(module X) where++import System.FilePath.FilePather.FileType as X+import System.FilePath.FilePather.RecursePredicate as X+import System.FilePath.FilePather.FilterPredicate as X+import System.FilePath.FilePather.FilePathPredicate as X+import System.FilePath.FilePather.Find as X+import System.FilePath.FilePather.LiftI as X+
+ src/System/FilePath/FilePather/FilePathPredicate.hs view
@@ -0,0 +1,270 @@+module System.FilePath.FilePather.FilePathPredicate+(+  FilePathPredicate(..)+) where++import qualified System.FilePath as P+import System.FilePath.FilePather.RecursePredicate+import System.FilePath.FilePather.FilterPredicate+import Control.Monad+import qualified Data.Foldable as F++-- | Functions that are common to predicates that work on 'FilePath' values.+class FilePathPredicate f where+  -- | A predicate that always succeeds.+  always ::+    Monad g =>+    f g+  -- | A predicate that always fails.+  never ::+    Monad g =>+    f g+  -- | Return a predicate that succeeds only if the two given predicates succeed.+  (.&&.) ::+    Monad g =>+    f g+    -> f g+    -> f g+  -- | Return a predicate that succeeds if any of the two given predicates succeed.+  (.||.) ::+    Monad g =>+    f g+    -> f g+    -> f g+  -- | Negates the given predicate.+  (.!.) ::+    Monad g =>+    f g+    -> f g+  -- | Folds the predicates on disjunction.+  anyof ::+    (F.Foldable t, Monad g) =>+    t (f g)+    -> f g+  -- | Folds the predicates on conjunction.+  anyof =+    F.foldr (.||.) never+  allof ::+    (F.Foldable t, Monad g) =>+    t (f g)+    -> f g+  allof =+    F.foldr (.&&.) always+  -- | A predicate that computes its result based on a file name extension.+  extension ::+    Monad g =>+    (FilePath -> Bool)+    -> f g+  -- | A predicate that computes its result based on equivalence to a file name extension. This function matches with and without the preceding extension separator (.).+  extensionEq ::+    Monad g =>+    FilePath+    -> f g+  extensionEq p =+    extension (== p)+  -- | A predicate that computes its result based on equivalence to one of a list of file name extensions.+  extensionOneof ::+    (F.Foldable t, Monad g) =>+    t FilePath+    -> f g+  extensionOneof =+    F.foldr (\a b -> extensionEq a .||. b) never+  -- | A predicate that computes its result based on inequivalence to any of a list of file name extensions.+  extensionNoneof ::+    (F.Foldable t, Monad g) =>+    t FilePath+    -> f g+  extensionNoneof =+    F.foldr (\a b -> (.!.) (extensionEq a) .&&. b) always+  -- | A predicate that computes its result based on a directory.+  directory ::+    Monad g =>+    (FilePath -> Bool)+    -> f g+  -- | A predicate that succeeds if its 'FilePath' has an extension.+  hasExtension ::+    Monad g =>+    f g+  hasExtension =+    (.!.) notHasExtension+  -- | A predicate that succeeds if its 'FilePath' does not have an extension.+  notHasExtension ::+    Monad g =>+    f g+  notHasExtension =+    (.!.) hasExtension+  -- | A predicate that computes its result based on the splitting of a name and extension.+  splitExtension ::+    Monad g =>+    (String -> String -> Bool)+    -> f g+  -- | A predicate that computes its result based on the splitting of a name into directories.+  splitDirectories ::+    Monad g =>+    ([FilePath] -> Bool)+    -> f g+  -- | A predicate that succeeds if its 'FilePath' has a trailing path separator.+  hasTrailingPathSeparator ::+    Monad g =>+    f g+  hasTrailingPathSeparator =+    (.!.) notHasTrailingPathSeparator+  -- | A predicate that succeeds if its 'FilePath' does not have a trailing path separator.+  notHasTrailingPathSeparator::+    Monad g =>+    f g+  notHasTrailingPathSeparator =+    (.!.) hasTrailingPathSeparator+  -- | A predicate that computes its result based on the file name.+  fileName ::+    Monad g =>+    (FilePath -> Bool)+    -> f g+  -- | A predicate that computes its result based on the base name.+  baseName ::+    Monad g =>+    (FilePath -> Bool)+    -> f g+  -- | A predicate that computes its result based on the normalised file name.+  normalise ::+    Monad g =>+    (FilePath -> Bool)+    -> f g+  -- | A predicate that computes its result based on the file name having been made valid.+  makeValid ::+    Monad g =>+    (FilePath -> Bool)+    -> f g+  -- | A predicate that succeeds if its 'FilePath' is relative.+  isRelative ::+    Monad g =>+    f g+  isRelative =+    (.!.) isNotRelative+  -- | A predicate that succeeds if its 'FilePath' is not relative.+  isNotRelative ::+    Monad g =>+    f g+  isNotRelative =+    (.!.) isRelative+  -- | A predicate that succeeds if its 'FilePath' is absolute.+  isAbsolute ::+    Monad g =>+    f g+  isAbsolute =+    (.!.) isNotAbsolute+  -- | A predicate that succeeds if its 'FilePath' is not absolute.+  isNotAbsolute ::+    Monad g =>+    f g+  isNotAbsolute =+    (.!.) isAbsolute+  -- | A predicate that succeeds if its 'FilePath' is valid.+  isValid ::+    Monad g =>+    f g+  isValid =+    (.!.) isNotValid+  -- | A predicate that succeeds if its 'FilePath' is not valid.+  isNotValid ::+    Monad g =>+    f g+  isNotValid =+    (.!.) isValid++instance FilePathPredicate RecursePredicateT where+  always =+    recursePredicateT . const . return $ True+  never =+    recursePredicateT . const . return $ False+  f .&&. g =+    recursePredicateT $ \p -> do r <- runRecursePredicateT f p+                                 if r+                                   then+                                     runRecursePredicateT g p+                                   else+                                     return False+  f .||. g =+    recursePredicateT $ \p -> do r <- runRecursePredicateT f p+                                 if r+                                   then+                                     return True+                                   else+                                     runRecursePredicateT g p+  (.!.) f =+    recursePredicateT $ liftM not . runRecursePredicateT f+  extension f = +    recursePredicateT $ return . liftM2 (||) f (f . drop 1) . P.takeExtension+  directory f = +    recursePredicateT $ return . f . P.takeDirectory+  hasExtension =+    recursePredicateT $ return . P.hasExtension+  splitExtension f =+    recursePredicateT $ return . uncurry f . P.splitExtension+  splitDirectories f = +    recursePredicateT $ return . f . P.splitDirectories+  hasTrailingPathSeparator =+    recursePredicateT $ return . P.hasTrailingPathSeparator+  fileName f = +    recursePredicateT $ return . f . P.takeFileName+  baseName f = +    recursePredicateT $ return . f . P.takeBaseName+  normalise f = +    recursePredicateT $ return . f . P.normalise+  makeValid f = +    recursePredicateT $ return . f . P.makeValid+  isRelative =+    recursePredicateT $ return . P.isRelative+  isAbsolute =+    recursePredicateT $ return . P.isAbsolute+  isValid =+    recursePredicateT $ return . P.isValid++instance FilePathPredicate FilterPredicateT where+  always =+    filterPredicateT . const . const . return $ True+  never =+    filterPredicateT . const . const . return $ False+  f .&&. g =+    filterPredicateT $ \p k -> do r <- runFilterPredicateT f p k+                                  if r+                                    then+                                      runFilterPredicateT g p k+                                    else+                                      return False+  f .||. g =+    filterPredicateT $ \p k -> do r <- runFilterPredicateT f p k+                                  if r+                                    then+                                      return True+                                    else+                                      runFilterPredicateT g p k+  (.!.) f =+    filterPredicateT $ \p -> liftM not . runFilterPredicateT f p+  extension f = +    filterPredicateT $ const . return . liftM2 (||) f (f . drop 1) . P.takeExtension+  directory f = +    filterPredicateT $ const . return . f . P.takeDirectory+  hasExtension =+    filterPredicateT $ const . return . P.hasExtension+  splitExtension f =+    filterPredicateT $ const . return . uncurry f . P.splitExtension+  splitDirectories f = +    filterPredicateT $ const . return . f . P.splitDirectories+  hasTrailingPathSeparator =+    filterPredicateT $ const . return . P.hasTrailingPathSeparator+  fileName f = +    filterPredicateT $ const . return . f . P.takeFileName+  baseName f = +    filterPredicateT $ const . return . f . P.takeBaseName+  normalise f = +    filterPredicateT $ const . return . f . P.normalise+  makeValid f = +    filterPredicateT $ const . return . f . P.makeValid+  isRelative =+    filterPredicateT $ const . return . P.isRelative+  isAbsolute =+    filterPredicateT $ const . return . P.isAbsolute+  isValid =+    filterPredicateT $ const . return . P.isValid+
+ src/System/FilePath/FilePather/FileType.hs view
@@ -0,0 +1,32 @@+module System.FilePath.FilePather.FileType+(+  FileType(..)+, isFile+, isDirectory+, isUnknown+) where+-- | The possible types of a file.+data FileType =+  File -- ^ The type is a normal file.+  | Directory -- ^ The type is a directory.+  | Unknown -- ^ The type is unknown.+  deriving (Eq, Ord, Show, Enum)++isFile ::+  FileType+  -> Bool+isFile =+  (==) File++isDirectory ::+  FileType+  -> Bool+isDirectory =+  (==) Directory++isUnknown ::+  FileType+  -> Bool+isUnknown =+  (==) Unknown+
+ src/System/FilePath/FilePather/FilterPredicate.hs view
@@ -0,0 +1,88 @@+module System.FilePath.FilePather.FilterPredicate+(+  FilterPredicateT+, FilterPredicate+, filterPredicateT+, filterPredicate+, filterPredicateT'+, filterPredicate'+, runFilterPredicateT+, runFilterPredicate+, isDirectoryType+, isFileType+, isUnknownType+) where++import Control.Monad.Identity+import System.FilePath.FilePather.FileType++newtype FilterPredicateT f =+  FilterPredicateT (FilePath -> FileType -> f Bool)++-- | A filter predicate that does not require effects to compute its result.+type FilterPredicate =+  FilterPredicateT Identity++-- | A filter predicate takes a 'FilePath' and a file type and returns whether or not to filter the value.+filterPredicateT ::+  (FilePath -> FileType -> f Bool)+  -> FilterPredicateT f+filterPredicateT =+  FilterPredicateT++-- | Construct a filter predicate that does not require effects to compute its result.+filterPredicate ::+  (FilePath -> FileType -> Bool)+  -> FilterPredicate+filterPredicate f =+  filterPredicateT (\z -> Identity . f z)++-- | A filter predicate takes a 'FilePath' and returns whether or not to filter the value.+filterPredicateT' ::+  (FilePath -> f Bool)+  -> FilterPredicateT f+filterPredicateT' f =+  filterPredicateT (const . f)++-- | Construct a filter predicate that does not require effects to compute its result.+filterPredicate' ::+  (FilePath -> Bool)+  -> FilterPredicate+filterPredicate' f =+  filterPredicate (const . f)++-- | Extract the filter predicate function.+runFilterPredicateT ::+  FilterPredicateT f+  -> FilePath+  -> FileType+  -> f Bool+runFilterPredicateT (FilterPredicateT f) =+  f++-- | Construct a filter predicate that does not require effects to compute its result.+runFilterPredicate ::+  FilterPredicate+  -> FilePath+  -> FileType+  -> Bool+runFilterPredicate p k =+  runIdentity . runFilterPredicateT p k++isDirectoryType ::+  Monad f =>+  FilterPredicateT f+isDirectoryType =+  filterPredicateT . const $ return . isDirectory++isFileType ::+  Monad f =>+  FilterPredicateT f+isFileType =+  filterPredicateT . const $ return . isFile++isUnknownType ::+  Monad f =>+  FilterPredicateT f+isUnknownType =+  filterPredicateT . const $ return . isUnknown
+ src/System/FilePath/FilePather/Find.hs view
@@ -0,0 +1,255 @@+module System.FilePath.FilePather.Find+(+  Find(..)+, findi+, findpi+, FindR+, foundR+, dropR+, recurseR+, noRecurseR+, foundL+, dropL+, recurseL+, noRecurseL+) where++import Control.Monad.Identity+import Control.Monad.Trans.Identity+import Control.Comonad+import Control.Comonad.Trans.Store+import Data.Lens.Partial.Common hiding (null)+import System.FilePath+import System.FilePath.FilePather.RecursePredicate+import System.FilePath.FilePather.FilterPredicate+import System.FilePath.FilePather.FileType+import System.Directory++class Find f where+  -- | Finds all files using the given recurse predicate and filter predicate in the given file path.+  find ::+    FilterPredicateT f+    -> RecursePredicateT f+    -> FilePath+    -> IO [FindR]+  -- | Find files in the current directory.+  findHere ::+    FilterPredicateT f+    -> RecursePredicateT f+    -> IO [FindR]+  findHere f r =+    getCurrentDirectory >>= find f r+  -- | Finds all files using the given recurse predicate and filter predicate in the given file path.+  findp ::+    FilterPredicateT f+    -> RecursePredicateT f+    -> FilePath+    -> IO [FilePath]+  findp f r =+    liftM (\x -> x >>= \w ->+      case w of+        Found p _   -> [p]+        Drop _ _    -> []+        Recurse _   -> []+        NoRecurse _ -> []) . find f r+  -- | Find files in the current directory.+  findpHere ::+    FilterPredicateT f+    -> RecursePredicateT f+    -> IO [FilePath]+  findpHere f r =+    getCurrentDirectory >>= findp f r++instance Find Identity where+  find f' r' =+    let find' base p =+          let f =+                runFilterPredicateT f'+              r =+                runRecursePredicateT r'+              z ::+                FilePath+              z =+                if null base then p else base </> p+              keep ::+                Bool+                -> FileType+                -> FindR+              keep u =+                (if u then Found else Drop) z+              rkeep ::+                Bool+                -> FindR+              rkeep u =+                (if u then Recurse else NoRecurse) z+              tkeep ::+                FileType+                -> [FindR]+              tkeep t =+                [keep (runIdentity (f z t)) t]+          in do fe <- doesFileExist z+                if fe+                  then+                    return (tkeep File)+                  else+                    do de <- doesDirectoryExist z+                       if de+                         then+                           let (Identity k) = f z Directory+                               (Identity l) = r z+                           in liftM ([rkeep l, keep k Directory] ++) $+                                if l+                                  then+                                    do t <- getDirectoryContents z+                                       u <- forM (filter (`notElem` [".", ".."]) t) (find f' r' . (z </>))+                                       return (concat u)+                                  else+                                    return []+                         else+                           return (tkeep Unknown)+    in find' []++instance Find IO where+  find f' r' =+    let find' base p =+          let f =+                runFilterPredicateT f'+              r =+                runRecursePredicateT r'+              z ::+                FilePath+              z =+                if null base then p else base </> p+              keep ::+                Bool+                -> FileType+                -> FindR+              keep u =+                (if u then Found else Drop) z+              rkeep ::+                Bool+                -> FindR+              rkeep u =+                (if u then Recurse else NoRecurse) z+              tkeep ::+                FileType+                -> IO [FindR]+              tkeep t =+                f z t >>= \y -> return [keep y t]+          in do fe <- doesFileExist z+                if fe+                  then+                    tkeep File+                  else+                    do de <- doesDirectoryExist z+                       if de+                         then+                           do k <- f z Directory+                              l <- r z+                              liftM ([rkeep l, keep k Directory] ++) $+                                if l+                                  then+                                    do t <- getDirectoryContents z+                                       u <- forM (filter (`notElem` [".", ".."]) t) (find f' r' . (z </>))+                                       return (concat u)+                                  else+                                    return []+                         else+                           tkeep Unknown+    in find' []++instance Comonad f => Find (IdentityT f) where+  find f r =+    find (filterPredicateT $ \p -> Identity . extract . runFilterPredicateT f p) (recursePredicateT $ Identity . extract . runRecursePredicateT r)++-- | A specialisation of `find` to the `Identity` monad. Useful in assisting type-inference.+findi ::+  FilterPredicate+  -> RecursePredicate+  -> FilePath+  -> IO [FindR]+findi =+  find++-- | A specialisation of `findp` to the `Identity` monad. Useful in assisting type-inference.+findpi ::+  FilterPredicate+  -> RecursePredicate+  -> FilePath+  -> IO [FilePath]+findpi =+  findp++-- | The results of a path find. One of+--+-- * @found@ with the file path name and file type.+--+-- * @drop@ with the file path name and file type.+--+-- * @recurse@ with the file path (the file type is always directory).+--+-- * @no-recurse@ with the file path (the file type is always directory).+data FindR =+  Found FilePath FileType+  | Drop FilePath FileType+  | Recurse FilePath+  | NoRecurse FilePath+  deriving (Eq, Show)++foundR ::+  FilePath+  -> FileType+  -> FindR+foundR =+  Found++dropR ::+  FilePath+  -> FileType+  -> FindR+dropR =+  Drop++recurseR ::+  FilePath+  -> FindR+recurseR =+  Recurse++noRecurseR ::+  FilePath+  -> FindR+noRecurseR =+  NoRecurse++foundL ::+  PartialLens FindR (FilePath, FileType)+foundL =+  PLens $ \r ->+    case r of+      Found p t -> Just (store (uncurry Found) (p, t))+      _         -> Nothing++dropL ::+  PartialLens FindR (FilePath, FileType)+dropL =+  PLens $ \r ->+    case r of+      Drop p t -> Just (store (uncurry Drop) (p, t))+      _        -> Nothing++recurseL ::+  PartialLens FindR FilePath+recurseL =+  PLens $ \r ->+    case r of+      Recurse p -> Just (store Recurse p)+      _         -> Nothing++noRecurseL ::+  PartialLens FindR FilePath+noRecurseL =+  PLens $ \r ->+    case r of+      NoRecurse p -> Just (store NoRecurse p)+      _           -> Nothing
+ src/System/FilePath/FilePather/LiftI.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}++module System.FilePath.FilePather.LiftI+(+  LiftI(..)+) where++import System.FilePath.FilePather.RecursePredicate+import System.FilePath.FilePather.FilterPredicate++-- | A type-class for lifting a value.+-- This type-class probably belongs elsewhere (pointers appreciated!).+class LiftI f a | f -> a where+  liftI ::+    Monad g =>+    g a+    -> f g++instance LiftI RecursePredicateT Bool where+  liftI = +    recursePredicateT . const++instance LiftI FilterPredicateT Bool where+  liftI = +    filterPredicateT . const . const+
+ src/System/FilePath/FilePather/RecursePredicate.hs view
@@ -0,0 +1,59 @@+module System.FilePath.FilePather.RecursePredicate+(+  RecursePredicateT+, RecursePredicate+, recursePredicateT+, recursePredicate+, runRecursePredicateT+, runRecursePredicate+, toFilterPredicate+) where++import Control.Monad.Identity+import System.FilePath.FilePather.FilterPredicate++-- | A recurse predicate takes a 'FilePath', which is a directory, and returns whether or not to continue recursing down on that directory.+newtype RecursePredicateT f =+  RecursePredicateT (FilePath -> f Bool)++-- | A recurse predicate that does not require effects to compute its result.+type RecursePredicate =+  RecursePredicateT Identity++-- | Construct a recurse predicate. The most general construction function.+recursePredicateT ::+  (FilePath -> f Bool)+  -> RecursePredicateT f+recursePredicateT =+  RecursePredicateT++-- | Construct a recurse predicate that does not require effects to compute its result.+recursePredicate ::+  (FilePath -> Bool)+  -> RecursePredicate+recursePredicate f =+  recursePredicateT (Identity . f)++-- | Extract the recurse predicate function.+runRecursePredicateT ::+  RecursePredicateT f+  -> FilePath+  -> f Bool+runRecursePredicateT (RecursePredicateT f) =+  f++-- | Extract the recurse predicate function that does not require effects to compute its result.+runRecursePredicate ::+  RecursePredicate+  -> FilePath+  -> Bool+runRecursePredicate p =+  runIdentity . runRecursePredicateT p++-- | Convert the recurse predicate to a filter predicate.+toFilterPredicate ::+  RecursePredicateT f+  -> FilterPredicateT f+toFilterPredicate (RecursePredicateT f) =+  filterPredicateT (const . f)+