pathtype-0.5.2: Type-safe replacement for System.FilePath etc

System.Path.Posix

Contents

Description

This module provides type-safe access to filepath manipulations.

Normally you would import System.Path (which will use the default implementation for the host platform) instead of this. However, importing this explicitly allows for manipulation of non-native paths.

Synopsis

The main filepath (& dirpath) abstract type

data Path ar fd Source

This is the main filepath abstract datatype

Instances

Eq (Path ar fd) 
Ord (Path ar fd) 
AbsRelClass ar => Read (Path ar fd) 
AbsRelClass ar => Show (Path ar fd) 
IsString (Path ar fd)

Allow use of OverloadedStrings if desired

Arbitrary (Path ar Dir) 
Arbitrary (Path ar File) 

Phantom Types

data Abs Source

Instances

AbsRelClass Abs 
Private Abs 

data Rel Source

Instances

AbsRelClass Rel 
Private Rel 

data File Source

Instances

data Dir Source

Instances

Type Synonyms

type AbsPath fd = Path Abs fdSource

type RelPath fd = Path Rel fdSource

type FilePath ar = Path ar FileSource

type DirPath ar = Path ar DirSource

Classes

class Private ar => AbsRelClass ar whereSource

This class allows selective behaviour for absolute and relative paths and is mostly for internal use.

Methods

absRel :: (AbsPath fd -> a) -> (RelPath fd -> a) -> Path ar fd -> aSource

class Private fd => FileDirClass fd whereSource

This class allows selective behaviour for file and directory paths and is mostly for internal use.

Methods

fileDir :: (FilePath ar -> a) -> (DirPath ar -> a) -> Path ar fd -> aSource

Path to String conversion

getPathString :: AbsRelClass ar => Path ar fd -> StringSource

Convert the Path into a plain String. This is simply an alias for show.

Constants

Unchecked Construction Functions

asPath :: String -> Path ar fdSource

Use a String as a Path whose type is determined by its context.

> asPath "/tmp" == "/tmp"
> asPath "file.txt" == "file.txt"
> isAbsolute (asPath "/tmp" :: AbsDir) == True
> isAbsolute (asPath "/tmp" :: RelDir) == False
> getPathString (asPath "/tmp" :: AbsDir) == "/tmp"
> getPathString (asPath "/tmp" :: RelDir) == "tmp"

asRelFile :: String -> RelFileSource

Use a String as a RelFile. No checking is done.

> getPathString (asRelFile "file.txt") == "file.txt"
> getPathString (asRelFile "/file.txt") == "file.txt"
> getPathString (asRelFile "tmp") == "tmp"
> getPathString (asRelFile "/tmp") == "tmp"

asRelDir :: String -> RelDirSource

Use a String as a RelDir. No checking is done.

> getPathString (asRelDir "file.txt") == "file.txt"
> getPathString (asRelDir "/file.txt") == "file.txt"
> getPathString (asRelDir "tmp") == "tmp"
> getPathString (asRelDir "/tmp") == "tmp"

asAbsFile :: String -> AbsFileSource

Use a String as an AbsFile. No checking is done.

> getPathString (asAbsFile "file.txt") == "/file.txt"
> getPathString (asAbsFile "/file.txt") == "/file.txt"
> getPathString (asAbsFile "tmp") == "/tmp"
> getPathString (asAbsFile "/tmp") == "/tmp"

asAbsDir :: String -> AbsDirSource

Use a String as an AbsDir. No checking is done.

> getPathString (asAbsDir "file.txt") == "/file.txt"
> getPathString (asAbsDir "/file.txt") == "/file.txt"
> getPathString (asAbsDir "tmp") == "/tmp"
> getPathString (asAbsDir "/tmp") == "/tmp"

asRelPath :: String -> RelPath fdSource

Use a String as a 'RelPath fd'. No checking is done.

asAbsPath :: String -> AbsPath fdSource

Use a String as an 'AbsPath fd'. No checking is done.

asFilePath :: String -> FilePath arSource

Use a String as a 'FilePath ar'. No checking is done.

asDirPath :: String -> DirPath arSource

Use a String as a 'DirPath ar'. No checking is done.

Checked Construction Functions

mkPathAbsOrRel :: String -> Either (AbsPath fd) (RelPath fd)Source

Examines the supplied string and constructs an absolute or relative path as appropriate.

> either id (const "fred") (mkPathAbsOrRel "/tmp") == "/tmp"
> either id (const "fred") (mkPathAbsOrRel  "tmp") == "fred"

mkPathFileOrDir :: AbsRelClass ar => String -> IO (Maybe (Either (FilePath ar) (DirPath ar)))Source

Searches for a file or directory with the supplied path string and returns a File or Dir path as appropriate. If neither exists at the supplied path, Nothing is returned.

mkAbsPath :: AbsDir -> String -> AbsPath fdSource

Convert a String into an AbsPath by interpreting it as relative to the supplied directory if necessary.

