-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Library for manipulating FilePaths in a cross platform way.
--   
--   Library for manipulating FilePaths in a cross platform way.
@package filepath
@version 1.2.0.0


-- | A library for FilePath manipulations, using Windows style paths on all
--   platforms. Importing <a>System.FilePath</a> is usually better.
module System.FilePath.Windows

-- | File and directory names are values of type <a>String</a>, whose
--   precise meaning is operating system dependent. Files can be opened,
--   yielding a handle which can then be used to operate on the contents of
--   that file.
type FilePath = String

-- | The character that separates directories. In the case where more than
--   one character is possible, <a>pathSeparator</a> is the 'ideal' one.
--   
--   <pre>
--   Windows: pathSeparator == '\\'
--   Posix:   pathSeparator ==  '/'
--   isPathSeparator pathSeparator
--   </pre>
pathSeparator :: Char

-- | The list of all possible separators.
--   
--   <pre>
--   Windows: pathSeparators == ['\\', '/']
--   Posix:   pathSeparators == ['/']
--   pathSeparator `elem` pathSeparators
--   </pre>
pathSeparators :: [Char]

-- | Rather than using <tt>(== <a>pathSeparator</a>)</tt>, use this. Test
--   if something is a path separator.
--   
--   <pre>
--   isPathSeparator a == (a `elem` pathSeparators)
--   </pre>
isPathSeparator :: Char -> Bool

-- | The character that is used to separate the entries in the $PATH
--   environment variable.
--   
--   <pre>
--   Windows: searchPathSeparator == ';'
--   Posix:   searchPathSeparator == ':'
--   </pre>
searchPathSeparator :: Char

-- | Is the character a file separator?
--   
--   <pre>
--   isSearchPathSeparator a == (a == searchPathSeparator)
--   </pre>
isSearchPathSeparator :: Char -> Bool

-- | File extension character
--   
--   <pre>
--   extSeparator == '.'
--   </pre>
extSeparator :: Char

-- | Is the character an extension character?
--   
--   <pre>
--   isExtSeparator a == (a == extSeparator)
--   </pre>
isExtSeparator :: Char -> Bool

-- | Take a string, split it on the <a>searchPathSeparator</a> character.
--   
--   Follows the recommendations in
--   <a>http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html</a>
--   
--   <pre>
--   Posix:   splitSearchPath "File1:File2:File3"  == ["File1","File2","File3"]
--   Posix:   splitSearchPath "File1::File2:File3" == ["File1",".","File2","File3"]
--   Windows: splitSearchPath "File1;File2;File3"  == ["File1","File2","File3"]
--   Windows: splitSearchPath "File1;;File2;File3" == ["File1","File2","File3"]
--   </pre>
splitSearchPath :: String -> [FilePath]

-- | Get a list of filepaths in the $PATH.
getSearchPath :: IO [FilePath]

-- | Split on the extension. <a>addExtension</a> is the inverse.
--   
--   <pre>
--   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")
--   splitExtension "file/path.txt/" == ("file/path.txt/","")
--   </pre>
splitExtension :: FilePath -> (String, String)

-- | Get the extension of a file, returns <tt>""</tt> for no extension,
--   <tt>.ext</tt> otherwise.
--   
--   <pre>
--   takeExtension x == snd (splitExtension x)
--   Valid x =&gt; takeExtension (addExtension x "ext") == ".ext"
--   Valid x =&gt; takeExtension (replaceExtension x "ext") == ".ext"
--   </pre>
takeExtension :: FilePath -> String

-- | Set the extension of a file, overwriting one if already present.
--   
--   <pre>
--   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"
--   </pre>
replaceExtension :: FilePath -> String -> FilePath

-- | Remove last extension, and the "." preceding it.
--   
--   <pre>
--   dropExtension x == fst (splitExtension x)
--   </pre>
dropExtension :: FilePath -> FilePath

-- | Add an extension, even if there is already one there. E.g.
--   <tt>addExtension "foo.txt" "bat" -&gt; "foo.txt.bat"</tt>.
--   
--   <pre>
--   addExtension "file.txt" "bib" == "file.txt.bib"
--   addExtension "file." ".bib" == "file..bib"
--   addExtension "file" ".bib" == "file.bib"
--   addExtension "/" "x" == "/.x"
--   Valid x =&gt; takeFileName (addExtension (addTrailingPathSeparator x) "ext") == ".ext"
--   Windows: addExtension "\\\\share" ".txt" == "\\\\share\\.txt"
--   </pre>
addExtension :: FilePath -> String -> FilePath

-- | Does the given filename have an extension?
--   
--   <pre>
--   null (takeExtension x) == not (hasExtension x)
--   </pre>
hasExtension :: FilePath -> Bool

-- | Alias to <a>addExtension</a>, for people who like that sort of thing.
(<.>) :: FilePath -> String -> FilePath

