#10, more concrete examples
authorNeil Mitchell <ndmitchell@gmail.com>
Mon, 10 Nov 2014 11:15:54 +0000 (11:15 +0000)
committerNeil Mitchell <ndmitchell@gmail.com>
Mon, 10 Nov 2014 11:15:54 +0000 (11:15 +0000)
System/FilePath/Internal.hs
tests/TestGen.hs

index 0e40fc6..62be343 100644 (file)
@@ -183,8 +183,6 @@ isExtSeparator :: Char -> Bool
 isExtSeparator = (== extSeparator)
 
 
-
-
 ---------------------------------------------------------------------
 -- Path methods (environment $PATH)
 
@@ -210,7 +208,7 @@ splitSearchPath = f
     g x = [x]
 
 
--- | Get a list of filepaths in the $PATH.
+-- | Get a list of 'FilePath's in the $PATH variable.
 getSearchPath :: IO [FilePath]
 getSearchPath = fmap splitSearchPath (getEnv "PATH")
 
@@ -220,6 +218,7 @@ getSearchPath = fmap splitSearchPath (getEnv "PATH")
 
 -- | Split on the extension. 'addExtension' is the inverse.
 --
+-- > splitExtension "/directory/path.ext" == ("/directory/path",".ext")
 -- > uncurry (++) (splitExtension x) == x
 -- > Valid x => uncurry addExtension (splitExtension x) == x
 -- > splitExtension "file.txt" == ("file",".txt")
@@ -239,41 +238,51 @@ splitExtension x = case nameDot of
 
 -- | Get the extension of a file, returns @\"\"@ for no extension, @.ext@ otherwise.
 --
+-- > takeExtension "/directory/path.ext" == ".ext"
 -- > takeExtension x == snd (splitExtension x)
 -- > Valid x => takeExtension (addExtension x "ext") == ".ext"
 -- > Valid x => takeExtension (replaceExtension x "ext") == ".ext"
 takeExtension :: FilePath -> String
 takeExtension = snd . splitExtension
 
--- | Remove the current extension and add another, an alias for 'replaceExtension'.
+-- | Remove the current extension and add another, equivalent to 'replaceExtension'.
 --
+-- > "/directory/path.txt" -<.> "ext" == "/directory/path.ext"
+-- > "/directory/path.txt" -<.> ".ext" == "/directory/path.ext"
 -- > "foo.o" -<.> "c" == "foo.c"
 (-<.>) :: FilePath -> String -> FilePath
 (-<.>) = replaceExtension
 
--- | Set the extension of a file, overwriting one if already present.
+-- | Set the extension of a file, overwriting one if already present, equivalent to '<.>'.
 --
+-- > replaceExtension "/directory/path.txt" "ext" == "/directory/path.ext"
+-- > replaceExtension "/directory/path.txt" ".ext" == "/directory/path.ext"
 -- > 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"
+-- > replaceExtension x y == addExtension (dropExtension x) y
 replaceExtension :: FilePath -> String -> FilePath
 replaceExtension x y = dropExtension x <.> y
 
--- | Alias to 'addExtension', for people who like that sort of thing.
+-- | Add an extension, even if there is already one there, equivalent to 'addExtension'.
+--
+-- > "/directory/path" <.> "ext" == "/directory/path.ext"
+-- > "/directory/path" <.> ".ext" == "/directory/path.ext"
 (<.>) :: FilePath -> String -> FilePath
 (<.>) = addExtension
 
 -- | Remove last extension, and the \".\" preceding it.
 --
+-- > dropExtension "/directory/path.ext" == "/directory/path"
 -- > dropExtension x == fst (splitExtension x)
 dropExtension :: FilePath -> FilePath
 dropExtension = fst . splitExtension
 
--- | Add an extension, even if there is already one there.
---   E.g. @addExtension \"foo.txt\" \"bat\" -> \"foo.txt.bat\"@.
+-- | Add an extension, even if there is already one there, equivalent to '<.>'.
 --
+-- > addExtension "/directory/path" "ext" == "/directory/path.ext"
 -- > addExtension "file.txt" "bib" == "file.txt.bib"
 -- > addExtension "file." ".bib" == "file..bib"
 -- > addExtension "file" ".bib" == "file.bib"
@@ -291,13 +300,17 @@ addExtension file xs@(x:_) = joinDrive a res
 
 -- | Does the given filename have an extension?
 --
+-- > hasExtension "/directory/path.ext" == True
+-- > hasExtension "/directory/path" == False
 -- > null (takeExtension x) == not (hasExtension x)
 hasExtension :: FilePath -> Bool
 hasExtension = any isExtSeparator . takeFileName
 
 
--- | Split on all extensions
+-- | Split on all extensions.
 --
+-- > splitExtensions "/directory/path.ext" == ("/directory/path",".ext")
+-- > splitExtensions "file.tar.gz" == ("file",".tar.gz")
 -- > uncurry (++) (splitExtensions x) == x
 -- > Valid x => uncurry addExtension (splitExtensions x) == x
 -- > splitExtensions "file.tar.gz" == ("file",".tar.gz")