> mkAbsPath "/tmp" "foo.txt" == "/tmp/foo.txt"
> mkAbsPath "/tmp" "/etc/foo.txt" == "/etc/foo.txt"

mkAbsPathFromCwd :: String -> IO (AbsPath fd)Source

Convert a String into an AbsPath by interpreting it as relative to the cwd if necessary.

Basic Manipulation Functions

(</>) :: DirPath ar -> RelPath fd -> Path ar fdSource

Join an (absolute or relative) directory path with a relative (file or directory) path to form a new path.

(<.>) :: FilePath ar -> String -> FilePath arSource

We only allow files (and not directories) to have extensions added by this function. This is because it's the vastly common case and an attempt to add one to a directory will - more often than not - represent an error. We don't however want to prevent the corresponding operation on directories, and so we provide a function that is more flexible: genericAddExtension.

addExtension :: FilePath ar -> String -> FilePath arSource

Add an extension, even if there is already one there. E.g. addExtension "foo.txt" "bat" -> "foo.txt.bat".

> addExtension "file.txt" "bib" == "file.txt.bib"
> addExtension "file." ".bib" == "file..bib"
> addExtension "file" ".bib" == "file.bib"
> takeFileName (addExtension "" "ext") == ".ext"

combine :: DirPath ar -> RelPath fd -> Path ar fdSource

Join an (absolute or relative) directory path with a relative (file or directory) path to form a new path.

dropExtension :: FilePath ar -> FilePath arSource

Remove last extension, and the "." preceding it.

> dropExtension x == fst (splitExtension x)

dropExtensions :: FilePath ar -> FilePath arSource

Drop all extensions

> not $ hasAnExtension (dropExtensions x)

replaceExtension :: FilePath ar -> String -> FilePath arSource

Set the extension of a file, overwriting one if already present.

> replaceExtension "file.txt" ".bob" == "file.bob"
> replaceExtension "file.txt" "bob" == "file.bob"
> replaceExtension "file" ".bob" == "file.bob"
> replaceExtension "file.txt" "" == "file"
> replaceExtension "file.fred.bob" "txt" == "file.fred.txt"

replaceBaseName :: Path ar fd -> String -> Path ar fdSource

replaceDirectory :: Path ar1 fd -> DirPath ar2 -> Path ar2 fdSource

replaceFileName :: Path ar fd -> String -> Path ar fdSource

splitExtension :: FilePath ar -> (FilePath ar, String)Source

Split on the extension. addExtension is the inverse.

> uncurry (<.>) (splitExtension x) == x
> uncurry addExtension (splitExtension x) == x
> splitExtension "file.txt" == ("file",".txt")
> splitExtension "file" == ("file","")
> splitExtension "file/file.txt" == ("file/file",".txt")
> splitExtension "file.txt/boris" == ("file.txt/boris","")
> splitExtension "file.txt/boris.ext" == ("file.txt/boris",".ext")
> splitExtension "file/path.txt.bob.fred" == ("file/path.txt.bob",".fred")

splitExtensions :: FilePath ar -> (FilePath ar, String)Source

Split on all extensions

> splitExtensions "file.tar.gz" == ("file",".tar.gz")

takeBaseName :: Path ar fd -> RelPath fdSource

Get the basename of a file

> takeBaseName "/tmp/somedir/myfile.txt" == "myfile"
> takeBaseName "./myfile.txt" == "myfile"
> takeBaseName "myfile.txt" == "myfile"

takeExtension :: FilePath ar -> StringSource

Get the extension of a file, returns "" for no extension, .ext otherwise.

> takeExtension x == snd (splitExtension x)
> takeExtension (addExtension x "ext") == ".ext"
> takeExtension (replaceExtension x "ext") == ".ext"

takeExtensions :: FilePath ar -> StringSource

Get all extensions

> takeExtensions "file.tar.gz" == ".tar.gz"

takeFileName :: Path ar fd -> RelPath fdSource

Get the filename component of a file path (ie stripping all parent dirs)

> takeFileName "/tmp/somedir/myfile.txt" == "myfile.txt"
> takeFileName "./myfile.txt" == "myfile.txt"
> takeFileName "myfile.txt" == "myfile.txt"

Auxillary Manipulation Functions

equalFilePath :: String -> String -> BoolSource

Check whether two strings are equal as file paths.

> equalFilePath "/tmp/" "/tmp" == True
> equalFilePath "/tmp"  "tmp"  == False

joinPath :: [String] -> Path ar fdSource

Constructs a Path from a list of components.

> joinPath ["/tmp","someDir","file.txt"] == "/tmp/someDir/file.txt"
> (joinPath ["/tmp","someDir","file.txt"] :: RelFile) == "tmp/someDir/file.txt"

normalise :: Path ar fd -> Path ar fdSource

Currently just transforms:

> normalise "/tmp/fred/./jim/./file" == "/tmp/fred/jim/file"

splitPath :: FileDirClass fd => Path ar fd -> ([RelDir], Maybe RelFile)Source

Deconstructs a path into its components.

