-- 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 "./"
--
--
--
-- - NOTE:* the IO functions like readDirectoryWith in this
-- library use standard lazy IO IOfunctions and will (necessarily)
-- traverse an entire system directory tree before returning a DirTree
-- constructor. This unfortunately makes it not suitable for large
-- directory trees. Any ideas or suggestions for improvements would be
-- most welcomed :-)
--
@package directory-tree
@version 0.2.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 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
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
Failed :: FileName -> IOException -> DirTree a
name :: DirTree a -> FileName
err :: DirTree a -> IOException
-- | 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
-- | an element in a FilePath:
type FileName = String
-- | build an AnchoredDirTree, given the path to a directory, opening the
-- files using readFile. Uses readDirectoryWith internally and has
-- the effect of traversing the entire directory structure, so is not
-- suitable for running on large directory trees (suggestions or patches
-- welcomed):
readDirectory :: FilePath -> IO (AnchoredDirTree String)
-- | same as readDirectory but allows us to, for example, use
-- ByteString.readFile to return a tree of ByteStrings.
readDirectoryWith :: (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:
writeDirectory :: AnchoredDirTree String -> IO ()
-- | writes the directory structure to disc, then uses the provided
-- function to write the contents of Files to disc.
writeDirectoryWith :: (FilePath -> a -> IO ()) -> AnchoredDirTree a -> IO ()
-- | tuple up the complete filename with the File contents, by building up
-- the path, trie-style, from the root. The filepath will be relative to
-- the current directory. This allows us to, for example, mapM_ 'uncurry
-- writeFile' over a DirTree of strings.
zipPaths :: AnchoredDirTree a -> DirTree (FilePath, a)
-- | 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)
-- | 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. can be preparation for writing files:
writeJustDirs :: AnchoredDirTree a -> IO ()
-- | 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
-- | strips away base directory wrapper:
free :: AnchoredDirTree a -> DirTree a
instance (Show a) => Show (AnchoredDirTree a)
instance (Ord a) => Ord (AnchoredDirTree a)
instance (Eq a) => Eq (AnchoredDirTree a)
instance (Show a) => Show (DirTree a)
instance (Eq a) => Eq (DirTree a)
instance Traversable DirTree
instance Foldable DirTree
instance Functor DirTree
instance (Ord a) => Ord (DirTree a)