@@ -307,14 +320,18 @@ splitExtensions x = (a ++ c, d)
         (a,b) = splitFileName_ x
         (c,d) = break isExtSeparator b
 
--- | Drop all extensions
+-- | Drop all extensions.
 --
--- > not $ hasExtension (dropExtensions x)
+-- > dropExtensions "/directory/path.ext" == "/directory/path"
+-- > dropExtensions "file.tar.gz" == "file"
+-- > not $ hasExtension $ dropExtensions x
+-- > not $ any isExtSeparator $ takeFileName $ dropExtensions x
 dropExtensions :: FilePath -> FilePath
 dropExtensions = fst . splitExtensions
 
--- | Get all extensions
+-- | Get all extensions.
 --
+-- > takeExtensions "/directory/path.ext" == ".ext"
 -- > takeExtensions "file.tar.gz" == ".tar.gz"
 takeExtensions :: FilePath -> String
 takeExtensions = snd . splitExtensions
@@ -331,7 +348,7 @@ isLetter x = isAsciiLower x || isAsciiUpper x
 
 
 -- | Split a path into a drive and a path.
---   On Unix, \/ is a Drive.
+--   On Posix, \/ is a Drive.
 --
 -- > uncurry (++) (splitDrive x) == x
 -- > Windows: splitDrive "file" == ("","file")
@@ -449,7 +466,9 @@ isDrive x = not (null x) && null (dropDrive x)
 -- Operations on a filepath, as a list of directories
 
 -- | Split a filename into directory and file. 'combine' is the inverse.
+--   The first component will often end with a trailing slash.
 --
+-- > splitFileName "/directory/file.ext" == ("/directory/","file.ext")
 -- > Valid x => uncurry (</>) (splitFileName x) == x || fst (splitFileName x) == "./"
 -- > Valid x => isValid (fst (splitFileName x))
 -- > splitFileName "file/bob.txt" == ("file/", "bob.txt")
@@ -476,12 +495,15 @@ splitFileName_ x = (drv ++ dir, file)
 
 -- | Set the filename.
 --
+-- > replaceFileName "/directory/other.txt" "file.ext" == "/directory/file.ext"
 -- > Valid x => replaceFileName x (takeFileName x) == x
 replaceFileName :: FilePath -> String -> FilePath
 replaceFileName x y = a </> y where (a,_) = splitFileName_ x
 
--- | Drop the filename.
+-- | Drop the filename. Unlike 'takeDirectory', this function will leave
+--   a trailing path separator on the directory.
 --
+-- > dropFileName "/directory/file.ext" == "/directory/"
 -- > dropFileName x == fst (splitFileName x)
 dropFileName :: FilePath -> FilePath
 dropFileName = fst . splitFileName
@@ -489,6 +511,7 @@ dropFileName = fst . splitFileName
 
 -- | Get the file name.
 --
+-- > takeFileName "/directory/file.ext" == "file.ext"
 -- > takeFileName "test/" == ""
 -- > takeFileName x `isSuffixOf` x
 -- > takeFileName x == snd (splitFileName x)
@@ -500,6 +523,7 @@ takeFileName = snd . splitFileName
 
 -- | Get the base name, without an extension or path.
 --
+-- > takeBaseName "/directory/file.ext" == "file"
 -- > takeBaseName "file/test.txt" == "test"
 -- > takeBaseName "dave.ext" == "dave"
 -- > takeBaseName "" == ""
@@ -511,6 +535,7 @@ takeBaseName = dropExtension . takeFileName
 
 -- | Set the base name.
 --
+-- > replaceBaseName "/directory/other.ext" "file" == "/directory/file.ext"
 -- > replaceBaseName "file/test.txt" "bob" == "file/bob.txt"
 -- > replaceBaseName "fred" "bill" == "bill"
 -- > replaceBaseName "/dave/fred/bob.gz.tar" "new" == "/dave/fred/new.tar"
@@ -560,6 +585,7 @@ dropTrailingPathSeparator x =
 
 -- | Get the directory name, move up one level.
 --
+-- >           takeDirectory "/directory/other.ext" == "/directory"
 -- >           takeDirectory x `isPrefixOf` x || takeDirectory x == "."
 -- >           takeDirectory "foo" == "."
 -- >           takeDirectory "/" == "/"
@@ -575,6 +601,7 @@ takeDirectory = dropTrailingPathSeparator . dropFileName
 
 -- | Set the directory, keeping the filename the same.
 --
+-- > replaceDirectory "root/file.ext" "/directory/" == "/directory/file.ext"
 -- > Valid x => replaceDirectory x (takeDirectory x) `equalFilePath` x
 replaceDirectory :: FilePath -> String -> FilePath
 replaceDirectory x dir = combineAlways dir (takeFileName x)
@@ -627,13 +654,17 @@ combineAlways a b | null a = b
                       _ -> a ++ [pathSeparator] ++ b
 
 
--- | A nice alias for 'combine'.
+-- | Join two values with a path separator. For examples and caveats see the equivalent function 'combine'.
+--
+-- > Posix:   "/directory" </> "file.ext" == "/directory/file.ext"
+-- > Windows: "/directory" </> "file.ext" == "/directory\\file.ext"
 (</>) :: FilePath -> FilePath -> FilePath
 (</>) = combine
 
 
 -- | Split a path by the directory separator.
 --
