-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/
-- | A simple directory-like tree datatype, with useful IO functions
--
-- A simple directory-like tree datatype, with useful IO functions and
-- Foldable and Traversable instance
--
-- Provides a simple data structure mirroring a directory tree on the
-- filesystem, as well as useful functions for reading and writing file
-- and directory structures in the IO monad.
--
-- Importing the library and optional (useful) Foldable and Traverable
-- libraries:
--
--
-- import System.Directory.Tree
-- import qualified Data.Foldable as F
-- import qualified Data.Traversable as T
--
--
-- Write a hand-made directory tree of textfiles (strings) to the disk.
-- Simulates creating a new user Tux's home directory on a unix machine:
--
--
-- writeDirectory$ "/home" :/ Dir "Tux" [File "README" "Welcome!"]
--
--
-- "read" a directory by opening all the files at a filepath with
-- readFile, returning an 'AnchoredDirTree String' (d2). Then check for
-- any IO failures:
--
--
-- do (base :/ d2) <- readDirectory "../parent_dir/dir2/"
-- let failed = anyFailed d2
-- if failed then ...
--
--
-- Use Foldable instance function to concat a directory dir of
-- text files into a single file under the same directory:
--
--
-- do (b :/ dt) <- readDirectory dir
-- let f = F.concat dt
-- return$ b :/ File "ALL_TEXT" f
--
--
-- Open all the files in the current directory as lazy bytestrings,
-- ignoring the base path in Anchored wrapper:
--
--
-- import qualified Data.ByteString.Lazy as B
-- do (_ :/ dTree) <- readDirectoryWith B.readFile "./"
--
--
-- This version also offers an experimental function
-- readDirectoryWithL that does lazy directory IO, allowing you to
-- treat the returned DirTree as if it were a normal
-- lazily-generated data structure.
--
-- For example, the following does only the amount of IO necessary to
-- list the file names of the children of the root directory, similar to
-- "ls /":
--
--
-- do d <- readDirectoryWithL readFile "/"
-- mapM_ (putStrLn . name) $ contents $ free d
--
--
-- Any ideas or suggestions for improvements are most welcome :-)
--
-- CHANGES: from 0.11
--
--
@package directory-tree
@version 0.12.1
-- | Provides a simple data structure mirroring a directory tree on the
-- filesystem, as well as useful functions for reading and writing file
-- and directory structures in the IO monad.
--
-- Errors are caught in a special constructor in the DirTree type.
--
-- Defined instances of Functor, Traversable and Foldable allow for
-- easily operating on a directory of files. For example, you could use
-- Foldable.foldr to create a hash of the entire contents of a directory.
--
-- The functions readDirectoryWithL and buildL allow for
-- doing directory-traversing IO lazily as required by the execution of
-- pure code. This allows you to treat large directories the same way as
-- you would a lazy infinite list.
--
-- The AnchoredDirTree type is a simple wrapper for DirTree to keep track
-- of a base directory context for the DirTree.
--
-- Please send me any requests, bugs, or other feedback on this module!
module System.Directory.Tree
-- | the String in the name field is always a file name, never a full path.
-- The free type variable is used in the File constructor and can hold
-- Handles, Strings representing a file's contents or anything else you
-- can think of. We catch any IO errors in the Failed constructor. an
-- Exception can be converted to a String with show.
data DirTree a
Failed :: FileName -> IOException -> DirTree a
[name] :: DirTree a -> FileName
[err] :: DirTree a -> IOException
Dir :: FileName -> [DirTree a] -> DirTree a
[name] :: DirTree a -> FileName
[contents] :: DirTree a -> [DirTree a]
File :: FileName -> a -> DirTree a
[name] :: DirTree a -> FileName
[file] :: DirTree a -> a
-- | a simple wrapper to hold a base directory name, which can be either an
-- absolute or relative path. This lets us give the DirTree a context,
-- while still letting us store only directory and file names (not
-- full paths) in the DirTree. (uses an infix constructor; don't be
-- scared)
data AnchoredDirTree a
(:/) :: FilePath -> DirTree a -> AnchoredDirTree a
[anchor] :: AnchoredDirTree a -> FilePath
[dirTree] :: AnchoredDirTree a -> DirTree a
-- | an element in a FilePath:
type FileName = String
-- | Build an AnchoredDirTree, given the path to a directory, opening the
-- files using readFile. Uses readDirectoryWith readFile
-- internally and has the effect of traversing the entire directory
-- structure. See readDirectoryWithL for lazy production of a
-- DirTree structure.
readDirectory :: FilePath -> IO (AnchoredDirTree String)
-- | Build a DirTree rooted at p and using f to
-- fill the file field of File nodes.
--
-- The FilePath arguments to f will be the full path to
-- the current file, and will include the root p as a prefix.
-- For example, the following would return a tree of full
-- FilePaths like "../tmp/foo" and "../tmp/bar/baz":
--
--
-- readDirectoryWith return "../tmp"
--
--
-- Note though that the build function below already does this.
readDirectoryWith :: (FilePath -> IO a) -> FilePath -> IO (AnchoredDirTree a)
-- | A "lazy" version of readDirectoryWith that does IO operations
-- as needed i.e. as the tree is traversed in pure code.
--
-- NOTE: This function uses unsafeInterleaveIO under the
-- hood. This means that:
--
--
-- - side effects are tied to evaluation order and only run on
-- demand
-- - you might receive exceptions in pure code
--
readDirectoryWithL :: (FilePath -> IO a) -> FilePath -> IO (AnchoredDirTree a)
-- | write a DirTree of strings to disk. Clobbers files of the same name.
-- Doesn't affect files in the directories (if any already exist) with
-- different names. Returns a new AnchoredDirTree where failures were
-- lifted into a Failed constructor:
writeDirectory :: AnchoredDirTree String -> IO (AnchoredDirTree ())
-- | writes the directory structure to disk and uses the provided function
-- to write the contents of Files to disk. The return value of
-- the function will become the new contents of the returned,
-- where IO errors at each node are replaced with Failed
-- constructors. The returned tree can be compared to the passed tree to
-- see what operations, if any, failed:
writeDirectoryWith :: (FilePath -> a -> IO b) -> AnchoredDirTree a -> IO (AnchoredDirTree b)
-- | builds a DirTree from the contents of the directory passed to it,
-- saving the base directory in the Anchored* wrapper. Errors are caught
-- in the tree in the Failed constructor. The file fields
-- initially are populated with full paths to the files they are
-- abstracting.
build :: FilePath -> IO (AnchoredDirTree FilePath)
-- | identical to build but does directory reading IO lazily as
-- needed:
buildL :: FilePath -> IO (AnchoredDirTree FilePath)
-- | a simple application of readDirectoryWith openFile:
openDirectory :: FilePath -> IOMode -> IO (AnchoredDirTree Handle)
-- | writes the directory structure (not files) of a DirTree to the
-- anchored directory. Returns a structure identical to the supplied tree
-- with errors replaced by Failed constructors:
writeJustDirs :: AnchoredDirTree a -> IO (AnchoredDirTree a)
-- | tuple up the complete file path with the file contents, by
-- building up the path, trie-style, from the root. The filepath will be
-- relative to "anchored" directory.
--
-- This allows us to, for example, mapM_ uncurry writeFile over
-- a DirTree of strings, although writeDirectory does a better job
-- of this.
zipPaths :: AnchoredDirTree a -> DirTree (FilePath, a)
-- | DEPRECATED. Use record dirTree instead.
-- | Deprecated: Use record dirTree
free :: AnchoredDirTree a -> DirTree a
-- | Tests equality of two trees, ignoring their free variable portion. Can
-- be used to check if any files have been added or deleted, for
-- instance.
equalShape :: DirTree a -> DirTree b -> Bool
-- | a compare function that ignores the free "file" type variable:
comparingShape :: DirTree a -> DirTree b -> Ordering
-- | True if there are no Failed constructors in the tree
successful :: DirTree a -> Bool
-- | True if any Failed constructors in the tree
anyFailed :: DirTree a -> Bool
-- | returns true if argument is a Failed constructor:
failed :: DirTree a -> Bool
-- | returns a list of Failed constructors only:
failures :: DirTree a -> [DirTree a]
-- | maps a function to convert Failed DirTrees to Files or Dirs
failedMap :: (FileName -> IOException -> DirTree a) -> DirTree a -> DirTree a
-- | Flattens a DirTree into a (never empty) list of tree
-- constructors. Dir constructors will have [] as their
-- contents:
flattenDir :: DirTree a -> [DirTree a]
-- | Recursively sort a directory tree according to the Ord instance
sortDir :: (Ord a) => DirTree a -> DirTree a
-- | Recursively sort a tree as in sortDir but ignore the file
-- contents of a File constructor
sortDirShape :: DirTree a -> DirTree a
-- | applies the predicate to each constructor in the tree, removing it
-- (and its children, of course) when the predicate returns False. The
-- topmost constructor will always be preserved:
filterDir :: (DirTree a -> Bool) -> DirTree a -> DirTree a
-- | At Dir constructor, apply transformation function to all of
-- directory's contents, then remove the Nothing's and recurse. This
-- always preserves the topomst constructor.
transformDir :: (DirTree a -> DirTree a) -> DirTree a -> DirTree a
-- | If the argument is a Dir containing a sub-DirTree matching
-- FileName then return that subtree, appending the name of
-- the old root Dir to the anchor of the AnchoredDirTree
-- wrapper. Otherwise return Nothing.
dropTo :: FileName -> AnchoredDirTree a -> Maybe (AnchoredDirTree a)
-- | Allows for a function on a bare DirTree to be applied to an
-- AnchoredDirTree within a Functor. Very similar to and useful in
-- combination with <$>:
($>) :: (Functor f) => (DirTree a -> DirTree b) -> f (AnchoredDirTree a) -> f (AnchoredDirTree b)
infixl 4 $>
_contents :: Applicative f => ([DirTree a] -> f [DirTree a]) -> DirTree a -> f (DirTree a)
_err :: Applicative f => (IOException -> f IOException) -> DirTree a -> f (DirTree a)
_file :: Applicative f => (a -> f a) -> DirTree a -> f (DirTree a)
_name :: Functor f => (FileName -> f FileName) -> DirTree a -> f (DirTree a)
_anchor :: Functor f => (FilePath -> f FilePath) -> AnchoredDirTree a -> f (AnchoredDirTree a)
_dirTree :: Functor f => (DirTree t -> f (DirTree a)) -> AnchoredDirTree t -> f (AnchoredDirTree a)
instance GHC.Classes.Eq a => GHC.Classes.Eq (System.Directory.Tree.AnchoredDirTree a)
instance GHC.Classes.Ord a => GHC.Classes.Ord (System.Directory.Tree.AnchoredDirTree a)
instance GHC.Show.Show a => GHC.Show.Show (System.Directory.Tree.AnchoredDirTree a)
instance GHC.Show.Show a => GHC.Show.Show (System.Directory.Tree.DirTree a)
instance GHC.Classes.Eq a => GHC.Classes.Eq (System.Directory.Tree.DirTree a)
instance (GHC.Classes.Ord a, GHC.Classes.Eq a) => GHC.Classes.Ord (System.Directory.Tree.DirTree a)
instance GHC.Base.Functor System.Directory.Tree.DirTree
instance Data.Foldable.Foldable System.Directory.Tree.DirTree
instance Data.Traversable.Traversable System.Directory.Tree.DirTree
instance GHC.Base.Functor System.Directory.Tree.AnchoredDirTree