> splitPath ("/tmp/someDir/myfile.txt" :: AbsDir)  == (["tmp","someDir","myfile.txt"],Nothing)
> splitPath ("/tmp/someDir/myfile.txt" :: AbsFile) == (["tmp","someDir"],Just "myfile.txt")
> splitPath (asAbsFile "/tmp/someDir/myfile.txt")  == (["tmp","someDir"],Just "myfile.txt")

makeRelative :: AbsDir -> AbsPath fd -> RelPath fdSource

This function can be used to construct a relative path by removing the supplied AbsDir from the front. It is a runtime error if the supplied AbsPath doesn't start with the AbsDir.

> makeRelative "/tmp/somedir" "/tmp/somedir/anotherdir/file.txt" == "anotherdir/file.txt"

makeAbsolute :: AbsDir -> RelPath fd -> AbsPath fdSource

Joins an absolute directory with a relative path to construct a new absolute path.

> makeAbsolute "/tmp" "file.txt"      == "/tmp/file.txt"
> makeAbsolute "/tmp" "adir/file.txt" == "/tmp/adir/file.txt"

makeAbsoluteFromCwd :: RelPath fd -> IO (AbsPath fd)Source

Converts a relative path into an absolute one by prepending the current working directory.

genericMakeAbsolute :: AbsRelClass ar => AbsDir -> Path ar fd -> AbsPath fdSource

As for makeAbsolute, but for use when the path may already be absolute (in which case it is left unchanged).

> genericMakeAbsolute "/tmp" (asRelFile "file.txt")       == "/tmp/file.txt"
> genericMakeAbsolute "/tmp" (asRelFile "adir/file.txt")  == "/tmp/adir/file.txt"
> genericMakeAbsolute "/tmp" (asAbsFile "adir/file.txt")  == "/adir/file.txt"
> genericMakeAbsolute "/tmp" (asAbsFile "/adir/file.txt") == "/adir/file.txt"

genericMakeAbsoluteFromCwd :: AbsRelClass ar => Path ar fd -> IO (AbsPath fd)Source

As for makeAbsoluteFromCwd, but for use when the path may already be absolute (in which case it is left unchanged).

pathMap :: (String -> String) -> Path ar fd -> Path ar fdSource

Map over the components of the path.

> pathMap (map toLower) "/tmp/Reports/SpreadSheets" == "/tmp/reports/spreadsheets"

Path Predicates

isAbsolute :: AbsRelClass ar => Path ar fd -> BoolSource

Test whether a Path ar fd is absolute.

> isAbsolute (asAbsFile "fred")  == True
> isAbsolute (asRelFile "fred")  == False
> isAbsolute (asAbsFile "/fred") == True
> isAbsolute (asRelFile "/fred") == False

isAbsoluteString :: String -> BoolSource

Test whether the String would correspond to an absolute path if interpreted as a Path.

isRelative :: AbsRelClass ar => Path ar fd -> BoolSource

Invariant - this should return True iff arg is of type Path Rel _

 isRelative = not . isAbsolute

isRelativeString :: String -> BoolSource

Test whether the String would correspond to a relative path if interpreted as a Path.

 isRelativeString = not . isAbsoluteString

hasAnExtension :: FilePath ar -> BoolSource

Does the given filename have an extension?

> null (takeExtension x) == not (hasAnExtension x)

hasExtension :: String -> FilePath ar -> BoolSource

Does the given filename have the given extension?

> hasExtension ".hs" "MyCode.hs" == True
> hasExtension ".hs" "MyCode.hs.bak" == False
> hasExtension ".hs" "MyCode.bak.hs" == True

Separators

addTrailingPathSeparator :: String -> StringSource

This is largely for System.FilePath compatability

dropTrailingPathSeparator :: String -> StringSource

This is largely for System.FilePath compatability

extSeparator :: CharSource

File extension character

> extSeparator == '.'

hasTrailingPathSeparator :: String -> BoolSource

This is largely for System.FilePath compatability

pathSeparator :: CharSource

The character that separates directories. In the case where more than one character is possible, pathSeparator is the 'ideal' one.

> isPathSeparator pathSeparator

pathSeparators :: [Char]Source

The list of all possible separators.

> pathSeparator `elem` pathSeparators

searchPathSeparator :: CharSource

The character that is used to separate the entries in the $PATH environment variable.

isExtSeparator :: Char -> BoolSource

Is the character an extension character?

> isExtSeparator a == (a == extSeparator)

isPathSeparator :: Char -> BoolSource

Rather than using (== pathSeparator), use this. Test if something is a path separator.

> isPathSeparator a == (a `elem` pathSeparators)

isSearchPathSeparator :: Char -> BoolSource

Is the character a file separator?

> isSearchPathSeparator a == (a == searchPathSeparator)

Generic Manipulation Functions

genericAddExtension :: Path ar fd -> String -> Path ar fdSource

This is a more flexible variant of addExtension / <.> which can work with files or directories

> genericAddExtension "/" "x" == "/.x"