+-- > splitPath "/directory/file.ext" == ["/","directory/","file.ext"]
 -- > concat (splitPath x) == x
 -- > splitPath "test//item/" == ["test//","item/"]
 -- > splitPath "test/item/file" == ["test/","item/","file"]
@@ -653,6 +684,7 @@ splitPath x = [drive | drive /= ""] ++ f path
 
 -- | Just as 'splitPath', but don't add the trailing slashes to each element.
 --
+-- >          splitDirectories "/directory/file.ext" == ["/","directory","file.ext"]
 -- >          splitDirectories "test/file" == ["test","file"]
 -- >          splitDirectories "/test/file" == ["/","test","file"]
 -- > Windows: splitDirectories "C:\\test\\file" == ["C:\\", "test", "file"]
@@ -666,12 +698,12 @@ splitDirectories = map dropTrailingPathSeparator . splitPath
 
 -- | Join path elements back together.
 --
+-- > joinPath ["/","directory/","file.ext"] == "/directory/file.ext"
 -- > Valid x => joinPath (splitPath x) == x
 -- > joinPath [] == ""
 -- > Posix: joinPath ["test","file","path"] == "test/file/path"
-
--- Note that this definition on c:\\c:\\, join then split will give c:\\.
 joinPath :: [FilePath] -> FilePath
+-- Note that this definition on c:\\c:\\, join then split will give c:\\.
 joinPath = foldr combine ""
 
 
index 014275f..8510eff 100755 (executable)
@@ -28,6 +28,8 @@ tests =
     ,("W.splitSearchPath \"File1;File2;File3\" == [\"File1\", \"File2\", \"File3\"]", test $ W.splitSearchPath "File1;File2;File3" == ["File1", "File2", "File3"])
     ,("W.splitSearchPath \"File1;;File2;File3\" == [\"File1\", \"File2\", \"File3\"]", test $ W.splitSearchPath "File1;;File2;File3" == ["File1", "File2", "File3"])
     ,("W.splitSearchPath \"File1;\\\"File2\\\";File3\" == [\"File1\", \"File2\", \"File3\"]", test $ W.splitSearchPath "File1;\"File2\";File3" == ["File1", "File2", "File3"])
+    ,("P.splitExtension \"/directory/path.ext\" == (\"/directory/path\", \".ext\")", test $ P.splitExtension "/directory/path.ext" == ("/directory/path", ".ext"))
+    ,("W.splitExtension \"/directory/path.ext\" == (\"/directory/path\", \".ext\")", test $ W.splitExtension "/directory/path.ext" == ("/directory/path", ".ext"))
     ,("uncurry (++) (P.splitExtension x) == x", test $ \(QFilePath x) -> uncurry (++) (P.splitExtension x) == x)
     ,("uncurry (++) (W.splitExtension x) == x", test $ \(QFilePath x) -> uncurry (++) (W.splitExtension x) == x)
     ,("uncurry P.addExtension (P.splitExtension x) == x", test $ \(QFilePathValidP x) -> uncurry P.addExtension (P.splitExtension x) == x)
@@ -46,14 +48,24 @@ tests =
     ,("W.splitExtension \"file/path.txt.bob.fred\" == (\"file/path.txt.bob\", \".fred\")", test $ W.splitExtension "file/path.txt.bob.fred" == ("file/path.txt.bob", ".fred"))
     ,("P.splitExtension \"file/path.txt/\" == (\"file/path.txt/\", \"\")", test $ P.splitExtension "file/path.txt/" == ("file/path.txt/", ""))
     ,("W.splitExtension \"file/path.txt/\" == (\"file/path.txt/\", \"\")", test $ W.splitExtension "file/path.txt/" == ("file/path.txt/", ""))
+    ,("P.takeExtension \"/directory/path.ext\" == \".ext\"", test $ P.takeExtension "/directory/path.ext" == ".ext")
+    ,("W.takeExtension \"/directory/path.ext\" == \".ext\"", test $ W.takeExtension "/directory/path.ext" == ".ext")
     ,("P.takeExtension x == snd (P.splitExtension x)", test $ \(QFilePath x) -> P.takeExtension x == snd (P.splitExtension x))
     ,("W.takeExtension x == snd (W.splitExtension x)", test $ \(QFilePath x) -> W.takeExtension x == snd (W.splitExtension x))
     ,("P.takeExtension (P.addExtension x \"ext\") == \".ext\"", test $ \(QFilePathValidP x) -> P.takeExtension (P.addExtension x "ext") == ".ext")
     ,("W.takeExtension (W.addExtension x \"ext\") == \".ext\"", test $ \(QFilePathValidW x) -> W.takeExtension (W.addExtension x "ext") == ".ext")
     ,("P.takeExtension (P.replaceExtension x \"ext\") == \".ext\"", test $ \(QFilePathValidP x) -> P.takeExtension (P.replaceExtension x "ext") == ".ext")
     ,("W.takeExtension (W.replaceExtension x \"ext\") == \".ext\"", test $ \(QFilePathValidW x) -> W.takeExtension (W.replaceExtension x "ext") == ".ext")