-- | Split on all extensions
--   
--   <pre>
--   uncurry (++) (splitExtensions x) == x
--   uncurry addExtension (splitExtensions x) == x
--   splitExtensions "file.tar.gz" == ("file",".tar.gz")
--   </pre>
splitExtensions :: FilePath -> (FilePath, String)

-- | Drop all extensions
--   
--   <pre>
--   not $ hasExtension (dropExtensions x)
--   </pre>
dropExtensions :: FilePath -> FilePath

-- | Get all extensions
--   
--   <pre>
--   takeExtensions "file.tar.gz" == ".tar.gz"
--   </pre>
takeExtensions :: FilePath -> String

-- | Split a path into a drive and a path. On Unix, / is a Drive.
--   
--   <pre>
--   uncurry (++) (splitDrive x) == x
--   Windows: splitDrive "file" == ("","file")
--   Windows: splitDrive "c:/file" == ("c:/","file")
--   Windows: splitDrive "c:\\file" == ("c:\\","file")
--   Windows: splitDrive "\\\\shared\\test" == ("\\\\shared\\","test")
--   Windows: splitDrive "\\\\shared" == ("\\\\shared","")
--   Windows: splitDrive "\\\\?\\UNC\\shared\\file" == ("\\\\?\\UNC\\shared\\","file")
--   Windows: splitDrive "\\\\?\\UNCshared\\file" == ("\\\\?\\","UNCshared\\file")
--   Windows: splitDrive "\\\\?\\d:\\file" == ("\\\\?\\d:\\","file")
--   Windows: splitDrive "/d" == ("","/d")
--   Posix:   splitDrive "/test" == ("/","test")
--   Posix:   splitDrive "//test" == ("//","test")
--   Posix:   splitDrive "test/file" == ("","test/file")
--   Posix:   splitDrive "file" == ("","file")
--   </pre>
splitDrive :: FilePath -> (FilePath, FilePath)

-- | Join a drive and the rest of the path.
--   
--   <pre>
--            uncurry joinDrive (splitDrive x) == x
--   Windows: joinDrive "C:" "foo" == "C:foo"
--   Windows: joinDrive "C:\\" "bar" == "C:\\bar"
--   Windows: joinDrive "\\\\share" "foo" == "\\\\share\\foo"
--   Windows: joinDrive "/:" "foo" == "/:\\foo"
--   </pre>
joinDrive :: FilePath -> FilePath -> FilePath

-- | Get the drive from a filepath.
--   
--   <pre>
--   takeDrive x == fst (splitDrive x)
--   </pre>
takeDrive :: FilePath -> FilePath

-- | Does a path have a drive.
--   
--   <pre>
--   not (hasDrive x) == null (takeDrive x)
--   </pre>
hasDrive :: FilePath -> Bool

-- | Delete the drive, if it exists.
--   
--   <pre>
--   dropDrive x == snd (splitDrive x)
--   </pre>
dropDrive :: FilePath -> FilePath

-- | Is an element a drive
isDrive :: FilePath -> Bool

-- | Split a filename into directory and file. <a>combine</a> is the
--   inverse.
--   
--   <pre>
--   Valid x =&gt; uncurry (&lt;/&gt;) (splitFileName x) == x || fst (splitFileName x) == "./"
--   Valid x =&gt; isValid (fst (splitFileName x))
--   splitFileName "file/bob.txt" == ("file/", "bob.txt")
--   splitFileName "file/" == ("file/", "")
--   splitFileName "bob" == ("./", "bob")
--   Posix:   splitFileName "/" == ("/","")
--   Windows: splitFileName "c:" == ("c:","")
--   </pre>
splitFileName :: FilePath -> (String, String)

-- | Get the file name.
--   
--   <pre>
--   takeFileName "test/" == ""
--   takeFileName x `isSuffixOf` x
--   takeFileName x == snd (splitFileName x)
--   Valid x =&gt; takeFileName (replaceFileName x "fred") == "fred"
--   Valid x =&gt; takeFileName (x &lt;/&gt; "fred") == "fred"
--   Valid x =&gt; isRelative (takeFileName x)
--   </pre>
takeFileName :: FilePath -> FilePath

-- | Set the filename.
--   
--   <pre>
--   Valid x =&gt; replaceFileName x (takeFileName x) == x
--   </pre>
replaceFileName :: FilePath -> String -> FilePath

-- | Drop the filename.
--   
--   <pre>
--   dropFileName x == fst (splitFileName x)
--   </pre>
dropFileName :: FilePath -> FilePath

-- | Get the base name, without an extension or path.
--   
--   <pre>
--   takeBaseName "file/test.txt" == "test"
--   takeBaseName "dave.ext" == "dave"
--   takeBaseName "" == ""
--   takeBaseName "test" == "test"
--   takeBaseName (addTrailingPathSeparator x) == ""
--   takeBaseName "file/file.tar.gz" == "file.tar"
--   </pre>
takeBaseName :: FilePath -> String

-- | Set the base name.
--   
--   <pre>
--   replaceBaseName "file/test.txt" "bob" == "file/bob.txt"
--   replaceBaseName "fred" "bill" == "bill"
--   replaceBaseName "/dave/fred/bob.gz.tar" "new" == "/dave/fred/new.tar"
--   Valid x =&gt; replaceBaseName x (takeBaseName x) == x
--   </pre>
replaceBaseName :: FilePath -> String -> FilePath

-- | Get the directory name, move up one level.
--   
--   <pre>
--             takeDirectory x `isPrefixOf` x || takeDirectory x == "."
--             takeDirectory "foo" == "."
--             takeDirectory "/foo/bar/baz" == "/foo/bar"
--             takeDirectory "/foo/bar/baz/" == "/foo/bar/baz"
--             takeDirectory "foo/bar/baz" == "foo/bar"
--   Windows:  takeDirectory "foo\\bar" == "foo"
--   Windows:  takeDirectory "foo\\bar\\\\" == "foo\\bar"
--   Windows:  takeDirectory "C:\\" == "C:\\"
--   </pre>
takeDirectory :: FilePath -> FilePath

-- | Set the directory, keeping the filename the same.
--   
--   <pre>
--   Valid x =&gt; replaceDirectory x (takeDirectory x) `equalFilePath` x
--   </pre>
replaceDirectory :: FilePath -> String -> FilePath

-- | Combine two paths, if the second path <a>isAbsolute</a>, then it
--   returns the second.
--   
--   <pre>
--   Valid x =&gt; combine (takeDirectory x) (takeFileName x) `equalFilePath` x
--   Posix:   combine "/" "test" == "/test"
--   Posix:   combine "home" "bob" == "home/bob"
--   Windows: combine "home" "bob" == "home\\bob"
--   Windows: combine "home" "/bob" == "/bob"
--   </pre>
combine :: FilePath -> FilePath -> FilePath

-- | A nice alias for <a>combine</a>.
(</>) :: FilePath -> FilePath -> FilePath

-- | Split a path by the directory separator.
--   
--   <pre>
--   concat (splitPath x) == x
--   splitPath "test//item/" == ["test//","item/"]
--   splitPath "test/item/file" == ["test/","item/","file"]
--   splitPath "" == []
--   Windows: splitPath "c:\\test\\path" == ["c:\\","test\\","path"]
--   Posix:   splitPath "/file/test" == ["/","file/","test"]
--   </pre>
splitPath :: FilePath -> [FilePath]

-- | Join path elements back together.
--   
--   <pre>
--   Valid x =&gt; joinPath (splitPath x) == x
--   joinPath [] == ""
--   Posix: joinPath ["test","file","path"] == "test/file/path"
--   </pre>
joinPath :: [FilePath] -> FilePath

-- | Just as <a>splitPath</a>, but don't add the trailing slashes to each
--   element.
--   
--   <pre>
--   splitDirectories "test/file" == ["test","file"]
--   splitDirectories "/test/file" == ["/","test","file"]
--   Valid x =&gt; joinPath (splitDirectories x) `equalFilePath` x
--   splitDirectories "" == []
--   </pre>
splitDirectories :: FilePath -> [FilePath]

-- | Is an item either a directory or the last character a path separator?
--   
--   <pre>
--   hasTrailingPathSeparator "test" == False
--   hasTrailingPathSeparator "test/" == True
--   </pre>
hasTrailingPathSeparator :: FilePath -> Bool

-- | Add a trailing file path separator if one is not already present.
--   
--   <pre>
--   hasTrailingPathSeparator (addTrailingPathSeparator x)
--   hasTrailingPathSeparator x ==&gt; addTrailingPathSeparator x == x
--   Posix:    addTrailingPathSeparator "test/rest" == "test/rest/"
--   </pre>
addTrailingPathSeparator :: FilePath -> FilePath

-- | Remove any trailing path separators
--   
--   <pre>
--   dropTrailingPathSeparator "file/test/" == "file/test"
--   Posix:    not (hasTrailingPathSeparator (dropTrailingPathSeparator x)) || isDrive x
--   Posix:    dropTrailingPathSeparator "/" == "/"
--   Windows:  dropTrailingPathSeparator "\\" == "\\"
--   </pre>
dropTrailingPathSeparator :: FilePath -> FilePath

-- | Normalise a file
--   
--   <ul>
--   <li>// outside of the drive can be made blank</li>
--   <li>/ -&gt; <a>pathSeparator</a></li>
--   <li>./ -&gt; ""</li>
--   </ul>
--   
--   <pre>
--   Posix:   normalise "/file/\\test////" == "/file/\\test/"
--   Posix:   normalise "/file/./test" == "/file/test"
--   Posix:   normalise "/test/file/../bob/fred/" == "/test/file/../bob/fred/"
--   Posix:   normalise "../bob/fred/" == "../bob/fred/"
--   Posix:   normalise "./bob/fred/" == "bob/fred/"
--   Windows: normalise "c:\\file/bob\\" == "C:\\file\\bob\\"
--   Windows: normalise "c:\\" == "C:\\"
--   Windows: normalise "\\\\server\\test" == "\\\\server\\test"
--   Windows: normalise "c:/file" == "C:\\file"
--            normalise "." == "."
--   Posix:   normalise "./" == "./"
--   </pre>
normalise :: FilePath -> FilePath