+    ,("\"/directory/path.txt\" P.-<.> \"ext\" == \"/directory/path.ext\"", test $ "/directory/path.txt" P.-<.> "ext" == "/directory/path.ext")
+    ,("\"/directory/path.txt\" W.-<.> \"ext\" == \"/directory/path.ext\"", test $ "/directory/path.txt" W.-<.> "ext" == "/directory/path.ext")
+    ,("\"/directory/path.txt\" P.-<.> \".ext\" == \"/directory/path.ext\"", test $ "/directory/path.txt" P.-<.> ".ext" == "/directory/path.ext")
+    ,("\"/directory/path.txt\" W.-<.> \".ext\" == \"/directory/path.ext\"", test $ "/directory/path.txt" W.-<.> ".ext" == "/directory/path.ext")
     ,("\"foo.o\" P.-<.> \"c\" == \"foo.c\"", test $ "foo.o" P.-<.> "c" == "foo.c")
     ,("\"foo.o\" W.-<.> \"c\" == \"foo.c\"", test $ "foo.o" W.-<.> "c" == "foo.c")
+    ,("P.replaceExtension \"/directory/path.txt\" \"ext\" == \"/directory/path.ext\"", test $ P.replaceExtension "/directory/path.txt" "ext" == "/directory/path.ext")
+    ,("W.replaceExtension \"/directory/path.txt\" \"ext\" == \"/directory/path.ext\"", test $ W.replaceExtension "/directory/path.txt" "ext" == "/directory/path.ext")
+    ,("P.replaceExtension \"/directory/path.txt\" \".ext\" == \"/directory/path.ext\"", test $ P.replaceExtension "/directory/path.txt" ".ext" == "/directory/path.ext")
+    ,("W.replaceExtension \"/directory/path.txt\" \".ext\" == \"/directory/path.ext\"", test $ W.replaceExtension "/directory/path.txt" ".ext" == "/directory/path.ext")
     ,("P.replaceExtension \"file.txt\" \".bob\" == \"file.bob\"", test $ P.replaceExtension "file.txt" ".bob" == "file.bob")
     ,("W.replaceExtension \"file.txt\" \".bob\" == \"file.bob\"", test $ W.replaceExtension "file.txt" ".bob" == "file.bob")
     ,("P.replaceExtension \"file.txt\" \"bob\" == \"file.bob\"", test $ P.replaceExtension "file.txt" "bob" == "file.bob")
@@ -64,8 +76,18 @@ tests =
     ,("W.replaceExtension \"file.txt\" \"\" == \"file\"", test $ W.replaceExtension "file.txt" "" == "file")
     ,("P.replaceExtension \"file.fred.bob\" \"txt\" == \"file.fred.txt\"", test $ P.replaceExtension "file.fred.bob" "txt" == "file.fred.txt")
     ,("W.replaceExtension \"file.fred.bob\" \"txt\" == \"file.fred.txt\"", test $ W.replaceExtension "file.fred.bob" "txt" == "file.fred.txt")
+    ,("P.replaceExtension x y == P.addExtension (P.dropExtension x) y", test $ \(QFilePath x) (QFilePath y) -> P.replaceExtension x y == P.addExtension (P.dropExtension x) y)
+    ,("W.replaceExtension x y == W.addExtension (W.dropExtension x) y", test $ \(QFilePath x) (QFilePath y) -> W.replaceExtension x y == W.addExtension (W.dropExtension x) y)
+    ,("\"/directory/path\" P.<.> \"ext\" == \"/directory/path.ext\"", test $ "/directory/path" P.<.> "ext" == "/directory/path.ext")
+    ,("\"/directory/path\" W.<.> \"ext\" == \"/directory/path.ext\"", test $ "/directory/path" W.<.> "ext" == "/directory/path.ext")
+    ,("\"/directory/path\" P.<.> \".ext\" == \"/directory/path.ext\"", test $ "/directory/path" P.<.> ".ext" == "/directory/path.ext")
+    ,("\"/directory/path\" W.<.> \".ext\" == \"/directory/path.ext\"", test $ "/directory/path" W.<.> ".ext" == "/directory/path.ext")
+    ,("P.dropExtension \"/directory/path.ext\" == \"/directory/path\"", test $ P.dropExtension "/directory/path.ext" == "/directory/path")
+    ,("W.dropExtension \"/directory/path.ext\" == \"/directory/path\"", test $ W.dropExtension "/directory/path.ext" == "/directory/path")
     ,("P.dropExtension x == fst (P.splitExtension x)", test $ \(QFilePath x) -> P.dropExtension x == fst (P.splitExtension x))
     ,("W.dropExtension x == fst (W.splitExtension x)", test $ \(QFilePath x) -> W.dropExtension x == fst (W.splitExtension x))