-- | Equality of two <a>FilePath</a>s. If you call
--   <tt>System.Directory.canonicalizePath</tt> first this has a much
--   better chance of working. Note that this doesn't follow symlinks or
--   DOSNAM~1s.
--   
--   <pre>
--            x == y ==&gt; equalFilePath x y
--            normalise x == normalise y ==&gt; equalFilePath x y
--   Posix:   equalFilePath "foo" "foo/"
--   Posix:   not (equalFilePath "foo" "/foo")
--   Posix:   not (equalFilePath "foo" "FOO")
--   Windows: equalFilePath "foo" "FOO"
--   </pre>
equalFilePath :: FilePath -> FilePath -> Bool

-- | Contract a filename, based on a relative path.
--   
--   There is no corresponding <tt>makeAbsolute</tt> function, instead use
--   <tt>System.Directory.canonicalizePath</tt> which has the same effect.
--   
--   <pre>
--            Valid y =&gt; equalFilePath x y || (isRelative x &amp;&amp; makeRelative y x == x) || equalFilePath (y &lt;/&gt; makeRelative y x) x
--            makeRelative x x == "."
--            null y || equalFilePath (makeRelative x (x &lt;/&gt; y)) y || null (takeFileName x)
--   Windows: makeRelative "C:\\Home" "c:\\home\\bob" == "bob"
--   Windows: makeRelative "C:\\Home" "c:/home/bob" == "bob"
--   Windows: makeRelative "C:\\Home" "D:\\Home\\Bob" == "D:\\Home\\Bob"
--   Windows: makeRelative "C:\\Home" "C:Home\\Bob" == "C:Home\\Bob"
--   Windows: makeRelative "/Home" "/home/bob" == "bob"
--   Posix:   makeRelative "/Home" "/home/bob" == "/home/bob"
--   Posix:   makeRelative "/home/" "/home/bob/foo/bar" == "bob/foo/bar"
--   Posix:   makeRelative "/fred" "bob" == "bob"
--   Posix:   makeRelative "/file/test" "/file/test/fred" == "fred"
--   Posix:   makeRelative "/file/test" "/file/test/fred/" == "fred/"
--   Posix:   makeRelative "some/path" "some/path/a/b/c" == "a/b/c"
--   </pre>
makeRelative :: FilePath -> FilePath -> FilePath

-- | Is a path relative, or is it fixed to the root?
--   
--   <pre>
--   Windows: isRelative "path\\test" == True
--   Windows: isRelative "c:\\test" == False
--   Windows: isRelative "c:test" == True
--   Windows: isRelative "c:" == True
--   Windows: isRelative "\\\\foo" == False
--   Windows: isRelative "/foo" == True
--   Posix:   isRelative "test/path" == True
--   Posix:   isRelative "/test" == False
--   </pre>
isRelative :: FilePath -> Bool

-- | <pre>
--   not . <a>isRelative</a>
--   </pre>
--   
--   <pre>
--   isAbsolute x == not (isRelative x)
--   </pre>
isAbsolute :: FilePath -> Bool

-- | Is a FilePath valid, i.e. could you create a file like it?
--   
--   <pre>
--            isValid "" == False
--   Posix:   isValid "/random_ path:*" == True
--   Posix:   isValid x == not (null x)
--   Windows: isValid "c:\\test" == True
--   Windows: isValid "c:\\test:of_test" == False
--   Windows: isValid "test*" == False
--   Windows: isValid "c:\\test\\nul" == False
--   Windows: isValid "c:\\test\\prn.txt" == False
--   Windows: isValid "c:\\nul\\file" == False
--   Windows: isValid "\\\\" == False
--   </pre>
isValid :: FilePath -> Bool

-- | Take a FilePath and make it valid; does not change already valid
--   FilePaths.
--   
--   <pre>
--   isValid (makeValid x)
--   isValid x ==&gt; makeValid x == x
--   makeValid "" == "_"
--   Windows: makeValid "c:\\test:of_test" == "c:\\test_of_test"
--   Windows: makeValid "test*" == "test_"
--   Windows: makeValid "c:\\test\\nul" == "c:\\test\\nul_"
--   Windows: makeValid "c:\\test\\prn.txt" == "c:\\test\\prn_.txt"
--   Windows: makeValid "c:\\test/prn.txt" == "c:\\test/prn_.txt"
--   Windows: makeValid "c:\\nul\\file" == "c:\\nul_\\file"
--   </pre>
makeValid :: FilePath -> FilePath


-- | A library for FilePath manipulations, using Posix style paths on all
--   platforms. Importing <a>System.FilePath</a> is usually better.
module System.FilePath.Posix

-- | File and directory names are values of type <a>String</a>, whose
--   precise meaning is operating system dependent. Files can be opened,
--   yielding a handle which can then be used to operate on the contents of
--   that file.
type FilePath = String

-- | The character that separates directories. In the case where more than
--   one character is possible, <a>pathSeparator</a> is the 'ideal' one.
--   
--   <pre>
--   Windows: pathSeparator == '\\'
--   Posix:   pathSeparator ==  '/'
--   isPathSeparator pathSeparator
--   </pre>
pathSeparator :: Char

-- | The list of all possible separators.
--   
--   <pre>
--   Windows: pathSeparators == ['\\', '/']
--   Posix:   pathSeparators == ['/']
--   pathSeparator `elem` pathSeparators
--   </pre>
pathSeparators :: [Char]

-- | Rather than using <tt>(== <a>pathSeparator</a>)</tt>, use this. Test
--   if something is a path separator.
--   
--   <pre>
--   isPathSeparator a == (a `elem` pathSeparators)
--   </pre>
isPathSeparator :: Char -> Bool

-- | The character that is used to separate the entries in the $PATH
--   environment variable.
--   
--   <pre>
--   Windows: searchPathSeparator == ';'
--   Posix:   searchPathSeparator == ':'
--   </pre>
searchPathSeparator :: Char

-- | Is the character a file separator?
--   
--   <pre>
--   isSearchPathSeparator a == (a == searchPathSeparator)
--   </pre>
isSearchPathSeparator :: Char -> Bool

-- | File extension character
--   
--   <pre>
--   extSeparator == '.'
--   </pre>
extSeparator :: Char

-- | Is the character an extension character?
--   
--   <pre>
--   isExtSeparator a == (a == extSeparator)
--   </pre>
isExtSeparator :: Char -> Bool

-- | Take a string, split it on the <a>searchPathSeparator</a> character.
--   
--   Follows the recommendations in
--   <a>http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html</a>
--   
--   <pre>
--   Posix:   splitSearchPath "File1:File2:File3"  == ["File1","File2","File3"]
--   Posix:   splitSearchPath "File1::File2:File3" == ["File1",".","File2","File3"]
--   Windows: splitSearchPath "File1;File2;File3"  == ["File1","File2","File3"]
--   Windows: splitSearchPath "File1;;File2;File3" == ["File1","File2","File3"]
--   </pre>
splitSearchPath :: String -> [FilePath]

-- | Get a list of filepaths in the $PATH.
getSearchPath :: IO [FilePath]

-- | Split on the extension. <a>addExtension</a> is the inverse.
--   
--   <pre>
--   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")
--   splitExtension "file/path.txt/" == ("file/path.txt/","")
--   </pre>
splitExtension :: FilePath -> (String, String)

-- | Get the extension of a file, returns <tt>""</tt> for no extension,
--   <tt>.ext</tt> otherwise.
--   
--   <pre>
--   takeExtension x == snd (splitExtension x)
--   Valid x =&gt; takeExtension (addExtension x "ext") == ".ext"
--   Valid x =&gt; takeExtension (replaceExtension x "ext") == ".ext"
--   </pre>
takeExtension :: FilePath -> String

-- | Set the extension of a file, overwriting one if already present.
--   
--   <pre>
--   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"
--   </pre>
replaceExtension :: FilePath -> String -> FilePath

-- | Remove last extension, and the "." preceding it.
--   
--   <pre>
--   dropExtension x == fst (splitExtension x)
--   </pre>
dropExtension :: FilePath -> FilePath

-- | Add an extension, even if there is already one there. E.g.
--   <tt>addExtension "foo.txt" "bat" -&gt; "foo.txt.bat"</tt>.
--   
--   <pre>
--   addExtension "file.txt" "bib" == "file.txt.bib"
--   addExtension "file." ".bib" == "file..bib"
--   addExtension "file" ".bib" == "file.bib"
--   addExtension "/" "x" == "/.x"
--   Valid x =&gt; takeFileName (addExtension (addTrailingPathSeparator x) "ext") == ".ext"
--   Windows: addExtension "\\\\share" ".txt" == "\\\\share\\.txt"
--   </pre>
addExtension :: FilePath -> String -> FilePath

-- | Does the given filename have an extension?
--   
--   <pre>
--   null (takeExtension x) == not (hasExtension x)
--   </pre>
hasExtension :: FilePath -> Bool

-- | Alias to <a>addExtension</a>, for people who like that sort of thing.
(<.>) :: FilePath -> String -> FilePath

-- | Split on all extensions
--   
--   <pre>
--   uncurry (++) (splitExtensions x) == x
--   uncurry addExtension (splitExtensions x) == x
--   splitExtensions "file.tar.gz" == ("file",".tar.gz")
--   </pre>
splitExtensions :: FilePath -> (FilePath, String)