+    ,("P.addExtension \"/directory/path\" \"ext\" == \"/directory/path.ext\"", test $ P.addExtension "/directory/path" "ext" == "/directory/path.ext")
+    ,("W.addExtension \"/directory/path\" \"ext\" == \"/directory/path.ext\"", test $ W.addExtension "/directory/path" "ext" == "/directory/path.ext")
     ,("P.addExtension \"file.txt\" \"bib\" == \"file.txt.bib\"", test $ P.addExtension "file.txt" "bib" == "file.txt.bib")
     ,("W.addExtension \"file.txt\" \"bib\" == \"file.txt.bib\"", test $ W.addExtension "file.txt" "bib" == "file.txt.bib")
     ,("P.addExtension \"file.\" \".bib\" == \"file..bib\"", test $ P.addExtension "file." ".bib" == "file..bib")
@@ -77,16 +99,32 @@ tests =
     ,("P.takeFileName (P.addExtension (P.addTrailingPathSeparator x) \"ext\") == \".ext\"", test $ \(QFilePathValidP x) -> P.takeFileName (P.addExtension (P.addTrailingPathSeparator x) "ext") == ".ext")
     ,("W.takeFileName (W.addExtension (W.addTrailingPathSeparator x) \"ext\") == \".ext\"", test $ \(QFilePathValidW x) -> W.takeFileName (W.addExtension (W.addTrailingPathSeparator x) "ext") == ".ext")
     ,("W.addExtension \"\\\\\\\\share\" \".txt\" == \"\\\\\\\\share\\\\.txt\"", test $ W.addExtension "\\\\share" ".txt" == "\\\\share\\.txt")
+    ,("P.hasExtension \"/directory/path.ext\" == True", test $ P.hasExtension "/directory/path.ext" == True)
+    ,("W.hasExtension \"/directory/path.ext\" == True", test $ W.hasExtension "/directory/path.ext" == True)
+    ,("P.hasExtension \"/directory/path\" == False", test $ P.hasExtension "/directory/path" == False)
+    ,("W.hasExtension \"/directory/path\" == False", test $ W.hasExtension "/directory/path" == False)
     ,("null (P.takeExtension x) == not (P.hasExtension x)", test $ \(QFilePath x) -> null (P.takeExtension x) == not (P.hasExtension x))
     ,("null (W.takeExtension x) == not (W.hasExtension x)", test $ \(QFilePath x) -> null (W.takeExtension x) == not (W.hasExtension x))
+    ,("P.splitExtensions \"/directory/path.ext\" == (\"/directory/path\", \".ext\")", test $ P.splitExtensions "/directory/path.ext" == ("/directory/path", ".ext"))
+    ,("W.splitExtensions \"/directory/path.ext\" == (\"/directory/path\", \".ext\")", test $ W.splitExtensions "/directory/path.ext" == ("/directory/path", ".ext"))
+    ,("P.splitExtensions \"file.tar.gz\" == (\"file\", \".tar.gz\")", test $ P.splitExtensions "file.tar.gz" == ("file", ".tar.gz"))
+    ,("W.splitExtensions \"file.tar.gz\" == (\"file\", \".tar.gz\")", test $ W.splitExtensions "file.tar.gz" == ("file", ".tar.gz"))
     ,("uncurry (++) (P.splitExtensions x) == x", test $ \(QFilePath x) -> uncurry (++) (P.splitExtensions x) == x)
     ,("uncurry (++) (W.splitExtensions x) == x", test $ \(QFilePath x) -> uncurry (++) (W.splitExtensions x) == x)
     ,("uncurry P.addExtension (P.splitExtensions x) == x", test $ \(QFilePathValidP x) -> uncurry P.addExtension (P.splitExtensions x) == x)
     ,("uncurry W.addExtension (W.splitExtensions x) == x", test $ \(QFilePathValidW x) -> uncurry W.addExtension (W.splitExtensions x) == x)
     ,("P.splitExtensions \"file.tar.gz\" == (\"file\", \".tar.gz\")", test $ P.splitExtensions "file.tar.gz" == ("file", ".tar.gz"))
     ,("W.splitExtensions \"file.tar.gz\" == (\"file\", \".tar.gz\")", test $ W.splitExtensions "file.tar.gz" == ("file", ".tar.gz"))
-    ,("not $ P.hasExtension (P.dropExtensions x)", test $ \(QFilePath x) -> not $ P.hasExtension (P.dropExtensions x))
-    ,("not $ W.hasExtension (W.dropExtensions x)", test $ \(QFilePath x) -> not $ W.hasExtension (W.dropExtensions x))
+    ,("P.dropExtensions \"/directory/path.ext\" == \"/directory/path\"", test $ P.dropExtensions "/directory/path.ext" == "/directory/path")
+    ,("W.dropExtensions \"/directory/path.ext\" == \"/directory/path\"", test $ W.dropExtensions "/directory/path.ext" == "/directory/path")
+    ,("P.dropExtensions \"file.tar.gz\" == \"file\"", test $ P.dropExtensions "file.tar.gz" == "file")
+    ,("W.dropExtensions \"file.tar.gz\" == \"file\"", test $ W.dropExtensions "file.tar.gz" == "file")
+    ,("not $ P.hasExtension $ P.dropExtensions x", test $ \(QFilePath x) -> not $ P.hasExtension $ P.dropExtensions x)
+    ,("not $ W.hasExtension $ W.dropExtensions x", test $ \(QFilePath x) -> not $ W.hasExtension $ W.dropExtensions x)
+    ,("not $ any P.isExtSeparator $ P.takeFileName $ P.dropExtensions x", test $ \(QFilePath x) -> not $ any P.isExtSeparator $ P.takeFileName $ P.dropExtensions x)
+    ,("not $ any W.isExtSeparator $ W.takeFileName $ W.dropExtensions x", test $ \(QFilePath x) -> not $ any W.isExtSeparator $ W.takeFileName $ W.dropExtensions x)
+    ,("P.takeExtensions \"/directory/path.ext\" == \".ext\"", test $ P.takeExtensions "/directory/path.ext" == ".ext")
+    ,("W.takeExtensions \"/directory/path.ext\" == \".ext\"", test $ W.takeExtensions "/directory/path.ext" == ".ext")
     ,("P.takeExtensions \"file.tar.gz\" == \".tar.gz\"", test $ P.takeExtensions "file.tar.gz" == ".tar.gz")
     ,("W.takeExtensions \"file.tar.gz\" == \".tar.gz\"", test $ W.takeExtensions "file.tar.gz" == ".tar.gz")
     ,("uncurry (++) (P.splitDrive x) == x", test $ \(QFilePath x) -> uncurry (++) (P.splitDrive x) == x)