-- | Drop all extensions
--   
--   <pre>
--   not $ hasExtension (dropExtensions x)
--   </pre>
dropExtensions :: FilePath -> FilePath

-- | Get all extensions
--   
--   <pre>
--   takeExtensions "file.tar.gz" == ".tar.gz"
--   </pre>
takeExtensions :: FilePath -> String

-- | Split a path into a drive and a path. On Unix, / is a Drive.
--   
--   <pre>
--   uncurry (++) (splitDrive x) == x
--   Windows: splitDrive "file" == ("","file")
--   Windows: splitDrive "c:/file" == ("c:/","file")
--   Windows: splitDrive "c:\\file" == ("c:\\","file")
--   Windows: splitDrive "\\\\shared\\test" == ("\\\\shared\\","test")
--   Windows: splitDrive "\\\\shared" == ("\\\\shared","")
--   Windows: splitDrive "\\\\?\\UNC\\shared\\file" == ("\\\\?\\UNC\\shared\\","file")
--   Windows: splitDrive "\\\\?\\UNCshared\\file" == ("\\\\?\\","UNCshared\\file")
--   Windows: splitDrive "\\\\?\\d:\\file" == ("\\\\?\\d:\\","file")
--   Windows: splitDrive "/d" == ("","/d")
--   Posix:   splitDrive "/test" == ("/","test")
--   Posix:   splitDrive "//test" == ("//","test")
--   Posix:   splitDrive "test/file" == ("","test/file")
--   Posix:   splitDrive "file" == ("","file")
--   </pre>
splitDrive :: FilePath -> (FilePath, FilePath)

-- | Join a drive and the rest of the path.
--   
--   <pre>
--            uncurry joinDrive (splitDrive x) == x
--   Windows: joinDrive "C:" "foo" == "C:foo"
--   Windows: joinDrive "C:\\" "bar" == "C:\\bar"
--   Windows: joinDrive "\\\\share" "foo" == "\\\\share\\foo"
--   Windows: joinDrive "/:" "foo" == "/:\\foo"
--   </pre>
joinDrive :: FilePath -> FilePath -> FilePath

-- | Get the drive from a filepath.
--   
--   <pre>
--   takeDrive x == fst (splitDrive x)
--   </pre>
takeDrive :: FilePath -> FilePath

-- | Does a path have a drive.
--   
--   <pre>
--   not (hasDrive x) == null (takeDrive x)
--   </pre>
hasDrive :: FilePath -> Bool

-- | Delete the drive, if it exists.
--   
--   <pre>
--   dropDrive x == snd (splitDrive x)
--   </pre>
dropDrive :: FilePath -> FilePath

-- | Is an element a drive
isDrive :: FilePath -> Bool

-- | Split a filename into directory and file. <a>combine</a> is the
--   inverse.
--   
--   <pre>
--   Valid x =&gt; uncurry (&lt;/&gt;) (splitFileName x) == x || fst (splitFileName x) == "./"
--   Valid x =&gt; isValid (fst (splitFileName x))
--   splitFileName "file/bob.txt" == ("file/", "bob.txt")
--   splitFileName "file/" == ("file/", "")
--   splitFileName "bob" == ("./", "bob")
--   Posix:   splitFileName "/" == ("/","")
--   Windows: splitFileName "c:" == ("c:","")
--   </pre>
splitFileName :: FilePath -> (String, String)

-- | Get the file name.
--   
--   <pre>
--   takeFileName "test/" == ""
--   takeFileName x `isSuffixOf` x
--   takeFileName x == snd (splitFileName x)
--   Valid x =&gt; takeFileName (replaceFileName x "fred") == "fred"
--   Valid x =&gt; takeFileName (x &lt;/&gt; "fred") == "fred"
--   Valid x =&gt; isRelative (takeFileName x)
--   </pre>
takeFileName :: FilePath -> FilePath

-- | Set the filename.
--   
--   <pre>
--   Valid x =&gt; replaceFileName x (takeFileName x) == x
--   </pre>
replaceFileName :: FilePath -> String -> FilePath

-- | Drop the filename.
--   
--   <pre>
--   dropFileName x == fst (splitFileName x)
--   </pre>
dropFileName :: FilePath -> FilePath

-- | Get the base name, without an extension or path.
--   
--   <pre>
--   takeBaseName "file/test.txt" == "test"
--   takeBaseName "dave.ext" == "dave"
--   takeBaseName "" == ""
--   takeBaseName "test" == "test"
--   takeBaseName (addTrailingPathSeparator x) == ""
--   takeBaseName "file/file.tar.gz" == "file.tar"
--   </pre>
takeBaseName :: FilePath -> String

-- | Set the base name.
--   
--   <pre>
--   replaceBaseName "file/test.txt" "bob" == "file/bob.txt"
--   replaceBaseName "fred" "bill" == "bill"
--   replaceBaseName "/dave/fred/bob.gz.tar" "new" == "/dave/fred/new.tar"
--   Valid x =&gt; replaceBaseName x (takeBaseName x) == x
--   </pre>
replaceBaseName :: FilePath -> String -> FilePath

-- | Get the directory name, move up one level.
--   
--   <pre>
--             takeDirectory x `isPrefixOf` x || takeDirectory x == "."
--             takeDirectory "foo" == "."
--             takeDirectory "/foo/bar/baz" == "/foo/bar"
--             takeDirectory "/foo/bar/baz/" == "/foo/bar/baz"
--             takeDirectory "foo/bar/baz" == "foo/bar"
--   Windows:  takeDirectory "foo\\bar" == "foo"
--   Windows:  takeDirectory "foo\\bar\\\\" == "foo\\bar"
--   Windows:  takeDirectory "C:\\" == "C:\\"
--   </pre>
takeDirectory :: FilePath -> FilePath

-- | Set the directory, keeping the filename the same.
--   
--   <pre>
--   Valid x =&gt; replaceDirectory x (takeDirectory x) `equalFilePath` x
--   </pre>
replaceDirectory :: FilePath -> String -> FilePath

-- | Combine two paths, if the second path <a>isAbsolute</a>, then it
--   returns the second.
--   
--   <pre>
--   Valid x =&gt; combine (takeDirectory x) (takeFileName x) `equalFilePath` x
--   Posix:   combine "/" "test" == "/test"
--   Posix:   combine "home" "bob" == "home/bob"
--   Windows: combine "home" "bob" == "home\\bob"
--   Windows: combine "home" "/bob" == "/bob"
--   </pre>
combine :: FilePath -> FilePath -> FilePath

-- | A nice alias for <a>combine</a>.
(</>) :: FilePath -> FilePath -> FilePath

-- | Split a path by the directory separator.
--   
--   <pre>
--   concat (splitPath x) == x
--   splitPath "test//item/" == ["test//","item/"]
--   splitPath "test/item/file" == ["test/","item/","file"]
--   splitPath "" == []
--   Windows: splitPath "c:\\test\\path" == ["c:\\","test\\","path"]
--   Posix:   splitPath "/file/test" == ["/","file/","test"]
--   </pre>
splitPath :: FilePath -> [FilePath]

-- | Join path elements back together.
--   
--   <pre>
--   Valid x =&gt; joinPath (splitPath x) == x
--   joinPath [] == ""
--   Posix: joinPath ["test","file","path"] == "test/file/path"
--   </pre>
joinPath :: [FilePath] -> FilePath

-- | Just as <a>splitPath</a>, but don't add the trailing slashes to each
--   element.
--   
--   <pre>
--   splitDirectories "test/file" == ["test","file"]
--   splitDirectories "/test/file" == ["/","test","file"]
--   Valid x =&gt; joinPath (splitDirectories x) `equalFilePath` x
--   splitDirectories "" == []
--   </pre>
splitDirectories :: FilePath -> [FilePath]

-- | Is an item either a directory or the last character a path separator?
--   
--   <pre>
--   hasTrailingPathSeparator "test" == False
--   hasTrailingPathSeparator "test/" == True
--   </pre>
hasTrailingPathSeparator :: FilePath -> Bool

-- | Add a trailing file path separator if one is not already present.
--   
--   <pre>
--   hasTrailingPathSeparator (addTrailingPathSeparator x)
--   hasTrailingPathSeparator x ==&gt; addTrailingPathSeparator x == x
--   Posix:    addTrailingPathSeparator "test/rest" == "test/rest/"
--   </pre>
addTrailingPathSeparator :: FilePath -> FilePath

-- | Remove any trailing path separators
--   
--   <pre>
--   dropTrailingPathSeparator "file/test/" == "file/test"
--   Posix:    not (hasTrailingPathSeparator (dropTrailingPathSeparator x)) || isDrive x
--   Posix:    dropTrailingPathSeparator "/" == "/"
--   Windows:  dropTrailingPathSeparator "\\" == "\\"
--   </pre>
dropTrailingPathSeparator :: FilePath -> FilePath

-- | Normalise a file
--   
--   <ul>
--   <li>// outside of the drive can be made blank</li>
--   <li>/ -&gt; <a>pathSeparator</a></li>
--   <li>./ -&gt; ""</li>
--   </ul>
--   
--   <pre>
--   Posix:   normalise "/file/\\test////" == "/file/\\test/"
--   Posix:   normalise "/file/./test" == "/file/test"
--   Posix:   normalise "/test/file/../bob/fred/" == "/test/file/../bob/fred/"
--   Posix:   normalise "../bob/fred/" == "../bob/fred/"
--   Posix:   normalise "./bob/fred/" == "bob/fred/"
--   Windows: normalise "c:\\file/bob\\" == "C:\\file\\bob\\"
--   Windows: normalise "c:\\" == "C:\\"
--   Windows: normalise "\\\\server\\test" == "\\\\server\\test"
--   Windows: normalise "c:/file" == "C:\\file"
--            normalise "." == "."
--   Posix:   normalise "./" == "./"
--   </pre>
normalise :: FilePath -> FilePath