@@ -129,6 +167,8 @@ tests =
     ,("W.isDrive \"C:\\\\foo\" == False", test $ W.isDrive "C:\\foo" == False)
     ,("P.isDrive \"\" == False", test $ P.isDrive "" == False)
     ,("W.isDrive \"\" == False", test $ W.isDrive "" == False)
+    ,("P.splitFileName \"/directory/file.ext\" == (\"/directory/\", \"file.ext\")", test $ P.splitFileName "/directory/file.ext" == ("/directory/", "file.ext"))
+    ,("W.splitFileName \"/directory/file.ext\" == (\"/directory/\", \"file.ext\")", test $ W.splitFileName "/directory/file.ext" == ("/directory/", "file.ext"))
     ,("uncurry (P.</>) (P.splitFileName x) == x || fst (P.splitFileName x) == \"./\"", test $ \(QFilePathValidP x) -> uncurry (P.</>) (P.splitFileName x) == x || fst (P.splitFileName x) == "./")
     ,("uncurry (W.</>) (W.splitFileName x) == x || fst (W.splitFileName x) == \"./\"", test $ \(QFilePathValidW x) -> uncurry (W.</>) (W.splitFileName x) == x || fst (W.splitFileName x) == "./")
     ,("P.isValid (fst (P.splitFileName x))", test $ \(QFilePathValidP x) -> P.isValid (fst (P.splitFileName x)))
@@ -141,10 +181,16 @@ tests =
     ,("W.splitFileName \"bob\" == (\"./\", \"bob\")", test $ W.splitFileName "bob" == ("./", "bob"))
     ,("P.splitFileName \"/\" == (\"/\", \"\")", test $ P.splitFileName "/" == ("/", ""))
     ,("W.splitFileName \"c:\" == (\"c:\", \"\")", test $ W.splitFileName "c:" == ("c:", ""))
+    ,("P.replaceFileName \"/directory/other.txt\" \"file.ext\" == \"/directory/file.ext\"", test $ P.replaceFileName "/directory/other.txt" "file.ext" == "/directory/file.ext")
+    ,("W.replaceFileName \"/directory/other.txt\" \"file.ext\" == \"/directory/file.ext\"", test $ W.replaceFileName "/directory/other.txt" "file.ext" == "/directory/file.ext")
     ,("P.replaceFileName x (P.takeFileName x) == x", test $ \(QFilePathValidP x) -> P.replaceFileName x (P.takeFileName x) == x)
     ,("W.replaceFileName x (W.takeFileName x) == x", test $ \(QFilePathValidW x) -> W.replaceFileName x (W.takeFileName x) == x)
+    ,("P.dropFileName \"/directory/file.ext\" == \"/directory/\"", test $ P.dropFileName "/directory/file.ext" == "/directory/")
+    ,("W.dropFileName \"/directory/file.ext\" == \"/directory/\"", test $ W.dropFileName "/directory/file.ext" == "/directory/")
     ,("P.dropFileName x == fst (P.splitFileName x)", test $ \(QFilePath x) -> P.dropFileName x == fst (P.splitFileName x))
     ,("W.dropFileName x == fst (W.splitFileName x)", test $ \(QFilePath x) -> W.dropFileName x == fst (W.splitFileName x))
+    ,("P.takeFileName \"/directory/file.ext\" == \"file.ext\"", test $ P.takeFileName "/directory/file.ext" == "file.ext")
+    ,("W.takeFileName \"/directory/file.ext\" == \"file.ext\"", test $ W.takeFileName "/directory/file.ext" == "file.ext")
     ,("P.takeFileName \"test/\" == \"\"", test $ P.takeFileName "test/" == "")
     ,("W.takeFileName \"test/\" == \"\"", test $ W.takeFileName "test/" == "")
     ,("P.takeFileName x `isSuffixOf` x", test $ \(QFilePath x) -> P.takeFileName x `isSuffixOf` x)
@@ -157,6 +203,8 @@ tests =
     ,("W.takeFileName (x W.</> \"fred\") == \"fred\"", test $ \(QFilePathValidW x) -> W.takeFileName (x W.</> "fred") == "fred")
     ,("P.isRelative (P.takeFileName x)", test $ \(QFilePathValidP x) -> P.isRelative (P.takeFileName x))
     ,("W.isRelative (W.takeFileName x)", test $ \(QFilePathValidW x) -> W.isRelative (W.takeFileName x))
+    ,("P.takeBaseName \"/directory/file.ext\" == \"file\"", test $ P.takeBaseName "/directory/file.ext" == "file")
+    ,("W.takeBaseName \"/directory/file.ext\" == \"file\"", test $ W.takeBaseName "/directory/file.ext" == "file")
     ,("P.takeBaseName \"file/test.txt\" == \"test\"", test $ P.takeBaseName "file/test.txt" == "test")
     ,("W.takeBaseName \"file/test.txt\" == \"test\"", test $ W.takeBaseName "file/test.txt" == "test")
     ,("P.takeBaseName \"dave.ext\" == \"dave\"", test $ P.takeBaseName "dave.ext" == "dave")
@@ -169,6 +217,8 @@ tests =
     ,("W.takeBaseName (W.addTrailingPathSeparator x) == \"\"", test $ \(QFilePath x) -> W.takeBaseName (W.addTrailingPathSeparator x) == "")
     ,("P.takeBaseName \"file/file.tar.gz\" == \"file.tar\"", test $ P.takeBaseName "file/file.tar.gz" == "file.tar")
     ,("W.takeBaseName \"file/file.tar.gz\" == \"file.tar\"", test $ W.takeBaseName "file/file.tar.gz" == "file.tar")
+    ,("P.replaceBaseName \"/directory/other.ext\" \"file\" == \"/directory/file.ext\"", test $ P.replaceBaseName "/directory/other.ext" "file" == "/directory/file.ext")
+    ,("W.replaceBaseName \"/directory/other.ext\" \"file\" == \"/directory/file.ext\"", test $ W.replaceBaseName "/directory/other.ext" "file" == "/directory/file.ext")
     ,("P.replaceBaseName \"file/test.txt\" \"bob\" == \"file/bob.txt\"", test $ P.replaceBaseName "file/test.txt" "bob" == "file/bob.txt")
     ,("W.replaceBaseName \"file/test.txt\" \"bob\" == \"file/bob.txt\"", test $ W.replaceBaseName "file/test.txt" "bob" == "file/bob.txt")
     ,("P.replaceBaseName \"fred\" \"bill\" == \"bill\"", test $ P.replaceBaseName "fred" "bill" == "bill")
@@ -192,6 +242,8 @@ tests =
     ,("W.dropTrailingPathSeparator \"/\" == \"/\"", test $ W.dropTrailingPathSeparator "/" == "/")
     ,("W.dropTrailingPathSeparator \"\\\\\" == \"\\\\\"", test $ W.dropTrailingPathSeparator "\\" == "\\")
     ,("not (P.hasTrailingPathSeparator (P.dropTrailingPathSeparator x)) || P.isDrive x", test $ \(QFilePath x) -> not (P.hasTrailingPathSeparator (P.dropTrailingPathSeparator x)) || P.isDrive x)
+    ,("P.takeDirectory \"/directory/other.ext\" == \"/directory\"", test $ P.takeDirectory "/directory/other.ext" == "/directory")
+    ,("W.takeDirectory \"/directory/other.ext\" == \"/directory\"", test $ W.takeDirectory "/directory/other.ext" == "/directory")
     ,("P.takeDirectory x `isPrefixOf` x || P.takeDirectory x == \".\"", test $ \(QFilePath x) -> P.takeDirectory x `isPrefixOf` x || P.takeDirectory x == ".")
     ,("W.takeDirectory x `isPrefixOf` x || W.takeDirectory x == \".\"", test $ \(QFilePath x) -> W.takeDirectory x `isPrefixOf` x || W.takeDirectory x == ".")
     ,("P.takeDirectory \"foo\" == \".\"", test $ P.takeDirectory "foo" == ".")
@@ -209,6 +261,8 @@ tests =
     ,("W.takeDirectory \"foo\\\\bar\" == \"foo\"", test $ W.takeDirectory "foo\\bar" == "foo")
     ,("W.takeDirectory \"foo\\\\bar\\\\\\\\\" == \"foo\\\\bar\"", test $ W.takeDirectory "foo\\bar\\\\" == "foo\\bar")
     ,("W.takeDirectory \"C:\\\\\" == \"C:\\\\\"", test $ W.takeDirectory "C:\\" == "C:\\")