-- | Equality of two <a>FilePath</a>s. If you call
--   <tt>System.Directory.canonicalizePath</tt> first this has a much
--   better chance of working. Note that this doesn't follow symlinks or
--   DOSNAM~1s.
--   
--   <pre>
--            x == y ==&gt; equalFilePath x y
--            normalise x == normalise y ==&gt; equalFilePath x y
--   Posix:   equalFilePath "foo" "foo/"
--   Posix:   not (equalFilePath "foo" "/foo")
--   Posix:   not (equalFilePath "foo" "FOO")
--   Windows: equalFilePath "foo" "FOO"
--   </pre>
equalFilePath :: FilePath -> FilePath -> Bool

-- | Contract a filename, based on a relative path.
--   
--   There is no corresponding <tt>makeAbsolute</tt> function, instead use
--   <tt>System.Directory.canonicalizePath</tt> which has the same effect.
--   
--   <pre>
--            Valid y =&gt; equalFilePath x y || (isRelative x &amp;&amp; makeRelative y x == x) || equalFilePath (y &lt;/&gt; makeRelative y x) x
--            makeRelative x x == "."
--            null y || equalFilePath (makeRelative x (x &lt;/&gt; y)) y || null (takeFileName x)
--   Windows: makeRelative "C:\\Home" "c:\\home\\bob" == "bob"
--   Windows: makeRelative "C:\\Home" "c:/home/bob" == "bob"
--   Windows: makeRelative "C:\\Home" "D:\\Home\\Bob" == "D:\\Home\\Bob"
--   Windows: makeRelative "C:\\Home" "C:Home\\Bob" == "C:Home\\Bob"
--   Windows: makeRelative "/Home" "/home/bob" == "bob"
--   Posix:   makeRelative "/Home" "/home/bob" == "/home/bob"
--   Posix:   makeRelative "/home/" "/home/bob/foo/bar" == "bob/foo/bar"
--   Posix:   makeRelative "/fred" "bob" == "bob"
--   Posix:   makeRelative "/file/test" "/file/test/fred" == "fred"
--   Posix:   makeRelative "/file/test" "/file/test/fred/" == "fred/"
--   Posix:   makeRelative "some/path" "some/path/a/b/c" == "a/b/c"
--   </pre>
makeRelative :: FilePath -> FilePath -> FilePath

-- | Is a path relative, or is it fixed to the root?
--   
--   <pre>
--   Windows: isRelative "path\\test" == True
--   Windows: isRelative "c:\\test" == False
--   Windows: isRelative "c:test" == True
--   Windows: isRelative "c:" == True
--   Windows: isRelative "\\\\foo" == False
--   Windows: isRelative "/foo" == True
--   Posix:   isRelative "test/path" == True
--   Posix:   isRelative "/test" == False
--   </pre>
isRelative :: FilePath -> Bool

-- | <pre>
--   not . <a>isRelative</a>
--   </pre>
--   
--   <pre>
--   isAbsolute x == not (isRelative x)
--   </pre>
isAbsolute :: FilePath -> Bool

-- | Is a FilePath valid, i.e. could you create a file like it?
--   
--   <pre>
--            isValid "" == False
--   Posix:   isValid "/random_ path:*" == True
--   Posix:   isValid x == not (null x)
--   Windows: isValid "c:\\test" == True
--   Windows: isValid "c:\\test:of_test" == False
--   Windows: isValid "test*" == False
--   Windows: isValid "c:\\test\\nul" == False
--   Windows: isValid "c:\\test\\prn.txt" == False
--   Windows: isValid "c:\\nul\\file" == False
--   Windows: isValid "\\\\" == False
--   </pre>
isValid :: FilePath -> Bool

-- | Take a FilePath and make it valid; does not change already valid
--   FilePaths.
--   
--   <pre>
--   isValid (makeValid x)
--   isValid x ==&gt; makeValid x == x
--   makeValid "" == "_"
--   Windows: makeValid "c:\\test:of_test" == "c:\\test_of_test"
--   Windows: makeValid "test*" == "test_"
--   Windows: makeValid "c:\\test\\nul" == "c:\\test\\nul_"
--   Windows: makeValid "c:\\test\\prn.txt" == "c:\\test\\prn_.txt"
--   Windows: makeValid "c:\\test/prn.txt" == "c:\\test/prn_.txt"
--   Windows: makeValid "c:\\nul\\file" == "c:\\nul_\\file"
--   </pre>
makeValid :: FilePath -> FilePath


-- | A library for <a>FilePath</a> manipulations, using Posix or Windows
--   filepaths depending on the platform.
--   
--   Both <a>System.FilePath.Posix</a> and <a>System.FilePath.Windows</a>
--   provide the same interface. See either for examples and a list of the
--   available functions.
module System.FilePath