+    ,("P.replaceDirectory \"root/file.ext\" \"/directory/\" == \"/directory/file.ext\"", test $ P.replaceDirectory "root/file.ext" "/directory/" == "/directory/file.ext")
+    ,("W.replaceDirectory \"root/file.ext\" \"/directory/\" == \"/directory/file.ext\"", test $ W.replaceDirectory "root/file.ext" "/directory/" == "/directory/file.ext")
     ,("P.replaceDirectory x (P.takeDirectory x) `P.equalFilePath` x", test $ \(QFilePathValidP x) -> P.replaceDirectory x (P.takeDirectory x) `P.equalFilePath` x)
     ,("W.replaceDirectory x (W.takeDirectory x) `W.equalFilePath` x", test $ \(QFilePathValidW x) -> W.replaceDirectory x (W.takeDirectory x) `W.equalFilePath` x)
     ,("P.combine (P.takeDirectory x) (P.takeFileName x) `P.equalFilePath` x", test $ \(QFilePathValidP x) -> P.combine (P.takeDirectory x) (P.takeFileName x) `P.equalFilePath` x)
@@ -225,6 +279,10 @@ tests =
     ,("W.combine \"C:\\\\home\" \"\\\\bob\" == \"\\\\bob\"", test $ W.combine "C:\\home" "\\bob" == "\\bob")
     ,("W.combine \"D:\\\\foo\" \"C:bar\" == \"C:bar\"", test $ W.combine "D:\\foo" "C:bar" == "C:bar")
     ,("W.combine \"C:\\\\foo\" \"C:bar\" == \"C:bar\"", test $ W.combine "C:\\foo" "C:bar" == "C:bar")
+    ,("\"/directory\" P.</> \"file.ext\" == \"/directory/file.ext\"", test $ "/directory" P.</> "file.ext" == "/directory/file.ext")
+    ,("\"/directory\" W.</> \"file.ext\" == \"/directory\\\\file.ext\"", test $ "/directory" W.</> "file.ext" == "/directory\\file.ext")
+    ,("P.splitPath \"/directory/file.ext\" == [\"/\", \"directory/\", \"file.ext\"]", test $ P.splitPath "/directory/file.ext" == ["/", "directory/", "file.ext"])
+    ,("W.splitPath \"/directory/file.ext\" == [\"/\", \"directory/\", \"file.ext\"]", test $ W.splitPath "/directory/file.ext" == ["/", "directory/", "file.ext"])
     ,("concat (P.splitPath x) == x", test $ \(QFilePath x) -> concat (P.splitPath x) == x)
     ,("concat (W.splitPath x) == x", test $ \(QFilePath x) -> concat (W.splitPath x) == x)
     ,("P.splitPath \"test//item/\" == [\"test//\", \"item/\"]", test $ P.splitPath "test//item/" == ["test//", "item/"])
@@ -235,6 +293,8 @@ tests =
     ,("W.splitPath \"\" == []", test $ W.splitPath "" == [])
     ,("W.splitPath \"c:\\\\test\\\\path\" == [\"c:\\\\\", \"test\\\\\", \"path\"]", test $ W.splitPath "c:\\test\\path" == ["c:\\", "test\\", "path"])
     ,("P.splitPath \"/file/test\" == [\"/\", \"file/\", \"test\"]", test $ P.splitPath "/file/test" == ["/", "file/", "test"])
+    ,("P.splitDirectories \"/directory/file.ext\" == [\"/\", \"directory\", \"file.ext\"]", test $ P.splitDirectories "/directory/file.ext" == ["/", "directory", "file.ext"])
+    ,("W.splitDirectories \"/directory/file.ext\" == [\"/\", \"directory\", \"file.ext\"]", test $ W.splitDirectories "/directory/file.ext" == ["/", "directory", "file.ext"])
     ,("P.splitDirectories \"test/file\" == [\"test\", \"file\"]", test $ P.splitDirectories "test/file" == ["test", "file"])
     ,("W.splitDirectories \"test/file\" == [\"test\", \"file\"]", test $ W.splitDirectories "test/file" == ["test", "file"])
     ,("P.splitDirectories \"/test/file\" == [\"/\", \"test\", \"file\"]", test $ P.splitDirectories "/test/file" == ["/", "test", "file"])
@@ -247,6 +307,8 @@ tests =
     ,("W.splitDirectories \"C:\\\\test\\\\\\\\\\\\file\" == [\"C:\\\\\", \"test\", \"file\"]", test $ W.splitDirectories "C:\\test\\\\\\file" == ["C:\\", "test", "file"])
     ,("P.splitDirectories \"/test///file\" == [\"/\", \"test\", \"file\"]", test $ P.splitDirectories "/test///file" == ["/", "test", "file"])
     ,("W.splitDirectories \"/test///file\" == [\"/\", \"test\", \"file\"]", test $ W.splitDirectories "/test///file" == ["/", "test", "file"])
+    ,("P.joinPath [\"/\", \"directory/\", \"file.ext\"] == \"/directory/file.ext\"", test $ P.joinPath ["/", "directory/", "file.ext"] == "/directory/file.ext")
+    ,("W.joinPath [\"/\", \"directory/\", \"file.ext\"] == \"/directory/file.ext\"", test $ W.joinPath ["/", "directory/", "file.ext"] == "/directory/file.ext")
     ,("P.joinPath (P.splitPath x) == x", test $ \(QFilePathValidP x) -> P.joinPath (P.splitPath x) == x)
     ,("W.joinPath (W.splitPath x) == x", test $ \(QFilePathValidW x) -> W.joinPath (W.splitPath x) == x)
     ,("P.joinPath [] == \"\"", test $ P.joinPath [] == "")