pathtype 0.5.5 → 0.8.1.4
raw patch · 26 files changed
Files
- CHANGELOG +141/−0
- README.md +243/−0
- pathtype.cabal +102/−107
- posix/System/Path/Host.hs +2/−0
- src/System/Path.hs +24/−85
- src/System/Path/Directory.hs +87/−65
- src/System/Path/Generic.hs +22/−0
- src/System/Path/IO.hs +34/−24
- src/System/Path/Internal.hs +1704/−957
- src/System/Path/Internal/Component.hs +88/−0
- src/System/Path/Internal/Part.hs +43/−0
- src/System/Path/Internal/PartClass.hs +160/−0
- src/System/Path/Internal/Separator.hs +14/−0
- src/System/Path/Internal/System.hs +37/−0
- src/System/Path/Part.hs +11/−0
- src/System/Path/PartClass.hs +6/−0
- src/System/Path/Posix.hs +237/−10
- src/System/Path/RegularExpression.hs +34/−0
- src/System/Path/Windows.hs +247/−10
- test/Test.hs +17/−22
- test/Test/Posix/System/Path/Internal.hs +1044/−0
- test/Test/Windows/System/Path/Internal.hs +1044/−0
- test/TestResult.hs +0/−215
- test/TestTemplate.hs +0/−11
- tool/CreateTest.hs +0/−31
- windows/System/Path/Host.hs +2/−0
+ CHANGELOG view
@@ -0,0 +1,141 @@+0.8:++* relPath, absPath, filePath, dirPath deprecated in favor of+ Path.rel, Path.abs, Path.absRel, Path.file, Path.dir+ Same for the according type synonyms.++* Deprecate extended path construction functions:+ mkAbsPath, mkAbsPathFromCwd, mkPathAbsOrRel, mkPathFileOrDir+ You better combine path constructors and further manipulations.++* Deprecate functions based on path strings.+ You should better use functions from the filepath package.++* absRel -> withAbsRel, fileDir -> withFileDir+ We do not need these functions very often+ and instead we need Path.absRel as constructor name+ that is consistent with Path.abs and Path.rel.++* Split main module into multiple one,+ in order to use a consistent name set for every aspect.++ E.g. we have:+ Path.Abs: an absolute path+ Path.Part.Abs: absolute (drive) part of a path+ Path.PartClass.Abs: class for an absolute part++ Path.AbsRel: an absolute or relative path+ Path.Part.AbsRel: initial part of an absolute or relative path+ Path.PartClass.AbsRel: class for absolute or relative parts++ Path.Abs -> Part.Abs+ Path.AbsOrRel -> Part.AbsRel+ Path.AbsOrRelClass -> PartClass.AbsRel+ Path.FileOrDirClass -> PartClass.FileDir++0.7:++* Move absRel and fileDir out of their classes.+ A problem would arise if someone writes+ import System.Path (AbsRelClass(absRel))+ He would have to replace it by+ import System.Path (AbsRelClass, absRel)++* Monoid instance for Path.RelDir+ Requires helper classes IsRel, IsDir.+ IsAbs and IsFile added for completeness.++* Declare infix precedences of </>, <.> and <++> such that we can write:+ dir0 </> dir1 </> dir2 </> base <++> "-foo" <++> "-bar" <.> "tar" <.> "gz"+ This is similar to the fixities in the 'filepath' package,+ but differs slightly+ since in our package paths and extensions have different types.++* Import packages 'transformers' and 'utility-ht'+ that allow for some simplifications.++* Deprecate asPath,+ asRelFile, asRelDir, asAbsFile, asAbsDir,+ asRelPath, asAbsPath, asFilePath, asDirPath++* Recommended are now the checking constructors 'path', maybePath, parsePath,+ relFile, relDir, absFile, absDir,+ relPath, absPath, filePath, dirPath++* replace IsString instance for OverloadedStrings+ by an instance that cannot be implemented.++* getDirectoryContents is no longer synonym to relDirectoryContents.+ Instead it returns the list of all directory objects as RelFileOrDir.+ This is closer to the getDirectoryContents function+ from the 'directory' package.++* clarify meaning of AbsRel and FileDir tags of a path++* clarify meaning of drive-relative paths on Windows++* clarify handling of file system links++0.6:++* joinPath: restrict to RelPath and atomic path components++* Add type class constraints and restrict types+ in order to make the functions work with the new datatype.+ E.g. we need to fix the type to FilePath+ wherever a function requires a non-empty path.++* Add support for MS Windows paths with leading drive labels++0.5.5:++* AbsRelClass, FileDirClass: turn into closed-world classes.+ Strict accordance to PVP would require to bump version to 0.6,+ but since the user cannot write instances of this class,+ we can hardly break code.++* instance {Show, Read} Path now emit and parse valid Haskell expressions++* IO.withFile restricted to FilePath+ This changes API but it should only break buggy code.++0.5.4.3:++* Make test suite static part of the source code,+ but maintain a program to update the test suite to changed tests.++0.5.4.1:++* Merge git back to darcs, continue on hub.darcs.net++0.5.4:++* Migrated from darcs to git (on GitHub)++0.5.3:++* Upgrades + changes for GHC 7.6.1 - by Ben Millwood++0.5.0:++* Added System.Path.Windows and System.Path.Posix modules. These are modelled on the System.FilePath approach to supporting the two styles of path.++0.0.2:++* Split System.Path.Directory into its own module+* Implemented covers for all the remaining System.Directory functions+* Renamed 'hasExtension' to 'hasAnExtension', and added new 'hasExtension' fn which checks for a given extension+* Renamed the '...FileOrDir...' functions to be 'generic...' (thanks to Neil Mitchell for the suggestion!)+* Added support for OverloadedStrings+* Renamed the 'mk...' unchecked construction functions to 'as...' to better reflect what they do+* Added: makeAbsolute, makeAbsoluteFromCwd, genericMakeAbsolute, genericMakeAbsoluteFromCwd+* Added: mkAbsPath, mkAbsPathFromCwd+* Added System.Path.IO to cover System.IO+* Made the internal 'Path' type strict+* Removed 'splitDirectories' as it serves no purpose not covered by 'splitPath'+* Changed behaviour of 'getDirectoryContents' to return relative paths+* Fixed the type of 'setCurrentDirectory'++0.0.1:++Initial Release
+ README.md view
@@ -0,0 +1,243 @@+# Construction of type-safe paths++You can use the construction functions as follows:++ f :: Path.RelFile+ f = relDir "tmp" </> relFile "someFile" <.> "ext"++or ...++ f :: Path.RelFile+ f = dirPath "tmp" </> filePath "someFile" <.> "ext"++or ...++ f :: Path.RelFile+ f = path "tmp" </> path "someFile" <.> "ext"++or just ...++ f :: Path.RelFile+ f = relFile "tmp/someFile.ext"++The first and the last implementations force the most specific types+and thus should be prefered.++Overloaded string literals are no longer supported,+since this extension is intended for alternative text storage types.+It would also decrease the type safety+if you could omit the path type and let the compiler guess its type.+++# Modules++You will typically want to import as follows:++ import qualified System.Path.Directory as Dir+ import qualified System.Path.IO as PathIO+ import qualified System.Path as Path+ import System.Path ((</>))++`System.Path.Generic` provides all functions with the OS as type parameter.+`System.Path.Posix` and `System.Path.Windows`+offers only path constructors and destructors+fixed to the corresponding operating system.+`System.Path` exports either `System.Path.Posix` or `System.Path.Windows`+depending on the host system+and additionally the manipulation functions from `System.Path.Generic`.+This mix should be appropriate for the average use+and should free the user from writing type annotations.+++# How to choose proper type arguments++The `ar` and the `fd` type parameters have quite different meaning.+The types `Abs` and `Rel` refer to a property of the path,+whereas the type `File` and `Dir` refers to a property of a disk object.+You can decide whether a path is absolute or relative+by just watching (the beginning of) the path string.+In contrast to that, you have to access the disk+in order to check the existence and type of a disk object.+Even more, the disk object might change at any time,+e.g. the user might delete a file and create a directory of the same name,+or the disk object might not exist,+and the purpose of the path is to create an according file or directory.+That's why even if you have a path of type `FilePath ar`,+every function accessing the file must check+that the refered object exists and is a file.+Conversely, there is not much sense in checking the disk object type+and then chosing the path accordingly.+Instead, you must choose the path type according+to what type of disk object your application needs.+The reality check must be performed+and is performed by the standard functions+for every access to the object.+If a disk object is not of the type required by the path type+then this is a runtime exception that must be handled at runtime+but it is not a programming error.++Sometimes you have to change the type of a path+as an intermediate step to construct a path for an object of different type.+E.g. you may convert the path "pkg" from `DirPath` to `FilePath`+because in the next step you like to extend it to "pkg.tar.gz".+This is valid use of the `Path` type.+E.g. the function `dropExtensions`+reduces the `FilePath` "pkg.tar.gz" to the new `FilePath` "pkg"+although no-one expects that there is or will be a file with name "pkg".+Thus, if a function has a `FilePath` parameter+then there is no warranty that it accesses the according file+and does not touch related disk objects.+It may well be that the function derives other file and directory names+from the path and accesses them.+That is, a `FilePath` or `DirPath` parameter+is mainly for documentation purposes+but it cannot prevent you seriously from any damage.+++# How to cope with user input++You may get a path from the user, e.g. as command-line argument.+It might be either absolute or relative+and it might refer to an actual file or directory or+to something yet non-existing.+In most cases it will not be important+whether the path is absolute or relative,+thus you should choose the `AbsRel` type parameter.+If somewhere in the program an `Abs` path is needed+then you can assert that the path is actually absolutized somewhere+e.g. by `dynamicMakeAbsolute`.+If you prevent usage of `genericMakeAbsolute`+then you avoid to absolutize a path that is already absolutized.++The choice of the `fd` type parameter follows a different reasoning:+Often you have a clear idea of+whether the user must pass a file or directory path.+The rule is: Just give the path the type you expect+but do not perform any checking+(unless you want to warn the user earlier about imminent danger).+The disk object type must be checked for every access to the object, anyway,+so there is no point in checking it immediately.+With your choice of the `fd` parameter+you just document its intended use.++It might be that the path is only a base name+used to construct other directory and file names.+E.g. for an Audacity project named `music`+you have to create the directory `music_data` and the file `music.aup`.+In this case we recommend to give `music` the type `FilePath`.+This type warrants that there is at least one final path component+in contrast to a directory path that might be empty.+You can easily convert a file path to a directory path+using `Path.dirFromFile`.+The reverse conversion is partial.+++# AbsRel vs. `ar` type parameter++In your application you will often know+whether your path denotes a file or directory,+thus you will use the `Path.File` or `Path.Dir` type synonym.+In contrast to that, you will often not know+whether the path is relative or absolute+and often it does not even matter.+You can express this either by using the monomorphic type `Path.AbsRelFile`+or by using the parameterized type `Path.File ar`+with constraint `PathClass.AbsRel ar`.+We recommend to use the first variant for command-line option parsing+and the second one for the application functions.+When you parse options it is the time where you know that you do not know+whether the path is absolute or relative.+That is, you could neither parse it as `Path.Abs` nor as `Path.Rel`.+Thus a type variable makes no sense.+You should always parse to type `Path.AbsRel`.+Conversely, your application would work equally well with+`Path.Abs`, `Path.Rel` and `Path.AbsRel`.+Thus, using an `ar` type variable is the way to go.+You must make sure to use different `ar`-like variables for independent paths.+By equality of `ar`-like type variables+you can also document dependencies of paths for the programmers.+++# Command-line argument parsing with `optparse-applicative`++For parsing of path options with the `optparse-applicative` package+you might use the following helper functions:++ module Option where++ import qualified System.Path.PartClass as PathC+ import qualified System.Path as Path+ import qualified Options.Applicative as OP++ path :: (PathC.FileDir fd) => OP.ReadM (Path.AbsRel fd)+ path = OP.eitherReader Path.parse++ pathArgument ::+ PathC.FileDir fd =>+ OP.Mod OP.ArgumentFields (Path.AbsRel fd) -> OP.Parser (Path.AbsRel fd)+ pathArgument = OP.argument path++ pathOption ::+ PathC.FileDir fd =>+ OP.Mod OP.OptionFields (Path.AbsRel fd) -> OP.Parser (Path.AbsRel fd)+ pathOption = OP.option path++It performs minimal checking of path strings as part of option parsing.+E.g. it will report a user error if the user passes "abc/" as a file path.+++# File system links++This package does not explicitly handle file system links.+We treat a file path containing links like any other file path.+The same holds for directory paths.+A link is handled like any other path component.+++# Drive-relative paths on MS Windows++We use the `Rel` type for paths that can be relative to any directory.+We use the `Abs` type for all other paths,+i.e. for paths with explicit locations or+with restrictions on the set of locations.+Windows has a notion of drives and+maintains a current directory for every drive.+E.g. the path `"c:text.txt"` refers to the current directory of drive `C`.+Since it cannot be freely combined with other directories+we treat this path like an absolute path.+This is consistent with the behaviour of the `filepath` package.+E.g. `filepath` evaluates all of the expressions+`"\\abs" </> "c:driverel"`, `"c:\\abs" </> "c:driverel"`,+`"d:\\abs" </> "c:driverel"` to `"c:driverel"`.+In our package you would have to use `genericMakeAbsolute`+but we recommend to avoid its use.+++# Path format strings++You might allow a user to pass a format string such as+`"page%06d.png"` to your program.+How to integrate this into the type-safe path handling?+We recommend not to use the `Path` for the format string+but instead to define a custom type:++ newtype Format ar fd = Format String++ printf ::+ (PathC.AbsRel ar) =>+ Format ar fd -> Int -> Either String (Path ar fd)+ printf (Format fmt) n = Path.parse (Pf.printf fmt n)++This makes sure that you will access a path on disk+only after formatting the path string.+++# Known problems++## Mac++Currently we select the Posix module on Mac systems.+On the one hand this choice is right+since Mac uses slashes for path component separation.+On the other hand it is wrong+since Mac ignores case when comparing filepaths.
pathtype.cabal view
@@ -1,117 +1,100 @@+Cabal-Version: 2.2 Name: pathtype-Version: 0.5.5+Version: 0.8.1.4 Synopsis: Type-safe replacement for System.FilePath etc-Description: This package provides type-safe access to filepath manipulations.- .- "System.Path" is designed to be used instead of "System.FilePath".- (It is intended to provide versions of functions from that- module which have equivalent functionality but are more- typesafe). "System.Path.Directory" is a companion module- providing a type-safe alternative to "System.Directory".- .- The heart of this module is the @'Path' ar fd@ abstract type which- represents file and directory paths. The idea is that there are- two phantom type parameters - the first should be 'Abs' or 'Rel',- and the second 'File' or 'Dir'. A number of type synonyms are- provided for common types:- .- > type AbsFile = Path Abs File- > type RelFile = Path Rel File- > type AbsDir = Path Abs Dir- > type RelDir = Path Rel Dir- >- > type AbsPath fd = Path Abs fd- > type RelPath fd = Path Rel fd- > type FilePath ar = Path ar File- > type DirPath ar = Path ar Dir- .- The type of the 'combine' (aka '</>') function gives the idea:- .- > (</>) :: DirPath ar -> RelPath fd -> Path ar fd- .- Together this enables us to give more meaningful types to- a lot of the functions, and (hopefully) catch a bunch more- errors at compile time.- .- Overloaded string literals are supported, so with the @OverloadedStrings@- extension enabled, you can:- .- > f :: FilePath ar- > f = "tmp" </> "someFile" <.> "ext"- .- If you don't want to use @OverloadedStrings@, you can use the construction fns:- .- > f :: FilePath ar- > f = asDirPath "tmp" </> asFilePath "someFile" <.> "ext"- .- or...- .- > f :: FilePath ar- > f = asPath "tmp" </> asPath "someFile" <.> "ext"- .- or just...- .- > f :: FilePath ar- > f = asPath "tmp/someFile.ext"- .- One point to note is that whether one of these is interpreted as- an absolute or a relative path depends on the type at which it is- used:- .- > *System.Path> f :: AbsFile- > /tmp/someFile.ext- > *System.Path> f :: RelFile- > tmp/someFile.ext- .- You will typically want to import as follows:- .- > import Prelude hiding (FilePath)- > import System.Path- > import System.Path.Directory- > import System.Path.IO- .- The basic API (and properties satisfied) are heavily influenced- by Neil Mitchell's "System.FilePath" module.- .- .+Description:+ This package provides type-safe access to filepath manipulations.+ .+ "System.Path" is designed to be used instead of "System.FilePath".+ (It is intended to provide versions of functions from that+ module which have equivalent functionality but are more typesafe).+ "System.Path.Directory" is a companion module+ providing a type-safe alternative to "System.Directory".+ .+ The heart of this package is the @'Path' ar fd@ abstract type+ which represents file and directory paths.+ The idea is that there are two type parameters -+ the first should be 'Abs' or 'Rel', and the second 'File' or 'Dir'.+ A number of type synonyms are provided for common types:+ .+ > type Path.AbsFile = Path Abs File+ > type Path.RelFile = Path Rel File+ > type Path.AbsDir = Path Abs Dir+ > type Path.RelDir = Path Rel Dir+ >+ > type Path.Abs fd = Path Abs fd+ > type Path.Rel fd = Path Rel fd+ > type Path.File ar = Path ar File+ > type Path.Dir ar = Path ar Dir+ .+ The type of the 'combine' (aka '</>') function gives the idea:+ .+ > (</>) :: Path.Dir ar -> Path.Rel fd -> Path ar fd+ .+ Together this enables us to give more meaningful types+ to a lot of the functions,+ and (hopefully) catch a bunch more errors at compile time.+ .+ For more details see the README.md file.+ .+ Related packages:+ .+ * @filepath@: The API of Neil Mitchell's "System.FilePath" module+ (and properties satisfied) heavily influenced our package.+ .+ * @path@: Provides a wrapper type around 'FilePath'+ and maps to functions from @filepath@ package.+ This warrants consistency with @filepath@ functions.+ Requires Template Haskell.+ .+ * @data-filepath@:+ Requires 'Typeable' and Template Haskell.+ .+ * @hpath@:+ @ByteString@-based path type with type parameter+ for absolute and relative paths. Stability: experimental-License: BSD3+License: BSD-3-Clause Category: System License-file: LICENSE Author: Ben Moseley, Ben Millwood, Henning Thielemann-Maintainer: haskell@henning-thielemann.de, ben@moseley.name-HomePage: http://hub.darcs.net/thielema/pathtype/+Maintainer: haskell@henning-thielemann.de+HomePage: https://hub.darcs.net/thielema/pathtype/ Build-Type: Simple-Cabal-Version: >=1.8 Extra-Source-Files:- test/TestTemplate.hs- src/System/Path/Internal.hs+ README.md+ posix/System/Path/Host.hs+ windows/System/Path/Host.hs directory/pre-1.2/System/Path/ModificationTime.hs directory/post-incl-1.2/System/Path/ModificationTime.hs +Extra-Doc-Files:+ CHANGELOG+ Source-Repository head Type: darcs- Location: http://hub.darcs.net/thielema/pathtype/+ Location: https://hub.darcs.net/thielema/pathtype/ Source-Repository this- Tag: 0.5.5+ Tag: 0.8.1.4 Type: darcs- Location: http://hub.darcs.net/thielema/pathtype/+ Location: https://hub.darcs.net/thielema/pathtype/ Flag old-time Description: Build with directory < 1.2 and old-time- Default: True--Flag buildTools- Description: Build tool for updating test module- Default: True+ Default: False Library Build-Depends:- QuickCheck >= 2.1.0.1 && < 3,- deepseq >= 1.3 && <1.5,- time >= 1.0 && < 2,- base >= 4 && < 5+ utility-ht >=0.0.11 && <0.1,+ doctest-exitcode-stdio >=0.0 && <0.1,+ QuickCheck >=2.1.0.1 && <3,+ deepseq >=1.3 && <1.7,+ time >=1.0 && <2,+ transformers >=0.3 && <0.7,+ semigroups >=0.1 && <1,+ tagged >=0.7 && <0.9,+ base >=4.11 && <5 If flag(old-time) Build-Depends: directory >= 1 && < 1.2, old-time >= 1.0 && < 2@@ -121,37 +104,49 @@ Hs-Source-Dirs: directory/post-incl-1.2 Hs-Source-Dirs: src+ If os(windows)+ Hs-Source-Dirs: windows+ Else+ Hs-Source-Dirs: posix Exposed-Modules: System.Path+ System.Path.Generic System.Path.Directory System.Path.IO System.Path.Posix System.Path.Windows+ System.Path.Part+ System.Path.PartClass Other-Modules:+ System.Path.Host+ System.Path.Internal+ System.Path.Internal.Part+ System.Path.Internal.PartClass+ System.Path.Internal.Component+ System.Path.Internal.Separator+ System.Path.Internal.System+ System.Path.RegularExpression System.Path.ModificationTime - GHC-Options: -Wall -fwarn-tabs -fwarn-incomplete-record-updates -fwarn-unused-do-bind+ GHC-Options:+ -Wall -fwarn-tabs -fwarn-incomplete-record-updates -fwarn-unused-do-bind+ Default-Language: Haskell98 Test-Suite test Type: exitcode-stdio-1.0 Main-Is: Test.hs- Other-Modules: TestResult+ Other-Modules:+ Test.Posix.System.Path.Internal+ Test.Windows.System.Path.Internal Hs-Source-Dirs: test Build-Depends: pathtype,- random >=1.0 && <1.2,+ QuickCheck,+ doctest-exitcode-stdio,+ doctest-lib >=0.1 && <0.1.2, base - GHC-Options: -Wall -fwarn-tabs -fwarn-incomplete-record-updates -fwarn-unused-do-bind--Executable create-pathtype-test- If flag(buildTools)- Build-Depends:- base- Else- Buildable: True- Main-Is: CreateTest.hs- Hs-Source-Dirs: tool-- GHC-Options: -Wall -fwarn-tabs -fwarn-incomplete-record-updates -fwarn-unused-do-bind+ GHC-Options:+ -Wall -fwarn-tabs -fwarn-incomplete-record-updates -fwarn-unused-do-bind+ Default-Language: Haskell98
+ posix/System/Path/Host.hs view
@@ -0,0 +1,2 @@+module System.Path.Host (module System.Path.Posix) where+import System.Path.Posix
src/System/Path.hs view
@@ -1,86 +1,25 @@-{-# LANGUAGE CPP #-}--- | This module provides type-safe access to filepath manipulations.------ It is designed to be imported instead of "System.FilePath".--- (It is intended to provide versions of functions from that--- module which have equivalent functionality but are more--- typesafe). "System.Path.Directory" is a companion module--- providing a type-safe alternative to "System.Directory".------ The heart of this module is the @'Path' ar fd@ abstract type which--- represents file and directory paths. The idea is that there are--- two phantom type parameters - the first should be 'Abs' or 'Rel',--- and the second 'File' or 'Dir'. A number of type synonyms are--- provided for common types:------ > type AbsFile = Path Abs File--- > type RelFile = Path Rel File--- > type AbsDir = Path Abs Dir--- > type RelDir = Path Rel Dir--- >--- > type AbsPath fd = Path Abs fd--- > type RelPath fd = Path Rel fd--- > type FilePath ar = Path ar File--- > type DirPath ar = Path ar Dir------ The type of the 'combine' (aka '</>') function gives the idea:------ > (</>) :: DirPath ar -> RelPath fd -> Path ar fd------ Together this enables us to give more meaningful types to--- a lot of the functions, and (hopefully) catch a bunch more--- errors at compile time.------ Overloaded string literals are supported, so with the @OverloadedStrings@--- extension enabled, you can:------ > f :: FilePath ar--- > f = "tmp" </> "someFile" <.> "ext"------ If you don't want to use @OverloadedStrings@, you can use the construction fns:------ > f :: FilePath ar--- > f = asDirPath "tmp" </> asFilePath "someFile" <.> "ext"------ or...------ > f :: FilePath ar--- > f = asPath "tmp" </> asPath "someFile" <.> "ext"------ or just...------ > f :: FilePath ar--- > f = asPath "tmp/someFile.ext"------ One point to note is that whether one of these is interpreted as--- an absolute or a relative path depends on the type at which it is--- used:------ > *System.Path> f :: AbsFile--- > /tmp/someFile.ext--- > *System.Path> f :: RelFile--- > tmp/someFile.ext------ You will typically want to import as follows:------ > import Prelude hiding (FilePath)--- > import System.Path--- > import System.Path.Directory--- > import System.Path.IO------ The basic API (and properties satisfied) are heavily influenced--- by Neil Mitchell's "System.FilePath" module.--------- Ben Moseley - (c) 2009-2010-----#if defined(mingw32_HOST_OS) || defined(__MINGW32__)-module System.Path(module System.Path.Windows) where-import System.Path.Windows-#else-module System.Path(module System.Path.Posix) where-import System.Path.Posix-#endif-+module System.Path (+ module System.Path.Host,+ module System.Path.Generic,+ ) where +import System.Path.Host+import System.Path.Generic hiding (+ System, Path,+ AbsFile, RelFile, AbsDir, RelDir,+ Abs, Rel, File, Dir,+ AbsRelFile, AbsRelDir, AbsFileDir, RelFileDir,+ AbsRel, FileDir, AbsRelFileDir,+ AbsPath, RelPath, FilePath, DirPath,+ AbsRelPath, FileDirPath,+ asPath,+ asRelFile, asRelDir, asAbsFile, asAbsDir,+ asRelPath, asAbsPath, asFilePath, asDirPath,+ isAbsoluteString, isRelativeString, equalFilePath,+ path, maybe, maybePath, parse, parsePath,+ relFile, relDir, absFile, absDir,+ abs, rel, absRel, file, dir, fileDir,+ relPath, absPath, filePath, dirPath,+ rootDir, currentDir, emptyFile,+ toString,+ )
src/System/Path/Directory.hs view
@@ -8,14 +8,9 @@ -- -- You will typically want to import as follows: ----- > import Prelude hiding (FilePath)--- > import System.Path--- > import System.Path.Directory--- > import System.Path.IO--------- Ben Moseley - (c) 2009---+-- > import qualified System.Path.IO as PathIO+-- > import qualified System.Path as Path+-- > import System.Path.Directory (createDirectory) module System.Path.Directory ( -- * Actions on directories@@ -58,12 +53,19 @@ setPermissions, -- * Timestamps- getModificationTime+ getModificationTime, ) where -import System.Path+import qualified System.Path.Internal.PartClass as Class+import qualified System.Path as Path+import System.Path (+ Path, path,+ AbsPath, AbsDir, AbsFile, RelPath, RelDir, RelFile,+ DirPath, FilePath, absDir, (</>),+ )+ import System.Path.ModificationTime (convertTime) import Data.Time (UTCTime) @@ -73,6 +75,7 @@ import Control.Applicative ((<$>)) import Data.List (partition)+import Data.Tuple.HT (mapPair) import Prelude hiding (FilePath) @@ -80,32 +83,37 @@ ------------------------------------------------------------------------ -- Actions on directories -createDirectory :: AbsRelClass ar => DirPath ar -> IO ()-createDirectory = SD.createDirectory . getPathString+createDirectory :: Class.AbsRel ar => DirPath ar -> IO ()+createDirectory = SD.createDirectory . Path.toString -createDirectoryIfMissing :: AbsRelClass ar => Bool -> DirPath ar -> IO ()-createDirectoryIfMissing flag = SD.createDirectoryIfMissing flag . getPathString+createDirectoryIfMissing :: Class.AbsRel ar => Bool -> DirPath ar -> IO ()+createDirectoryIfMissing flag = SD.createDirectoryIfMissing flag . Path.toString -removeDirectory :: AbsRelClass ar => DirPath ar -> IO ()-removeDirectory = SD.removeDirectory . getPathString+removeDirectory :: Class.AbsRel ar => DirPath ar -> IO ()+removeDirectory = SD.removeDirectory . Path.toString -removeDirectoryRecursive :: AbsRelClass ar => DirPath ar -> IO ()-removeDirectoryRecursive = SD.removeDirectoryRecursive . getPathString+removeDirectoryRecursive :: Class.AbsRel ar => DirPath ar -> IO ()+removeDirectoryRecursive = SD.removeDirectoryRecursive . Path.toString -renameDirectory :: (AbsRelClass ar1, AbsRelClass ar2) => DirPath ar1 -> DirPath ar2 -> IO ()-renameDirectory p1 p2 = SD.renameDirectory (getPathString p1) (getPathString p2)+renameDirectory ::+ (Class.AbsRel ar1, Class.AbsRel ar2) => DirPath ar1 -> DirPath ar2 -> IO ()+renameDirectory p1 p2 =+ SD.renameDirectory (Path.toString p1) (Path.toString p2) --- | An alias for 'relDirectoryContents'.-getDirectoryContents :: AbsRelClass ar => DirPath ar -> IO ([RelDir], [RelFile])-getDirectoryContents = relDirectoryContents+-- | Retrieve the contents of a directory without any directory prefixes.+-- In contrast to 'System.Directory.getDirectoryContents',+-- exclude special directories \".\" and \"..\".+getDirectoryContents :: Class.AbsRel ar => DirPath ar -> IO [Path.RelFileDir]+getDirectoryContents dir =+ map Path.path <$> plainDirectoryContents dir -- | Retrieve the contents of a directory path (which may be relative) as absolute paths-absDirectoryContents :: AbsRelClass ar => DirPath ar -> IO ([AbsDir], [AbsFile])+absDirectoryContents ::+ Class.AbsRel ar => DirPath ar -> IO ([AbsDir], [AbsFile]) absDirectoryContents p = do- cd <- asAbsDir <$> SD.getCurrentDirectory- let dir = absRel id (cd </>) p- (rds, rfs) <- relDirectoryContents dir- return (map (dir </>) rds, map (dir </>) rfs)+ cd <- absDir <$> SD.getCurrentDirectory+ let dir = Path.withAbsRel id (cd </>) p+ mapPair (map (dir </>), map (dir </>)) <$> relDirectoryContents dir -- | Returns paths relative /to/ the supplied (abs or relative) directory path. -- eg (for current working directory of @\/somewhere\/cwd\/@):@@ -113,91 +121,105 @@ -- > show (relDirectoryContents "d/e/f/") == (["subDir1A","subDir1B"], -- > ["file1A","file1B"]) ---relDirectoryContents :: AbsRelClass ar => DirPath ar -> IO ([RelDir], [RelFile])+relDirectoryContents ::+ Class.AbsRel ar => DirPath ar -> IO ([RelDir], [RelFile]) relDirectoryContents dir = do- filenames <- filter (not . flip elem [".",".."]) <$> SD.getDirectoryContents (getPathString dir)- dirFlags <- mapM (doesDirectoryExist . (dir </>) . asRelPath) filenames- let fileinfo = zip filenames dirFlags- (dirs, files) = partition snd fileinfo- return (map (combine currentDir . asRelDir . fst) dirs,- map (combine currentDir . asRelFile . fst) files)+ filenames <- plainDirectoryContents dir+ mapPair (map (Path.relDir . fst), map (Path.relFile . fst)) .+ partition snd . zip filenames+ <$> mapM (doesDirectoryExist . (dir </>) . Path.relPath) filenames +plainDirectoryContents :: Class.AbsRel ar => DirPath ar -> IO [String]+plainDirectoryContents dir =+ filter (not . flip elem [".",".."]) <$>+ SD.getDirectoryContents (Path.toString dir)+ -- | A convenient alternative to 'relDirectoryContents' if you only want files.-filesInDir :: AbsRelClass ar => DirPath ar -> IO [RelFile]+filesInDir :: Class.AbsRel ar => DirPath ar -> IO [RelFile] filesInDir dir = snd <$> relDirectoryContents dir -- | A convenient alternative to 'relDirectoryContents' if you only want directories.-dirsInDir :: AbsRelClass ar => DirPath ar -> IO [RelDir]+dirsInDir :: Class.AbsRel ar => DirPath ar -> IO [RelDir] dirsInDir dir = fst <$> relDirectoryContents dir getCurrentDirectory :: IO AbsDir-getCurrentDirectory = asAbsDir <$> SD.getCurrentDirectory+getCurrentDirectory = absDir <$> SD.getCurrentDirectory -setCurrentDirectory :: AbsRelClass ar => DirPath ar -> IO ()-setCurrentDirectory = SD.setCurrentDirectory . getPathString+setCurrentDirectory :: Class.AbsRel ar => DirPath ar -> IO ()+setCurrentDirectory = SD.setCurrentDirectory . Path.toString ------------------------------------------------------------------------ -- Pre-defined directories getHomeDirectory :: IO AbsDir-getHomeDirectory = asAbsDir <$> SD.getHomeDirectory+getHomeDirectory = absDir <$> SD.getHomeDirectory getAppUserDataDirectory :: String -> IO AbsDir-getAppUserDataDirectory user = asAbsDir <$> SD.getAppUserDataDirectory user+getAppUserDataDirectory user = absDir <$> SD.getAppUserDataDirectory user getUserDocumentsDirectory :: IO AbsDir-getUserDocumentsDirectory = asAbsDir <$> SD.getUserDocumentsDirectory+getUserDocumentsDirectory = absDir <$> SD.getUserDocumentsDirectory getTemporaryDirectory :: IO AbsDir-getTemporaryDirectory = asAbsDir <$> SD.getTemporaryDirectory+getTemporaryDirectory = absDir <$> SD.getTemporaryDirectory ------------------------------------------------------------------------ -- Actions on files -removeFile :: AbsRelClass ar => FilePath ar -> IO ()-removeFile = SD.removeFile . getPathString+removeFile :: Class.AbsRel ar => FilePath ar -> IO ()+removeFile = SD.removeFile . Path.toString -renameFile :: (AbsRelClass ar1, AbsRelClass ar2) => FilePath ar1 -> FilePath ar2 -> IO ()-renameFile p1 p2 = SD.renameFile (getPathString p1) (getPathString p2)+renameFile ::+ (Class.AbsRel ar1, Class.AbsRel ar2) =>+ FilePath ar1 -> FilePath ar2 -> IO ()+renameFile p1 p2 = SD.renameFile (Path.toString p1) (Path.toString p2) -copyFile :: (AbsRelClass ar1, AbsRelClass ar2) => FilePath ar1 -> FilePath ar2 -> IO ()-copyFile p1 p2 = SD.copyFile (getPathString p1) (getPathString p2)+copyFile ::+ (Class.AbsRel ar1, Class.AbsRel ar2) =>+ FilePath ar1 -> FilePath ar2 -> IO ()+copyFile p1 p2 = SD.copyFile (Path.toString p1) (Path.toString p2) -canonicalizePath :: AbsRelClass ar => Path ar fd -> IO (AbsPath fd)-canonicalizePath p = asPath <$> SD.canonicalizePath (getPathString p)+canonicalizePath ::+ (Class.AbsRel ar, Class.FileDir fd) => Path ar fd -> IO (AbsPath fd)+canonicalizePath p = path <$> SD.canonicalizePath (Path.toString p) -makeRelativeToCurrentDirectory :: AbsRelClass ar => Path ar fd -> IO (RelPath fd)-makeRelativeToCurrentDirectory p = asPath <$> SD.makeRelativeToCurrentDirectory (getPathString p)+makeRelativeToCurrentDirectory ::+ (Class.AbsRel ar, Class.FileDir fd) => Path ar fd -> IO (RelPath fd)+makeRelativeToCurrentDirectory p =+ path <$> SD.makeRelativeToCurrentDirectory (Path.toString p) findExecutable :: String -> IO (Maybe AbsFile)-findExecutable s = fmap asPath <$> SD.findExecutable s+findExecutable s = fmap path <$> SD.findExecutable s ------------------------------------------------------------------------ -- Existence tests -doesFileExist :: AbsRelClass ar => FilePath ar -> IO Bool-doesFileExist = SD.doesFileExist . getPathString+doesFileExist :: Class.AbsRel ar => FilePath ar -> IO Bool+doesFileExist = SD.doesFileExist . Path.toString -doesDirectoryExist :: AbsRelClass ar => DirPath ar -> IO Bool-doesDirectoryExist = SD.doesDirectoryExist . getPathString+doesDirectoryExist :: Class.AbsRel ar => DirPath ar -> IO Bool+doesDirectoryExist = SD.doesDirectoryExist . Path.toString ------------------------------------------------------------------------ -- Permissions -getPermissions :: AbsRelClass ar => Path ar fd -> IO Permissions-getPermissions p = SD.getPermissions (getPathString p)+getPermissions ::+ (Class.AbsRel ar, Class.FileDir fd) => Path ar fd -> IO Permissions+getPermissions p = SD.getPermissions (Path.toString p) -setPermissions :: AbsRelClass ar => Path ar fd -> Permissions -> IO ()-setPermissions p perms = SD.setPermissions (getPathString p) perms+setPermissions ::+ (Class.AbsRel ar, Class.FileDir fd) => Path ar fd -> Permissions -> IO ()+setPermissions p perms = SD.setPermissions (Path.toString p) perms ------------------------------------------------------------------------ -- Timestamps -getModificationTime :: AbsRelClass ar => Path ar fd -> IO UTCTime-getModificationTime p = convertTime <$> SD.getModificationTime (getPathString p)+getModificationTime ::+ (Class.AbsRel ar, Class.FileDir fd) => Path ar fd -> IO UTCTime+getModificationTime p = convertTime <$> SD.getModificationTime (Path.toString p)
+ src/System/Path/Generic.hs view
@@ -0,0 +1,22 @@+{- |+This module provides type-safe access to filepath manipulations+independent from the operating system.++Normally you would import 'System.Path'+since this contains types fixed to your host system+and otherwise generic functions.+However, importing this explicitly+allows for manipulation of non-native paths.+-}+module System.Path.Generic (+ module System.Path.Internal,+ Core.System,+ ) where++import qualified System.Path.Internal as Core+import System.Path.Internal hiding (+ System(..),+ extSeparator, isExtSeparator,+ searchPathSeparator, isSearchPathSeparator,+ testAll,+ )
src/System/Path/IO.hs view
@@ -9,9 +9,9 @@ -- You will typically want to import as follows: -- -- > import Prelude hiding (FilePath)--- > import System.Path--- > import System.Path.Directory--- > import System.Path.IO+-- > import qualified System.Path as Path+-- > import qualified System.Path.Directory as Dir+-- > import qualified System.Path.IO as PIO -- -- -- Ben Moseley - (c) 2009@@ -85,18 +85,20 @@ SIO.hPutBuf, SIO.hGetBuf, SIO.hPutBufNonBlocking,- SIO.hGetBufNonBlocking+ SIO.hGetBufNonBlocking, ) where -import System.Path+import qualified System.Path.Internal.PartClass as Class+import qualified System.Path as Path+import System.Path (DirPath, FilePath, AbsFile, RelFile) import qualified System.IO as SIO import System.IO (IOMode, Handle) -import Control.Arrow (first) import Control.Applicative ((<$>))+import Data.Tuple.HT (mapFst) import Prelude hiding (FilePath, readFile, writeFile, appendFile) @@ -104,29 +106,37 @@ ------------------------------------------------------------------------ -- Covers for System.IO functions -withFile :: AbsRelClass ar => FilePath ar -> IOMode -> (Handle -> IO r) -> IO r-withFile f = SIO.withFile (getPathString f)+withFile ::+ Class.AbsRel ar => FilePath ar -> IOMode -> (Handle -> IO r) -> IO r+withFile f = SIO.withFile (Path.toString f) -openFile :: AbsRelClass ar => FilePath ar -> IOMode -> IO Handle-openFile f = SIO.openFile (getPathString f)+openFile :: Class.AbsRel ar => FilePath ar -> IOMode -> IO Handle+openFile f = SIO.openFile (Path.toString f) -readFile :: AbsRelClass ar => FilePath ar -> IO String-readFile f = SIO.readFile (getPathString f)+readFile :: Class.AbsRel ar => FilePath ar -> IO String+readFile f = SIO.readFile (Path.toString f) -writeFile :: AbsRelClass ar => FilePath ar -> String -> IO ()-writeFile f = SIO.writeFile (getPathString f)+writeFile :: Class.AbsRel ar => FilePath ar -> String -> IO ()+writeFile f = SIO.writeFile (Path.toString f) -appendFile :: AbsRelClass ar => FilePath ar -> String -> IO ()-appendFile f = SIO.appendFile (getPathString f)+appendFile :: Class.AbsRel ar => FilePath ar -> String -> IO ()+appendFile f = SIO.appendFile (Path.toString f) -withBinaryFile :: AbsRelClass ar => FilePath ar -> IOMode -> (Handle -> IO r) -> IO r-withBinaryFile f = SIO.withBinaryFile (getPathString f)+withBinaryFile ::+ Class.AbsRel ar => FilePath ar -> IOMode -> (Handle -> IO r) -> IO r+withBinaryFile f = SIO.withBinaryFile (Path.toString f) -openBinaryFile :: AbsRelClass ar => FilePath ar -> IOMode -> IO Handle-openBinaryFile f = SIO.openBinaryFile (getPathString f)+openBinaryFile :: Class.AbsRel ar => FilePath ar -> IOMode -> IO Handle+openBinaryFile f = SIO.openBinaryFile (Path.toString f) -openTempFile :: AbsRelClass ar => DirPath ar -> RelFile -> IO (AbsFile, Handle)-openTempFile f template = first asAbsFile <$> SIO.openTempFile (getPathString f) (getPathString template)+openTempFile ::+ Class.AbsRel ar => DirPath ar -> RelFile -> IO (AbsFile, Handle)+openTempFile f template =+ mapFst Path.absFile <$>+ SIO.openTempFile (Path.toString f) (Path.toString template) -openBinaryTempFile :: AbsRelClass ar => DirPath ar -> RelFile -> IO (AbsFile, Handle)-openBinaryTempFile f template = first asAbsFile <$> SIO.openBinaryTempFile (getPathString f) (getPathString template)+openBinaryTempFile ::+ Class.AbsRel ar => DirPath ar -> RelFile -> IO (AbsFile, Handle)+openBinaryTempFile f template =+ mapFst Path.absFile <$>+ SIO.openBinaryTempFile (Path.toString f) (Path.toString template)
src/System/Path/Internal.hs view
@@ -1,958 +1,1705 @@---- LANGUAGE pragmas need to go in System.Path.[Windows|Posix]-module System.Path.MODULE_NAME-(- -- * The main filepath (& dirpath) abstract type- Path, -- kept abstract-- -- * Phantom Types- Abs,- Rel,- File,- Dir,-- -- * Type Synonyms- AbsFile,- RelFile,- AbsDir,- RelDir,- AbsPath,- RelPath,- FilePath,- DirPath,-- -- * Classes- AbsRelClass(..),- FileDirClass(..),-- -- * Path to String conversion- getPathString,-- -- * Constants- rootDir,- currentDir,-- -- * Unchecked Construction Functions- asPath,- asRelFile,- asRelDir,- asAbsFile,- asAbsDir,- asRelPath,- asAbsPath,- asFilePath,- asDirPath,-- -- * Checked Construction Functions- mkPathAbsOrRel,- mkPathFileOrDir,- mkAbsPath,- mkAbsPathFromCwd,-- -- * Basic Manipulation Functions- (</>),- (<.>),- addExtension,- combine,- dropExtension,- dropExtensions,- dropFileName,- replaceExtension,- replaceBaseName,- replaceDirectory,- replaceFileName,- splitExtension,- splitExtensions,- splitFileName,- takeBaseName,- takeDirectory,- takeExtension,- takeExtensions,- takeFileName,-- -- * Auxillary Manipulation Functions- equalFilePath,- joinPath,- normalise,- splitPath,- makeRelative,- makeAbsolute,- makeAbsoluteFromCwd,- genericMakeAbsolute,- genericMakeAbsoluteFromCwd,- pathMap,-- -- * Path Predicates- isAbsolute,- isAbsoluteString,- isRelative,- isRelativeString,- hasAnExtension,- hasExtension,-- -- * Separators- addTrailingPathSeparator,- dropTrailingPathSeparator,- extSeparator,- hasTrailingPathSeparator,- pathSeparator,- pathSeparators,- searchPathSeparator,- isExtSeparator,- isPathSeparator,- isSearchPathSeparator,-- -- * Generic Manipulation Functions- genericAddExtension,- genericDropExtension,- genericDropExtensions,- genericSplitExtension,- genericSplitExtensions,- genericTakeExtension,- genericTakeExtensions-)--where--import qualified System.Directory as SD--import Control.Arrow (first, (|||), (***))-import Control.Applicative ((<$>))-import Control.DeepSeq (NFData(rnf))-import Data.List (isSuffixOf, isPrefixOf, stripPrefix, intercalate)-import Data.String (IsString(fromString))-import Data.Char (isSpace)--import Text.Printf (printf)--import qualified Test.QuickCheck as QC-import Test.QuickCheck- (Gen, Property, property, Arbitrary(arbitrary),- oneof, frequency, quickCheck)--import Prelude hiding (FilePath)------------------------------------------------------------------------------ Types--data Abs-data Rel-data File-data Dir---- | This is the main filepath abstract datatype-data Path ar fd = PathRoot -- ^ Invariant - this should always have type :: DirPath ar- | FileDir !(DirPath ar) !PathComponent -- The fact that we recurse binding fd to Dir- -- makes this a "nested datatype"- deriving (Eq, Ord)---- Possible GADT version...------ data Path ar fd where--- AbsRoot :: Path Abs Dir--- RelRoot :: Path Rel Dir--- File :: Path ar Dir -> PathComponent -> Path ar File--- Dir :: Path ar Dir -> PathComponent -> Path ar Dir------ ... doesn't presently seem to add much value over non-GADT.--newtype PathComponent = PathComponent String deriving (Eq,Ord)--type AbsFile = Path Abs File-type RelFile = Path Rel File-type AbsDir = Path Abs Dir-type RelDir = Path Rel Dir--type AbsPath fd = Path Abs fd-type RelPath fd = Path Rel fd-type FilePath ar = Path ar File-type DirPath ar = Path ar Dir--instance NFData PathComponent where- rnf (PathComponent pc) = rnf pc--instance NFData (Path ar fd) where- rnf PathRoot = ()- rnf (FileDir d pc) = rnf (d, pc)---- I don't think this basic type of fold is appropriate for a nested datatype--- pathFold :: a -> (a -> String -> a) -> Path ar fd -> a--- pathFold pr f PathRoot = pr--- pathFold pr f (FileDir d pc) = f (pathFold pr f d) (unPathComponent pc)---- | Map over the components of the path.------ >> pathMap (map toLower) "/tmp/Reports/SpreadSheets" == "/tmp/reports/spreadsheets"-pathMap :: (String -> String) -> Path ar fd -> Path ar fd-pathMap _ PathRoot = PathRoot-pathMap f (FileDir d pc) = FileDir (pathMap f d) (pcMap f pc)---- Private fn-pcMap :: (String -> String) -> PathComponent -> PathComponent-pcMap f (PathComponent s) = PathComponent (f s)------------------------------------------------------------------------------ Type classes and machinery for switching on Abs/Rel and File/Dir---- | This class provides a way to prevent other modules--- from making further 'AbsRelClass' or 'FileDirClass'--- instances-class Private p-instance Private Abs-instance Private Rel-instance Private File-instance Private Dir---- | This class allows selective behaviour for absolute and--- relative paths and is mostly for internal use.-class Private ar => AbsRelClass ar where- -- | See <https://wiki.haskell.org/Closed_world_instances>- -- for the used technique.- switchAbsRel :: f Abs -> f Rel -> f ar- -- | Will become a top-level function in future- absRel :: (AbsPath fd -> a) -> (RelPath fd -> a) -> Path ar fd -> a- absRel f g = runAbsRel $ switchAbsRel (AbsRel f) (AbsRel g)--newtype AbsRel fd a ar = AbsRel {runAbsRel :: Path ar fd -> a}--instance AbsRelClass Abs where switchAbsRel f _g = f-instance AbsRelClass Rel where switchAbsRel _f g = g---- | This class allows selective behaviour for file and--- directory paths and is mostly for internal use.-class Private fd => FileDirClass fd where- switchFileDir :: f File -> f Dir -> f fd- -- | Will become a top-level function in future- fileDir :: (FilePath ar -> a) -> (DirPath ar -> a) -> Path ar fd -> a- fileDir f g = runFileDir $ switchFileDir (FileDirFunc f) (FileDirFunc g)--newtype FileDir ar a fd = FileDirFunc {runFileDir :: Path ar fd -> a}--instance FileDirClass File where switchFileDir f _g = f-instance FileDirClass Dir where switchFileDir _f g = g----- | Currently not exported-_pathAbsRel :: AbsRelClass ar => Path ar fd -> Either (AbsPath fd) (RelPath fd)-_pathAbsRel = absRel Left Right---- | Currently not exported-_pathFileDir :: FileDirClass fd => Path ar fd -> Either (FilePath ar) (DirPath ar)-_pathFileDir = fileDir Left Right----------------------------------------------------------------------------- Read & Show instances---- >> show (rootDir </> "bla" </> "blub") == "rootDir </> \"bla\" </> \"blub\""--- >> show (Just (rootDir </> "bla" </> "blub")) == "Just (rootDir </> \"bla\" </> \"blub\")"--- >> show (currentDir </> "bla" </> "blub") == "currentDir </> \"bla\" </> \"blub\""--- >> show (Just (currentDir </> "bla" </> "blub")) == "Just (currentDir </> \"bla\" </> \"blub\")"-instance AbsRelClass ar => Show (Path ar fd) where- showsPrec d =- let go :: AbsRelClass ar => Path ar fd -> ShowS- go x@PathRoot =- absRel (const $ showString rootName) (const $ showString currentName) x- go (FileDir p (PathComponent pc)) =- go p . showChar ' ' .- showString combineOperator . showChar ' ' . shows pc- in showParen (d>9) . go---- >> read (show (rootDir </> "bla" </> "blub")) == rootDir </> "bla" </> "blub"--- >> read (show (Just (rootDir </> "bla" </> "blub"))) == Just (rootDir </> "bla" </> "blub")--- >> read (show (currentDir </> "bla" </> "blub")) == currentDir </> "bla" </> "blub"--- >> read (show (Just (currentDir </> "bla" </> "blub"))) == Just (currentDir </> "bla" </> "blub")-instance AbsRelClass ar => Read (Path ar fd) where- readsPrec d = readParen (d>9) $ \str ->- let go :: AbsRelClass ar => Path ar Dir -> ReadS (Path ar fd)- go path s0 =- case stripPrefix combineOperator $ dropWhile isSpace s0 of- Nothing -> [(relaxDir path, s0)]- Just s1 -> do- (pc, s2) <- reads s1- go (FileDir path (PathComponent pc)) s2- result = do- let required = absRel (const rootName) (const currentName) $ fst $ head result- maybe [] (go PathRoot) $- stripPrefix required $ dropWhile isSpace str- in result--relaxDir :: Path ar Dir -> Path ar fd-relaxDir PathRoot = PathRoot-relaxDir (FileDir p pc) = FileDir p pc---- | Convert the 'Path' into a plain 'String' as required for OS calls.-getPathString :: AbsRelClass ar => Path ar fd -> String-getPathString = flip getPathStringS ""--getPathStringS :: AbsRelClass ar => Path ar fd -> ShowS-getPathStringS =- let go :: AbsRelClass ar => Path ar fd -> ShowS- go x@PathRoot =- absRel- (const $ showChar pathSeparator)- (const $ showString currentDirComponent) x- -- we need the clause below so that we don't duplicate the pathSeparator after an abs- -- root and we don't want to display a "./" prefix on relative paths- go (FileDir p@PathRoot (PathComponent pc)) =- absRel (const $ showChar pathSeparator) (const id) p .- showString pc- go (FileDir p (PathComponent pc)) =- go p . showChar pathSeparator . showString pc- in go--prop_asPath_getPathString :: AbsFile -> Property-prop_asPath_getPathString p = property $ p == asPath (getPathString p)------------------------------------------------------------------------------ Windows / Posix--_isPosix :: Bool-_isPosix = not isWindows--isWindows :: Bool-isWindows = IS_WINDOWS----------------------------------------------------------------------------- Constants--rootDir :: AbsDir-rootDir = PathRoot--currentDir :: RelDir-currentDir = PathRoot--rootName :: String-rootName = "rootDir"--currentName :: String-currentName = "currentDir"--currentDirComponent :: String-currentDirComponent = "."------------------------------------------------------------------------------ Unchecked Construction Functions--- NB - these construction functions are non-IO and do no checking!!---- | 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"-asPath :: String -> Path ar fd-asPath = mkPathFromComponents . mkPathComponents---- | 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"-asRelFile :: String -> RelFile-asRelFile = asPath---- | Use a 'String' as a 'RelDir'. No checking is done.------ >> getPathString (asRelDir ".") == "."--- >> getPathString (asRelDir "file.txt") == "file.txt"--- >> getPathString (asRelDir "/file.txt") == "file.txt"--- >> getPathString (asRelDir "tmp") == "tmp"--- >> getPathString (asRelDir "/tmp") == "tmp"-asRelDir :: String -> RelDir-asRelDir = asPath---- | 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"-asAbsFile :: String -> AbsFile-asAbsFile = asPath---- | 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"-asAbsDir :: String -> AbsDir-asAbsDir = asPath---- | Use a 'String' as a 'RelPath fd'. No checking is done.-asRelPath :: String -> RelPath fd-asRelPath = asPath---- | Use a 'String' as an 'AbsPath fd'. No checking is done.-asAbsPath :: String -> AbsPath fd-asAbsPath = asPath---- | Use a 'String' as a 'FilePath ar'. No checking is done.-asFilePath :: String -> FilePath ar-asFilePath = asPath---- | Use a 'String' as a 'DirPath ar'. No checking is done.-asDirPath :: String -> DirPath ar-asDirPath = asPath---- | Allow use of OverloadedStrings if desired-instance IsString (Path ar fd) where fromString = asPath----------------------------------------------------------------------------- Checked Construction Functions---- | Examines the supplied string and constructs an absolute or--- relative path as appropriate.------ >> mkPathAbsOrRel "/tmp" == Left (asAbsDir "/tmp")--- >> mkPathAbsOrRel "tmp" == Right (asRelDir "tmp")-mkPathAbsOrRel :: String -> Either (AbsPath fd) (RelPath fd)-mkPathAbsOrRel s =- if isAbsoluteString s- then Left $ asAbsPath s- else Right $ asRelPath s---- | 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.-mkPathFileOrDir ::- AbsRelClass ar => String -> IO (Maybe (Either (FilePath ar) (DirPath ar)))-mkPathFileOrDir s = do- isfile <- SD.doesFileExist s- isdir <- SD.doesDirectoryExist s- case (isfile, isdir) of- (False, False) -> return Nothing- (True, False) -> return $ Just $ Left $ asPath s- (False, True ) -> return $ Just $ Right $ asPath s- (True, True ) -> ioError $ userError "mkPathFileOrDir - object type changed while checking"---- | 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"-mkAbsPath :: AbsDir -> String -> AbsPath fd-mkAbsPath d = (id ||| makeAbsolute d) . mkPathAbsOrRel---- | Convert a 'String' into an 'AbsPath' by interpreting it as--- relative to the cwd if necessary.-mkAbsPathFromCwd :: String -> IO (AbsPath fd)-mkAbsPathFromCwd = (return ||| makeAbsoluteFromCwd) . mkPathAbsOrRel------------------------------------------------------------------------------ Internal Functions for PathComponent manipulation--mkPathFromComponents :: [PathComponent] -> Path ar fd-mkPathFromComponents pcs =- case reverse pcs of- [] -> PathRoot- p:ps -> FileDir (foldr (flip FileDir) PathRoot ps) p--mkPathComponents :: String -> [PathComponent]-mkPathComponents xs =- case break isPathSeparator (dropWhile isPathSeparator xs) of- ("","") -> []- (s,rest) -> PathComponent s : mkPathComponents rest--pathComponents :: Path ar fd -> [PathComponent]-pathComponents PathRoot = []-pathComponents (FileDir p pc) = pathComponents p ++ [pc]--prop_mkPathFromComponents_pathComponents :: AbsFile -> Property-prop_mkPathFromComponents_pathComponents p =- property $ mkPathFromComponents (pathComponents p) == p------------------------------------------------------------------------------- Basic Manipulation Functions--combineOperator :: String-combineOperator = "</>"---- | Infix variant of 'combine'.-(</>) :: DirPath ar -> RelPath fd -> Path ar fd-PathRoot </> PathRoot = PathRoot-(FileDir dp dpc) </> PathRoot = FileDir dp dpc-d </> (FileDir p pc) = FileDir (d </> p) pc---- | Infix variant of 'addExtension'.--- 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'.-(<.>) :: FilePath ar -> String -> FilePath ar-(<.>) = genericAddExtension---- | 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"--- >> addExtension "" "bib" == ".bib"--- >> addExtension "" ".bib" == ".bib"--- >> takeFileName (addExtension "" "ext") == ".ext"-addExtension :: FilePath ar -> String -> FilePath ar-addExtension = (<.>)---- | Join an (absolute or relative) directory path with a relative--- (file or directory) path to form a new path.-combine :: DirPath ar -> RelPath fd -> Path ar fd-combine = (</>)----- | Remove last extension, and the \".\" preceding it.------ >> dropExtension x == fst (splitExtension x)-dropExtension :: FilePath ar -> FilePath ar-dropExtension = fst . splitExtension---- | Drop all extensions------ >> not $ hasAnExtension (dropExtensions x)-dropExtensions :: FilePath ar -> FilePath ar-dropExtensions = fst . splitExtensions---- | Synonym for 'takeDirectory'-dropFileName :: Path ar fd -> DirPath ar-dropFileName = fst . splitFileName----- | 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"-replaceExtension :: FilePath ar -> String -> FilePath ar-replaceExtension p ext = dropExtension p <.> ext--replaceBaseName :: Path ar fd -> String -> Path ar fd-replaceBaseName p bn = takeDirectory p </> (asPath bn `genericAddExtension` genericTakeExtension p)--replaceDirectory :: Path ar1 fd -> DirPath ar2 -> Path ar2 fd-replaceDirectory p d = d </> takeFileName p--replaceFileName :: Path ar fd -> String -> Path ar fd-replaceFileName p fn = takeDirectory p </> asPath fn----- | 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")-splitExtension :: FilePath ar -> (FilePath ar, String)-splitExtension = genericSplitExtension---- | Split on all extensions------ >> splitExtensions "file.tar.gz" == ("file",".tar.gz")-splitExtensions :: FilePath ar -> (FilePath ar, String)-splitExtensions = genericSplitExtensions--prop_split_combineExt :: AbsFile -> Property-prop_split_combineExt p = property $ p == uncurry (<.>) (splitExtension p)---- | Path must not be empty-splitFileName :: Path ar fd -> (DirPath ar, RelPath fd)-splitFileName (FileDir p pc) = (p, mkPathFromComponents [pc])-splitFileName PathRoot = error "splitFileName: empty path"--prop_split_combine :: AbsFile -> Property-prop_split_combine p = property $ uncurry combine (splitFileName p) == p----- | Get the basename of a file------ >> takeBaseName "/tmp/somedir/myfile.txt" == "myfile"--- >> takeBaseName "./myfile.txt" == "myfile"--- >> takeBaseName "myfile.txt" == "myfile"-takeBaseName :: Path ar fd -> RelPath fd-takeBaseName = takeFileName . genericDropExtension--takeDirectory :: Path ar fd -> DirPath ar-takeDirectory = fst . splitFileName---- | 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"-takeExtension :: FilePath ar -> String-takeExtension = snd . splitExtension---- | Get all extensions------ >> takeExtensions "file.tar.gz" == ".tar.gz"-takeExtensions :: FilePath ar -> String-takeExtensions = snd . splitExtensions---- | 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"-takeFileName :: Path ar fd -> RelPath fd-takeFileName PathRoot = PathRoot -- becomes a relative root-takeFileName (FileDir _ pc) = FileDir PathRoot pc--prop_takeFileName_end :: AbsFile -> Property-prop_takeFileName_end p = property $ show (takeFileName p) `isSuffixOf` show p------------------------------------------------------------------------------ Auxillary Manipulation Functions---- | Check whether two strings are equal as file paths.------ >> equalFilePath "/tmp/" "/tmp" == True--- >> equalFilePath "/tmp" "tmp" == False-equalFilePath :: String -> String -> Bool-equalFilePath s1 s2 =- isAbsoluteString s1 == isAbsoluteString s2 && asPath s1 == asPath s2---- | Constructs a 'Path' from a list of components.------ >> joinPath ["/tmp","someDir","file.txt"] == "/tmp/someDir/file.txt"--- >> joinPath ["/tmp","someDir","file.txt"] == asRelFile "tmp/someDir/file.txt"-joinPath :: [String] -> Path ar fd-joinPath = asPath . intercalate [pathSeparator]---- | Currently just transforms:------ >> normalise "/tmp/fred/./jim/./file" == "/tmp/fred/jim/file"-normalise :: Path ar fd -> Path ar fd-normalise =- mkPathFromComponents .- filter (/= PathComponent currentDirComponent) .- pathComponents---- | Deconstructs a path into its components.------ >> splitPath (asAbsDir "/tmp/someDir/mydir.dir") == (["tmp","someDir","mydir.dir"], Nothing)--- >> splitPath (asAbsFile "/tmp/someDir/myfile.txt") == (["tmp","someDir"], Just "myfile.txt")-splitPath :: FileDirClass fd => Path ar fd -> ([RelDir], Maybe RelFile)-splitPath PathRoot = ([],Nothing)-splitPath p@(FileDir d pc) =- first (map (FileDir PathRoot)) $- fileDir- (\ _ -> (pathComponents d, Just (FileDir PathRoot pc)))- (\ _ -> (pathComponents p, Nothing))- p---- | 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" == asRelFile "anotherdir/file.txt"--- >> makeRelative "/tmp/somedir" "/tmp/somedir/anotherdir/dir" == asRelDir "anotherdir/dir"-makeRelative :: AbsDir -> AbsPath fd -> RelPath fd-makeRelative relTo orig =- maybe (error msg) mkPathFromComponents $- stripPrefix (pathComponents relTo) (pathComponents orig)- where- msg =- printf "System.Path can't make (%s) relative to (%s)"- (show orig) (show relTo)---- | Joins an absolute directory with a relative path to construct a--- new absolute path.------ >> makeAbsolute "/tmp" "file.txt" == asAbsFile "/tmp/file.txt"--- >> makeAbsolute "/tmp" "adir/file.txt" == asAbsFile "/tmp/adir/file.txt"--- >> makeAbsolute "/tmp" "adir/dir" == asAbsDir "/tmp/adir/dir"-makeAbsolute :: AbsDir -> RelPath fd -> AbsPath fd-makeAbsolute = genericMakeAbsolute---- | Converts a relative path into an absolute one by--- prepending the current working directory.-makeAbsoluteFromCwd :: RelPath fd -> IO (AbsPath fd)-makeAbsoluteFromCwd = genericMakeAbsoluteFromCwd---- | 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"-genericMakeAbsolute :: AbsRelClass ar => AbsDir -> Path ar fd -> AbsPath fd-genericMakeAbsolute base p = absRel id (base </>) p---- | As for 'makeAbsoluteFromCwd', but for use when the path may already be--- absolute (in which case it is left unchanged).-genericMakeAbsoluteFromCwd :: AbsRelClass ar => Path ar fd -> IO (AbsPath fd)-genericMakeAbsoluteFromCwd p = do- cwdString <- SD.getCurrentDirectory -- we don't use System.Path.Directory impl here to avoid module cycle- return $ genericMakeAbsolute (asAbsDir cwdString) p--prop_makeAbsoluteFromDir_endSame :: AbsDir -> RelFile -> Property-prop_makeAbsoluteFromDir_endSame base p =- property $ show p `isSuffixOf` show (makeAbsolute base p)--prop_makeAbsoluteFromDir_startSame :: AbsDir -> RelFile -> Property-prop_makeAbsoluteFromDir_startSame base p =- property $ show base `isPrefixOf` show (makeAbsolute base p)---- prop_makeAbsoluteFromDir_startSameAbs :: AbsDir -> AbsFile -> Property--- prop_makeAbsoluteFromDir_startSameAbs base p = property $ show base `isPrefixOf` show (makeAbsolute base p)------------------------------------------------------------------------------ NYI - Not Yet Implemented--{--splitSearchPath :: String -> [String]-getSearchPath :: IO [String]-splitDrive :: String -> (String, String)-joinDrive :: String -> String -> String-takeDrive :: String -> String-hasDrive :: String -> Bool-dropDrive :: String -> String-isDrive :: String -> Bool-isValid :: String -> Bool-makeValid :: String -> String--}------------------------------------------------------------------------------ Path Predicates---- | Test whether a @'Path' ar fd@ is absolute.------ >> isAbsolute (asAbsFile "fred") == True--- >> isAbsolute (asRelFile "fred") == False--- >> isAbsolute (asAbsFile "/fred") == True--- >> isAbsolute (asRelFile "/fred") == False-isAbsolute :: AbsRelClass ar => Path ar fd -> Bool-isAbsolute = absRel (const True) (const False)---- | Test whether the 'String' would correspond to an absolute path--- if interpreted as a 'Path'.-isAbsoluteString :: String -> Bool-isAbsoluteString [] = False -- Treat the empty string as relative because it doesn't start with 'pathSeparators'-isAbsoluteString (x:_) = isPathSeparator x -- Absolute if first char is a path separator---- | Invariant - this should return True iff arg is of type @'Path' Rel _@------ > isRelative = not . isAbsolute-isRelative :: AbsRelClass ar => Path ar fd -> Bool-isRelative = not . isAbsolute---- | Test whether the 'String' would correspond to a relative path--- if interpreted as a 'Path'.------ > isRelativeString = not . isAbsoluteString-isRelativeString :: String -> Bool-isRelativeString = not . isAbsoluteString----- | Does the given filename have an extension?------ >> null (takeExtension x) == not (hasAnExtension x)-hasAnExtension :: FilePath ar -> Bool-hasAnExtension = not . null . snd . splitExtension---- | 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-hasExtension :: String -> FilePath ar -> Bool-hasExtension ext = (==ext) . snd . splitExtension------------------------------------------------------------------------------ Separators---- | This is largely for 'System.FilePath' compatability-addTrailingPathSeparator :: String -> String-addTrailingPathSeparator = (++[pathSeparator])---- | This is largely for 'System.FilePath' compatability-dropTrailingPathSeparator :: String -> String-dropTrailingPathSeparator = init---- | File extension character------ >> extSeparator == '.'-extSeparator :: Char-extSeparator = '.'---- | This is largely for 'System.FilePath' compatability-hasTrailingPathSeparator :: String -> Bool-hasTrailingPathSeparator = isPathSeparator . last---- | The character that separates directories. In the case where more than--- one character is possible, 'pathSeparator' is the \'ideal\' one.------ >> isPathSeparator pathSeparator-pathSeparator :: Char-pathSeparator | isWindows = '\\'- | otherwise = '/'---- | The list of all possible separators.------ >> pathSeparator `elem` pathSeparators-pathSeparators :: [Char]-pathSeparators = return pathSeparator---- | The character that is used to separate the entries in the $PATH environment variable.----searchPathSeparator :: Char-searchPathSeparator = ':'---- | Is the character an extension character?------ >> isExtSeparator a == (a == extSeparator)-isExtSeparator :: Char -> Bool-isExtSeparator = (== extSeparator)---- | Rather than using @(== 'pathSeparator')@, use this. Test if something--- is a path separator.------ >> isPathSeparator a == (a `elem` pathSeparators)-isPathSeparator :: Char -> Bool-isPathSeparator = flip elem pathSeparators---- | Is the character a file separator?------ >> isSearchPathSeparator a == (a == searchPathSeparator)-isSearchPathSeparator :: Char -> Bool-isSearchPathSeparator = (== searchPathSeparator)------------------------------------------------------------------------------ Generic Manipulation Functions---- These functions support manipulation of extensions on directories--- as well as files. They have looser types than the corresponding--- 'Basic Manipulation Functions', but it is expected that the basic--- functions will be used more frequently as they provide more checks.---- | This is a more flexible variant of 'addExtension' / '<.>' which can--- work with files or directories------ >> genericAddExtension "/" "x" == asAbsDir "/.x"--- >> genericAddExtension "/a" "x" == asAbsDir "/a.x"--- >> genericAddExtension "" "x" == asRelFile ".x"--- >> genericAddExtension "" "" == asRelFile ""-genericAddExtension :: Path ar fd -> String -> Path ar fd-genericAddExtension p "" = p-genericAddExtension path ext =- let suffix =- if [extSeparator] `isPrefixOf` ext- then ext- else extSeparator : ext- in case path of- FileDir p (PathComponent pc) ->- FileDir p (PathComponent (pc ++ suffix))- PathRoot ->- FileDir PathRoot (PathComponent suffix)--genericDropExtension :: Path ar fd -> Path ar fd-genericDropExtension = fst . genericSplitExtension--genericDropExtensions :: Path ar fd -> Path ar fd-genericDropExtensions = fst . genericSplitExtensions--genericSplitExtension :: Path ar fd -> (Path ar fd, String)-genericSplitExtension (FileDir p (PathComponent s)) = (FileDir p (PathComponent s1), s2)- where (s1,s2) = fixTrailingDot $ rbreak isExtSeparator s- fixTrailingDot ("",r2) = (r2,"")- fixTrailingDot (r1,r2) | [extSeparator] `isSuffixOf` r1 = (init r1, extSeparator:r2)- | otherwise = (r1,r2)- swap (x,y) = (y,x)- rbreak q = (reverse *** reverse) . swap . break q . reverse-genericSplitExtension p = (p,"")--genericSplitExtensions :: Path ar fd -> (Path ar fd, String)-genericSplitExtensions (FileDir p (PathComponent s)) = (FileDir p (PathComponent s1), s2)- where (s1,s2) = break isExtSeparator s-genericSplitExtensions p = (p,"")--genericTakeExtension :: Path ar fd -> String-genericTakeExtension = snd . genericSplitExtension--genericTakeExtensions :: Path ar fd -> String-genericTakeExtensions = snd . genericSplitExtension------------------------------------------------------------------------------ QuickCheck--_testall :: IO ()-_testall = do- putStrLn "Running QuickCheck tests..."- quickCheck prop_asPath_getPathString- quickCheck prop_mkPathFromComponents_pathComponents- quickCheck prop_makeAbsoluteFromDir_endSame- quickCheck prop_makeAbsoluteFromDir_startSame- quickCheck prop_split_combine- quickCheck prop_takeFileName_end- quickCheck prop_split_combineExt- putStrLn "Tests completed."---- test :: Testable a => a -> IO ()--- test = quickCheck--qcFileComponent :: Gen PathComponent-qcFileComponent = PathComponent <$> frequency [- (1, return "someFile"),- (1, return "fileWith.ext"),- (1, return "file.with.multiple.exts"),- (1, return "file with spcs")- ]--qcDirComponent :: Gen PathComponent-qcDirComponent = PathComponent <$> frequency [- (1, return "someDir"),- (1, return "aDir"),- (1, return "aFolder"),- (1, return "a folder"),- (1, return "directory")- ]--instance Arbitrary PathComponent where- arbitrary = oneof [qcFileComponent, qcDirComponent]---qcGenPath :: Gen PathComponent -> Gen (Path ar fd)-qcGenPath qcLastComponent = do- pcs <- QC.listOf qcDirComponent- pc <- qcLastComponent- return $ mkPathFromComponents (pcs ++ [pc])--qcFilePath :: Gen (FilePath ar)-qcFilePath = qcGenPath qcFileComponent--qcDirPath :: Gen (DirPath ar)-qcDirPath = qcGenPath qcDirComponent--newtype PathGen ar fd = PathGen {runPathGen :: Gen (Path ar fd)}--qcPath :: (AbsRelClass ar, FileDirClass fd) => Gen (Path ar fd)-qcPath = runPathGen $ switchFileDir (PathGen qcFilePath) (PathGen qcDirPath)--instance (AbsRelClass ar, FileDirClass fd) => Arbitrary (Path ar fd) where+module System.Path.Internal+(+ -- * The main filepath (& dirpath) abstract type+ Path, -- kept abstract++ -- * Type Synonyms+ AbsFile,+ RelFile,+ AbsDir,+ RelDir,+ AbsRelFile,+ AbsRelDir,+ AbsFileDir,+ RelFileDir,+ AbsRelFileDir,++ AbsPath, Abs,+ RelPath, Rel,+ FilePath, File,+ DirPath, Dir,+ AbsRelPath, AbsRel,+ FileDirPath, FileDir,++ -- * Decisions on path types+ withAbsRel, withFileDir,++ -- * Path to String conversion+ toString,+ getPathString,++ -- * Constants+ rootDir,+ currentDir,+ emptyFile,++ -- * Parsing Functions+ maybePath, maybe,+ parsePath, parse,++ -- * Checked Construction Functions+ path,+ relFile,+ relDir,+ absFile,+ absDir,+ relPath, rel,+ absPath, abs,+ filePath, file,+ dirPath, dir,+ absRel, fileDir,++ idAbsRel, idAbs, idRel,+ idFileDir, idFile, idDir,++ -- * Unchecked Construction Functions+ asPath,+ asRelFile,+ asRelDir,+ asAbsFile,+ asAbsDir,+ asRelPath,+ asAbsPath,+ asFilePath,+ asDirPath,++ -- * Checked Construction Functions+ mkPathAbsOrRel,+ mkPathFileOrDir,+ mkAbsPath,+ mkAbsPathFromCwd,++ -- * Basic Manipulation Functions+ (</>),+ (<.>),+ (<++>),+ addExtension,+ combine,+ dropExtension,+ dropExtensions,+ dropFileName,+ replaceExtension,+ replaceBaseName,+ replaceDirectory,+ replaceFileName,+ splitExtension,+ splitExtensions,+ splitFileName,+ splitDirName,+ takeBaseName,+ takeDirectory,+ takeSuperDirectory,+ takeExtension,+ takeExtensions,+ takeFileName,+ takeDirName,+ mapFileName,+ mapFileNameF,++ -- * Auxillary Manipulation Functions+ equalFilePath,+ joinPath,+ normalise,+ splitPath,+ makeRelative,+ makeRelativeMaybe,+ makeAbsolute,+ makeAbsoluteFromCwd,+ dynamicMakeAbsolute,+ dynamicMakeAbsoluteFromCwd,+ genericMakeAbsolute,+ genericMakeAbsoluteFromCwd,+ pathMap,+ dirFromFile,+ fileFromDir,+ toFileDir,+ fromFileDir,+ fileFromFileDir,+ dirFromFileDir,+ toAbsRel,+ fromAbsRel,++ -- * Path Predicates+ isAbsolute,+ isRelative,+ isAbsoluteString,+ isRelativeString,+ hasAnExtension,+ hasExtension,++ -- * Separators+ System(..),+ extSeparator,+ searchPathSeparator,+ isExtSeparator,+ isSearchPathSeparator,++ -- * Generic Manipulation Functions+ genericAddExtension,+ genericDropExtension,+ genericDropExtensions,+ genericSplitExtension,+ genericSplitExtensions,+ genericTakeExtension,+ genericTakeExtensions,++ -- * Tests+ testAll,+ isValid,+)++where++import qualified System.Path.Internal.PartClass as Class+import qualified System.Path.Internal.Part as Part+import qualified System.Path.Internal.Component as PC+import qualified System.Path.Internal.Separator as Sep+import System.Path.Internal.PartClass as Class+ (WrapFileDir(WrapFileDir), WrapAbsRel(WrapAbsRel), FuncArg(..), fdMap)+import System.Path.Internal.Part (absPC)+import System.Path.Internal.System (System(..))+import System.Path.Internal.Component+ (Component(Component), GenComponent)++import qualified System.Directory as SD++import qualified Control.Monad.Trans.Class as MT+import qualified Control.Monad.Trans.State as MS+import Control.Monad (MonadPlus, guard, liftM2, mplus, mzero)+import Control.Applicative (Const(Const), liftA2, (<$>), (<$))+import Control.DeepSeq (NFData(rnf))++import qualified Data.Monoid.HT as MonHT+import qualified Data.List.HT as ListHT+import Data.Tagged (Tagged(Tagged), untag)+import Data.Functor.Compose (Compose(Compose), getCompose)+import Data.List (isSuffixOf, stripPrefix, intersperse)+import Data.String (IsString(fromString))+import Data.Maybe.HT (toMaybe)+import Data.Maybe (fromMaybe, maybeToList)+import Data.Tuple.HT (mapFst, mapSnd)+import Data.Monoid (Monoid(mempty, mconcat), Endo(Endo), appEndo)+import Data.Semigroup (Semigroup(sconcat, (<>)), )+import Data.Char (isSpace)+import Data.Ord.HT (comparing)+import Data.Eq.HT (equating)++import Text.Show.HT (concatS)+import Text.Printf (printf)++import qualified Test.DocTest.Driver as DocTest+import qualified Test.QuickCheck as QC+import Test.QuickCheck+ (Gen, Property, property, Arbitrary(arbitrary), frequency)++import qualified Prelude as P+import Prelude hiding (FilePath, maybe, abs)+++{- $setup+>>> :set -fno-warn-warnings-deprecations+>>> import qualified System.Path.PartClass as Class+>>> import qualified System.Path.Generic as Path+>>> import qualified System.Path.Posix as Posix+>>> import qualified System.Path.Windows as Windows+>>> import System.Path.Generic ((</>), (<.>), relFile, relDir, absFile, absDir)+>>> import Data.List (isSuffixOf, isPrefixOf)+>>> import Data.Char (toLower)+>>> import qualified Test.QuickCheck as QC+>>> forAllAbsRel :: (Class.FileDir fd, QC.Testable prop) => (Default.AbsRel fd -> prop) -> QC.Property+>>> forAllAbsRel = QC.forAll QC.arbitrary+-}+++------------------------------------------------------------------------+-- Types++-- | This is the main filepath abstract datatype+data Path os ar fd = Path ar [Component os] fd++instance+ (System os, Class.AbsRel ar, Class.FileDir fd) =>+ Eq (Path os ar fd) where+ (==) = equating inspectPath++instance+ (System os, Class.AbsRel ar, Class.FileDir fd) =>+ Ord (Path os ar fd) where+ compare = comparing inspectPath++inspectPath ::+ Path os ar fd -> (WrapAbsRel os ar, [Component os], WrapFileDir os fd)+inspectPath (Path ar pcs fd) = (WrapAbsRel ar, pcs, WrapFileDir fd)+++selTag :: Path os ar fd -> Tagged os a -> a+selTag _ = untag+++type AbsFile os = Path os Part.Abs Part.File+type RelFile os = Path os Part.Rel Part.File+type AbsDir os = Path os Part.Abs Part.Dir+type RelDir os = Path os Part.Rel Part.Dir+type AbsRelFile os = Path os Part.AbsRel Part.File+type AbsRelDir os = Path os Part.AbsRel Part.Dir+type AbsFileDir os = Path os Part.Abs Part.FileDir+type RelFileDir os = Path os Part.Rel Part.FileDir+type AbsRelFileDir os = Path os Part.AbsRel Part.FileDir++type Abs os fd = Path os Part.Abs fd+type Rel os fd = Path os Part.Rel fd+type File os ar = Path os ar Part.File+type Dir os ar = Path os ar Part.Dir+type AbsRel os fd = Path os Part.AbsRel fd+type FileDir os ar = Path os ar Part.FileDir++{-# DEPRECATED RelPath "Use Path.Rel instead." #-}+{-# DEPRECATED AbsPath "Use Path.Abs instead." #-}+{-# DEPRECATED AbsRelPath "Use Path.AbsRel instead." #-}+{-# DEPRECATED FilePath "Use Path.File instead." #-}+{-# DEPRECATED DirPath "Use Path.Dir instead." #-}+{-# DEPRECATED FileDirPath "Use Path.FileDir instead." #-}++type AbsPath os fd = Path os Part.Abs fd+type RelPath os fd = Path os Part.Rel fd+type FilePath os ar = Path os ar Part.File+type DirPath os ar = Path os ar Part.Dir+type AbsRelPath os fd = Path os Part.AbsRel fd+type FileDirPath os ar = Path os ar Part.FileDir++instance (Class.AbsRel ar, Class.FileDir fd) => NFData (Path os ar fd) where+ rnf (Path ar pcs fd) =+ rnf (Class.withAbsRel rnf () ar, pcs, Class.withFileDir rnf () () fd)++-- I don't think this basic type of fold is appropriate for a nested datatype+-- pathFold :: a -> (a -> String -> a) -> Path ar fd -> a+-- pathFold pr f PathRoot = pr+-- pathFold pr f (FileDir d pc) = f (pathFold pr f d) (unPathComponent pc)++-- | Map over the components of the path.+--+-- prop> Path.pathMap (map toLower) (absDir "/tmp/Reports/SpreadSheets") == Posix.absDir "/tmp/reports/spreadsheets"+pathMap ::+ (Class.FileDir fd) => (String -> String) -> Path os ar fd -> Path os ar fd+pathMap f (Path ar pcs fd) = Path ar (map (PC.map f) pcs) (fdMap f fd)+++mapFilePart ::+ (GenComponent -> GenComponent) -> FilePath os ar -> FilePath os ar+mapFilePart f (Path ar pcs (Part.File fd)) = Path ar pcs $ Part.File $ f fd++mapFilePartF ::+ (Functor f) =>+ (GenComponent -> f GenComponent) -> FilePath os ar -> f (FilePath os ar)+mapFilePartF f (Path ar pcs (Part.File fd)) =+ Path ar pcs <$> Part.File <$> f fd++splitFilePart ::+ (GenComponent -> (GenComponent, a)) -> FilePath os ar -> (FilePath os ar, a)+splitFilePart f (Path ar pcs (Part.File fd)) = mapFst (Path ar pcs . Part.File) $ f fd++mapPathDirs ::+ ([Component os] -> [Component os]) -> Path os ar fd -> Path os ar fd+mapPathDirs f ~(Path ar pcs fd) = Path ar (f pcs) fd+++withAbsRel ::+ (Class.AbsRel ar) =>+ (AbsPath os fd -> a) -> (RelPath os fd -> a) -> Path os ar fd -> a+withAbsRel fAbs fRel (Path ar pcs fd) =+ Class.withAbsRel+ (\drive -> fAbs $ Path (Part.Abs (Component drive)) pcs fd)+ (fRel $ Path Part.Rel pcs fd)+ ar++switchFileDir ::+ (Class.FileDir fd) =>+ f (FilePath os ar) -> f (DirPath os ar) -> f (FileDirPath os ar) ->+ f (Path os ar fd)+switchFileDir f d fd =+ getCompose $ Class.switchFileDir (Compose f) (Compose d) (Compose fd)++switchFileOrDir ::+ (Class.FileOrDir fd) =>+ f (FilePath os ar) -> f (DirPath os ar) -> f (Path os ar fd)+switchFileOrDir f d =+ getCompose $ Class.switchFileOrDir (Compose f) (Compose d)++withFileDir ::+ (Class.FileOrDir fd) =>+ (FilePath os ar -> a) -> (DirPath os ar -> a) -> Path os ar fd -> a+withFileDir f g = runFuncArg $ switchFileOrDir (FuncArg f) (FuncArg g)+++-- | Currently not exported+eitherFromAbsRel ::+ Class.AbsRel ar => Path os ar fd -> Either (AbsPath os fd) (RelPath os fd)+eitherFromAbsRel = withAbsRel Left Right++-- | Currently not exported+_eitherFromFileDir ::+ Class.FileOrDir fd => Path os ar fd -> Either (FilePath os ar) (DirPath os ar)+_eitherFromFileDir = withFileDir Left Right++------------------------------------------------------------------------+-- Read & Show instances++{- |+We show and parse file path components+using the rather generic 'relPath' smart constructor+instead of 'relFile', 'relDir' and @relPath str :: FileDirPath ar@.+Otherwise handling of all cases of 'Part.File', 'Part.Dir' and 'Part.FileDir' types+becomes pretty complicated.++>>> Posix.rootDir </> relDir "bla" </> relFile "blub"+rootDir </> relPath "bla" </> relPath "blub"+>>> Just (Posix.rootDir </> relDir "bla" </> relFile "blub")+Just (rootDir </> relPath "bla" </> relPath "blub")+>>> Posix.currentDir </> relDir "bla" </> relFile "blub"+currentDir </> relPath "bla" </> relPath "blub"+>>> Just (Posix.currentDir </> relDir "bla" </> relFile "blub")+Just (currentDir </> relPath "bla" </> relPath "blub")+>>> Windows.absDir "c:" </> relDir "bla" </> relFile "blub"+absDir "c:" </> relPath "bla" </> relPath "blub"+>>> Just (Windows.absDir "c:\\" </> relDir "bla" </> relFile "blub")+Just (absDir "c:\\" </> relPath "bla" </> relPath "blub")+-}+instance+ (System os, Class.AbsRel ar, Class.FileDir fd) =>+ Show (Path os ar fd) where+ showsPrec = untag showsPrecTagged++showsPrecTagged ::+ (System os, Class.AbsRel ar, Class.FileDir fd) =>+ Tagged os (Int -> Path os ar fd -> ShowS)+showsPrecTagged =+ flip fmap rootStringTagged $ \root d x ->+ case pathComponents x of+ (ar, pcs) ->+ showParen (d>5) $ concatS $+ intersperse+ (showChar ' ' . showString combineOperator . showChar ' ') $+ Class.withAbsRel+ (\drive ->+ if drive == root+ then showString rootName+ else showsCons absDirName drive)+ (showString currentName)+ ar :+ map (\(Component pc) -> showsCons relPathName pc) pcs++showsCons :: Show a => String -> a -> ShowS+showsCons name arg = showString name . showChar ' ' . showsPrec 11 arg++{- |+Currently it also parses Part.AbsRel and Part.FileDir paths,+although these cannot be composed with the accepted combinators.+-}+-- prop> read "rootDir" == Posix.rootDir+-- prop> read "rootDir" == Windows.rootDir+-- prop> read "currentDir" == Posix.currentDir+-- prop> read "currentDir" == Windows.currentDir+-- prop> let path = Posix.rootDir </> relDir "bla" </> relFile "blub" in read (show path) == path+-- prop> let path = Just (Posix.rootDir </> relDir "bla" </> relFile "blub") in read (show path) == path+-- prop> let path = Posix.currentDir </> relDir "bla" </> relFile "blub" in read (show path) == path+-- prop> let path = Just (Posix.currentDir </> relDir "bla" </> relFile "blub") in read (show path) == path+-- prop> let path = Windows.rootDir </> relDir "bla" </> relFile "blub" in read (show path) == path+-- prop> let path = Just (Windows.rootDir </> relDir "bla" </> relFile "blub") in read (show path) == path+-- prop> let path = Windows.absDir "c:" </> relDir "bla" </> relFile "blub" in read (show path) == path+instance+ (System os, Class.AbsRel ar, Class.FileDir fd) =>+ Read (Path os ar fd) where+ readsPrec d = readParen (d>5) $ untag readsPrecTagged++readsPrecTagged ::+ (System os, Class.AbsRel ar, Class.FileDir fd) =>+ Tagged os (ReadS (Path os ar fd))+readsPrecTagged =+ flip fmap readsSplitDrive $ \readsSplDrv ->+ let go =+ handleMismatch+ (skipSpaces >> matchString combineOperator)+ (return [])+ (liftM2 (:) (fmap Component $ readsCons relPathName) go)+ in MS.runStateT $ do+ skipSpaces+ MT.lift . maybeToList =<<+ liftM2 maybePathFromComponents readsSplDrv go++skipSpaces :: (Monad m) => MS.StateT String m ()+skipSpaces = MS.modify $ dropWhile isSpace++readsCons :: (Read a) => String -> MS.StateT String [] a+readsCons name = do+ skipSpaces+ matchString name+ MS.StateT $ readsPrec 11++handleMismatch ::+ MS.StateT s Maybe () ->+ MS.StateT s m a -> MS.StateT s m a -> MS.StateT s m a+handleMismatch act err success =+ MS.StateT $ \s0 ->+ case MS.execStateT act s0 of+ Nothing -> MS.runStateT err s0+ Just s1 -> MS.runStateT success s1++matchString :: (MonadPlus m) => String -> MS.StateT String m ()+matchString prefix =+ MS.StateT $ P.maybe mzero (return . (,) ()) . stripPrefix prefix++readsSplitDrive ::+ (System os, Class.AbsRel ar) => Tagged os (MS.StateT String [] ar)+readsSplitDrive =+ flip fmap readsSplitDriveAbs $ \readsSplDrvAbs ->+ Class.switchAbsRel+ readsSplDrvAbs+ readsSplitDriveRel+ (mplus+ (fmap (\(Part.Abs drive) -> Part.AbsO drive) readsSplDrvAbs)+ (fmap (\Part.Rel -> Part.RelO) readsSplitDriveRel))++readsSplitDriveAbs :: (System os) => Tagged os (MS.StateT String [] Part.Abs)+readsSplitDriveAbs =+ flip fmap rootStringTagged $ \root ->+ fmap absPC $+ (root <$ matchString rootName)+ `mplus`+ readsCons absDirName++readsSplitDriveRel :: (MonadPlus m) => MS.StateT String m Part.Rel+readsSplitDriveRel = matchString currentName >> return Part.Rel+++-- | Convert the 'Path' into a plain 'String' as required for OS calls.+--+-- prop> \p -> Path.asPath (Path.toString p) == (p::Default.AbsFile)+toString ::+ (System os, Class.AbsRel ar, Class.FileDir fd) => Path os ar fd -> String+toString = flip toStringS ""++{-# DEPRECATED getPathString "Use Path.toString instead." #-}++-- | Synonym of 'toString' intended for unqualified use.+getPathString ::+ (System os, Class.AbsRel ar, Class.FileDir fd) => Path os ar fd -> String+getPathString = toString++toStringS ::+ (System os, Class.AbsRel ar, Class.FileDir fd) => Path os ar fd -> ShowS+toStringS x =+ case pathComponents x of+ (ar, []) ->+ Class.withAbsRel showString (showString currentDirComponent) ar+ (ar, pcs) ->+ concatS $+ Class.withAbsRel (\drive -> (showString drive :)) id ar $+ intersperse (showChar (selTag x pathSeparator)) $+ map (\(Component pc) -> showString pc) pcs+++------------------------------------------------------------------------+-- Constants++-- prop> Posix.toString Path.rootDir == "/"+-- prop> Windows.toString Path.rootDir == "\\"+rootDir :: (System os) => AbsDir os+rootDir = untag rootDirTagged++rootDirTagged :: (System os) => Tagged os (AbsDir os)+rootDirTagged = fmap (\root -> Path (absPC root) [] Part.Dir) rootStringTagged++rootStringTagged :: (System os) => Tagged os String+rootStringTagged = fmap (\sep -> [sep]) pathSeparator++-- prop> Posix.toString Path.currentDir == "."+-- prop> Windows.toString Path.currentDir == "."+currentDir :: (System os) => RelDir os+currentDir = mempty++{- |+This is a file with path @\"\"@.+You will not be able to create a file with this name.+We also forbid parsing @\"\"@ by 'relFile'.+You might only need this file path as intermediate step+when manipulating extensions of files like @\".bashrc\"@.+-}+emptyFile :: (System os) => RelFile os+emptyFile = atomicFile $ Part.File PC.empty++atomicFile :: Part.File -> RelFile os+atomicFile = Path Part.Rel []++rootName :: String+rootName = "rootDir"++currentName :: String+currentName = "currentDir"++currentDirComponent :: String+currentDirComponent = "."++absDirName :: String+absDirName = "absDir"++relPathName :: String+relPathName = "relPath"+++------------------------------------------------------------------------+-- Parsing Functions++{-# DEPRECATED maybePath "Use Path.maybe instead." #-}+{-# DEPRECATED parsePath "Use Path.parse instead." #-}++-- | This function is intended for checking and parsing paths+-- provided as user input.+--+-- prop> fmap Posix.toString (Posix.maybePath "/" :: Maybe Posix.AbsDir) == Just "/"+-- prop> fmap Posix.toString (Posix.maybePath "/" :: Maybe Posix.AbsFile) == Nothing+-- prop> fmap Posix.toString (Posix.maybePath "/" :: Maybe Posix.RelDir) == Nothing+-- prop> fmap Posix.toString (Posix.maybePath "/" :: Maybe Posix.RelFile) == Nothing+-- prop> fmap Posix.toString (Posix.maybePath "/tmp" :: Maybe Posix.AbsDir) == Just "/tmp"+-- prop> fmap Posix.toString (Posix.maybePath "/tmp" :: Maybe Posix.AbsFile) == Just "/tmp"+-- prop> fmap Posix.toString (Posix.maybePath "/tmp" :: Maybe Posix.RelDir) == Nothing+-- prop> fmap Posix.toString (Posix.maybePath "/tmp" :: Maybe Posix.RelFile) == Nothing+-- prop> fmap Posix.toString (Posix.maybePath "/tmp/" :: Maybe Posix.AbsDir) == Just "/tmp"+-- prop> fmap Posix.toString (Posix.maybePath "/tmp/" :: Maybe Posix.AbsFile) == Nothing+-- prop> fmap Posix.toString (Posix.maybePath "/tmp/" :: Maybe Posix.RelDir) == Nothing+-- prop> fmap Posix.toString (Posix.maybePath "/tmp/" :: Maybe Posix.RelFile) == Nothing+-- prop> fmap Posix.toString (Posix.maybePath "/tmp" :: Maybe Posix.AbsRelFileDir) == Just "/tmp"+-- prop> fmap Posix.toString (Posix.maybePath "/tmp/" :: Maybe Posix.AbsRelFileDir) == Just "/tmp"+-- prop> fmap Posix.toString (Posix.maybePath "file.txt" :: Maybe Posix.RelFile) == Just "file.txt"+-- prop> fmap Posix.toString (Posix.maybePath "file.txt" :: Maybe Posix.AbsFile) == Nothing+-- prop> fmap Windows.toString (Windows.maybePath "\\tmp" :: Maybe Windows.AbsDir) == Just "\\tmp"+-- prop> fmap Windows.toString (Windows.maybePath "a:\\tmp" :: Maybe Windows.AbsDir) == Just "a:\\tmp"+-- prop> fmap Windows.toString (Windows.maybePath "a:tmp" :: Maybe Windows.AbsDir) == Just "a:tmp"+-- prop> fmap Windows.toString (Windows.maybePath "a:\\" :: Maybe Windows.AbsDir) == Just "a:\\"+-- prop> fmap Windows.toString (Windows.maybePath "a:" :: Maybe Windows.AbsDir) == Just "a:"+-- prop> fmap Windows.toString (Windows.maybePath "tmp" :: Maybe Windows.RelDir) == Just "tmp"+-- prop> fmap Windows.toString (Windows.maybePath "\\tmp" :: Maybe Windows.RelDir) == Nothing+-- prop> fmap Windows.toString (Windows.maybePath "a:\\tmp" :: Maybe Windows.RelDir) == Nothing+-- prop> fmap Windows.toString (Windows.maybePath "a:tmp" :: Maybe Windows.RelDir) == Nothing+-- prop> fmap Windows.toString (Windows.maybePath "tmp" :: Maybe Windows.AbsDir) == Nothing+maybe, maybePath ::+ (System os, Class.AbsRel ar, Class.FileDir fd) =>+ String -> Maybe (Path os ar fd)+maybe str = do+ let (ar0, pcs0, fd0) = untag makePathComponents str+ ar <- Class.fromAbsRel ar0+ (pcs, fd) <-+ case fd0 of+ Left Part.FileDir -> arrangeComponents pcs0+ Right Part.Dir ->+ fmap ((,) pcs0) $+ Class.switchFileDir Nothing (Just Part.Dir) (Just Part.FileDir)+ return $ Path ar pcs fd++maybePath = maybe++parse, parsePath ::+ (System os, Class.AbsRel ar, Class.FileDir fd) =>+ String -> Either String (Path os ar fd)+parse = pathWithNames arName fdName+parsePath = parse++pathWithNames ::+ (System os, Class.AbsRel ar, Class.FileDir fd) =>+ Const String ar -> Const String fd ->+ String -> Either String (Path os ar fd)+pathWithNames (Const ar) (Const fd) str =+ P.maybe (Left (printf "\"%s\" is not a valid %s%spath" str ar fd)) Right $+ maybePath str++arName :: (Class.AbsRel ar) => Const String ar+arName = Class.switchAbsRel (Const "absolute ") (Const "relative ") (Const "")++fdName :: (Class.FileDir fd) => Const String fd+fdName = Class.switchFileDir (Const "file ") (Const "directory ") (Const "")++------------------------------------------------------------------------+-- Checked Construction Functions++-- | This function is intended for converting path strings+-- with known content, e.g. string literals, to the 'Path' type.+path ::+ (System os, Class.AbsRel ar, Class.FileDir fd) =>+ String -> Path os ar fd+path = either error id . parsePath++-- | Construct a 'RelFile' from a 'String'.+--+-- prop> Posix.toString (Posix.relFile "file.txt") == "file.txt"+-- prop> Posix.toString (Posix.relFile "tmp") == "tmp"+relFile :: (System os) => String -> RelFile os+relFile = path++-- | Construct a 'RelDir' from a 'String'.+--+-- prop> Posix.toString (Posix.relDir ".") == "."+-- prop> Posix.toString (Posix.relDir "file.txt") == "file.txt"+-- prop> Posix.toString (Posix.relDir "tmp") == "tmp"+relDir :: (System os) => String -> RelDir os+relDir = path++-- | Construct an 'AbsFile' from a 'String'.+--+-- prop> Posix.toString (Posix.absFile "/file.txt") == "/file.txt"+-- prop> Posix.toString (Posix.absFile "/tmp") == "/tmp"+absFile :: (System os) => String -> AbsFile os+absFile = path++-- | Construct an 'AbsDir' from a 'String'.+--+-- prop> Posix.toString (Posix.absDir "/file.txt") == "/file.txt"+-- prop> Posix.toString (Posix.absDir "/tmp") == "/tmp"+absDir :: (System os) => String -> AbsDir os+absDir = path++-- | Construct a 'Rel fd' from a 'String'.+rel :: (System os, Class.FileDir fd) => String -> Rel os fd+rel = path++-- | Construct an 'Abs fd' from a 'String'.+abs :: (System os, Class.FileDir fd) => String -> Abs os fd+abs = path++-- | Construct an 'AbsRel fd' from a 'String'.+absRel :: (System os, Class.FileDir fd) => String -> AbsRel os fd+absRel = path++-- | Construct a 'File ar' from a 'String'.+file :: (System os, Class.AbsRel ar) => String -> File os ar+file = path++-- | Construct a 'Dir ar' from a 'String'.+dir :: (System os, Class.AbsRel ar) => String -> Dir os ar+dir = path++-- | Construct a 'FileDir ar' from a 'String'.+fileDir :: (System os, Class.AbsRel ar) => String -> FileDir os ar+fileDir = path+++{-# DEPRECATED relPath "Use Path.rel instead." #-}+{-# DEPRECATED absPath "Use Path.abs instead." #-}+{-# DEPRECATED filePath "Use Path.file instead." #-}+{-# DEPRECATED dirPath "Use Path.dir instead." #-}++-- | Construct a 'RelPath fd' from a 'String'.+relPath :: (System os, Class.FileDir fd) => String -> RelPath os fd+relPath = path++-- | Construct an 'AbsPath fd' from a 'String'.+absPath :: (System os, Class.FileDir fd) => String -> AbsPath os fd+absPath = path++-- | Construct a 'FilePath ar' from a 'String'.+filePath :: (System os, Class.AbsRel ar) => String -> FilePath os ar+filePath = path++-- | Construct a 'DirPath ar' from a 'String'.+dirPath :: (System os, Class.AbsRel ar) => String -> DirPath os ar+dirPath = path++++idAbsRel :: AbsRelPath os fd -> AbsRelPath os fd+idAbsRel = id++idAbs :: AbsPath os fd -> AbsPath os fd+idAbs = id++idRel :: RelPath os fd -> RelPath os fd+idRel = id+++idFileDir :: FileDirPath os fd -> FileDirPath os fd+idFileDir = id++idFile :: FilePath os fd -> FilePath os fd+idFile = id++idDir :: DirPath os fd -> DirPath os fd+idDir = id+++{-# DEPRECATED asPath "Use 'maybePath', 'parsePath' or 'path' instead." #-}+{-# DEPRECATED asRelFile "Use 'relFile' instead." #-}+{-# DEPRECATED asRelDir "Use 'relDir' instead." #-}+{-# DEPRECATED asAbsFile "Use 'absFile' instead." #-}+{-# DEPRECATED asAbsDir "Use 'absDir' instead." #-}+{-# DEPRECATED asRelPath "Use 'relPath' instead." #-}+{-# DEPRECATED asAbsPath "Use 'absPath' instead." #-}+{-# DEPRECATED asFilePath "Use 'filePath' instead." #-}+{-# DEPRECATED asDirPath "Use 'dirPath' instead." #-}++------------------------------------------------------------------------+-- Unchecked Construction Functions+-- NB - these construction functions are non-IO and do no checking!!++-- | Use a 'String' as a 'Path' whose type is determined by its context.+-- You should not use this and other @as*@ functions,+-- since they may silently turn a relative path to an absolute one,+-- or vice versa, or they may accept a path as file path+-- although it ends on a slash.+-- If you are certain about the string content+-- then you should use 'path'.+-- If you got the string as user input then use 'maybePath' or 'parsePath'.+--+-- prop> Posix.asPath "/tmp" == Posix.absDir "/tmp"+-- prop> Posix.asPath "file.txt" == Posix.relFile "file.txt"+-- prop> Path.isAbsolute (Posix.asAbsDir "/tmp")+-- prop> Path.isRelative (Posix.asRelDir "/tmp")+-- prop> Posix.toString (Posix.asPath "/tmp" :: Posix.AbsDir) == "/tmp"+-- prop> Posix.toString (Posix.asPath "/tmp" :: Posix.RelDir) == "tmp"+-- prop> Windows.toString (Windows.asPath "\\tmp" :: Windows.AbsDir) == "\\tmp"+-- prop> Windows.toString (Windows.asPath "a:\\tmp" :: Windows.AbsDir) == "a:\\tmp"+-- prop> Windows.toString (Windows.asPath "a:tmp" :: Windows.AbsDir) == "a:tmp"+-- prop> Windows.toString (Windows.asPath "tmp" :: Windows.RelDir) == "tmp"+asPath ::+ (System os, Class.AbsRel ar, Class.FileDir fd) => String -> Path os ar fd+asPath = uncurry mkPathFromComponents . untag mkPathComponents+++-- | Use a 'String' as a 'RelFile'. No checking is done.+--+-- prop> Posix.toString (Posix.asRelFile "file.txt") == "file.txt"+-- prop> Posix.toString (Posix.asRelFile "/file.txt") == "file.txt"+-- prop> Posix.toString (Posix.asRelFile "tmp") == "tmp"+-- prop> Posix.toString (Posix.asRelFile "/tmp") == "tmp"+asRelFile :: (System os) => String -> RelFile os+asRelFile = asPath++-- | Use a 'String' as a 'RelDir'. No checking is done.+--+-- prop> Posix.toString (Posix.asRelDir ".") == "."+-- prop> Posix.toString (Posix.asRelDir "file.txt") == "file.txt"+-- prop> Posix.toString (Posix.asRelDir "/file.txt") == "file.txt"+-- prop> Posix.toString (Posix.asRelDir "tmp") == "tmp"+-- prop> Posix.toString (Posix.asRelDir "/tmp") == "tmp"+asRelDir :: (System os) => String -> RelDir os+asRelDir = asPath++-- | Use a 'String' as an 'AbsFile'. No checking is done.+--+-- prop> Posix.toString (Posix.asAbsFile "/file.txt") == "/file.txt"+-- prop> Posix.toString (Posix.asAbsFile "/tmp") == "/tmp"+asAbsFile :: (System os) => String -> AbsFile os+asAbsFile = asPath++-- | Use a 'String' as an 'AbsDir'. No checking is done.+--+-- prop> Posix.toString (Posix.asAbsDir "/file.txt") == "/file.txt"+-- prop> Posix.toString (Posix.asAbsDir "/tmp") == "/tmp"+asAbsDir :: (System os) => String -> AbsDir os+asAbsDir = asPath++-- | Use a 'String' as a 'RelPath fd'. No checking is done.+asRelPath :: (System os, Class.FileDir fd) => String -> RelPath os fd+asRelPath = asPath++-- | Use a 'String' as an 'AbsPath fd'. No checking is done.+asAbsPath :: (System os, Class.FileDir fd) => String -> AbsPath os fd+asAbsPath = asPath++-- | Use a 'String' as a 'FilePath ar'. No checking is done.+asFilePath :: (System os, Class.AbsRel ar) => String -> FilePath os ar+asFilePath = asPath++-- | Use a 'String' as a 'DirPath ar'. No checking is done.+asDirPath :: (System os, Class.AbsRel ar) => String -> DirPath os ar+asDirPath = asPath++-- | Forbid use of OverloadedStrings and prevent custom orphan instances+instance+ (ForbiddenSystem os, ForbiddenAbsRel ar, ForbiddenFileDir fd) =>+ IsString (Path os ar fd) where fromString = forbiddenFromString++class System os => ForbiddenSystem os where+ forbiddenFromString :: String -> Path os ar fd++class Class.AbsRel ar => ForbiddenAbsRel ar where+class Class.FileDir fd => ForbiddenFileDir fd where++------------------------------------------------------------------------+-- Checked Construction Functions++{-# DEPRECATED mkPathAbsOrRel "Use Path.absRel instead." #-}++-- | Examines the supplied string and constructs an absolute or+-- relative path as appropriate.+--+-- prop> Path.mkPathAbsOrRel "/tmp" == Left (Posix.absDir "/tmp")+-- prop> Path.mkPathAbsOrRel "tmp" == Right (Posix.relDir "tmp")+-- prop> Path.mkPathAbsOrRel "\\tmp" == Left (Windows.absDir "\\tmp")+-- prop> Path.mkPathAbsOrRel "d:\\tmp" == Left (Windows.absDir "d:\\tmp")+-- prop> Path.mkPathAbsOrRel "d:tmp" == Left (Windows.absDir "d:tmp")+-- prop> Path.mkPathAbsOrRel "tmp" == Right (Windows.relDir "tmp")+mkPathAbsOrRel, mkPathAbsOrRelPriv ::+ (System os, Class.FileDir fd) =>+ String -> Either (AbsPath os fd) (RelPath os fd)+mkPathAbsOrRel = mkPathAbsOrRelPriv+mkPathAbsOrRelPriv = eitherFromAbsRel . absRel++{-# DEPRECATED mkPathFileOrDir "Don't let the path type depend on current file system content. Instead choose the path type according to the needed disk object type." #-}++-- | Searches for a file or directory with the supplied path string+-- and returns a 'Part.File' or 'Part.Dir' path as appropriate. If neither exists+-- at the supplied path, 'Nothing' is returned.+mkPathFileOrDir ::+ (System os, Class.AbsRel ar) =>+ String -> IO (Maybe (Either (FilePath os ar) (DirPath os ar)))+mkPathFileOrDir s = do+ isfile <- SD.doesFileExist s+ isdir <- SD.doesDirectoryExist s+ case (isfile, isdir) of+ (False, False) -> return Nothing+ (True, False) -> return $ Just $ Left $ path s+ (False, True ) -> return $ Just $ Right $ path s+ (True, True ) -> ioError $ userError "mkPathFileOrDir - object type changed while checking"++{-# DEPRECATED mkAbsPath "Use Path.dynamicMakeAbsolute instead." #-}++-- | Convert a 'String' into an 'AbsPath' by interpreting it as+-- relative to the supplied directory if necessary.+--+-- prop> Path.mkAbsPath (absDir "/tmp") "foo.txt" == Posix.absFile "/tmp/foo.txt"+-- prop> Path.mkAbsPath (absDir "/tmp") "/etc/foo.txt" == Posix.absFile "/etc/foo.txt"+mkAbsPath ::+ (System os, Class.FileDir fd) => AbsDir os -> String -> AbsPath os fd+mkAbsPath d = either id (makeAbsolute d) . mkPathAbsOrRelPriv++{-# DEPRECATED mkAbsPathFromCwd "Use Path.dynamicMakeAbsoluteFromCwd instead." #-}++-- | Convert a 'String' into an 'AbsPath' by interpreting it as+-- relative to the cwd if necessary.+mkAbsPathFromCwd ::+ (System os, Class.FileDir fd) => String -> IO (AbsPath os fd)+mkAbsPathFromCwd = either return makeAbsoluteFromCwd . mkPathAbsOrRelPriv+++------------------------------------------------------------------------+-- Internal Functions for GenComponent manipulation++mkPathFromComponents ::+ (Class.FileDir fd) => ar -> [Component os] -> Path os ar fd+mkPathFromComponents ar pcs =+ uncurry (Path ar) $+ Class.switchFileDir+ (mapSnd Part.File $+ ListHT.switchR ([], PC.empty) (curry $ mapSnd PC.untag) pcs)+ (pcs, Part.Dir)+ (pcs, Part.FileDir)++maybePathFromComponents ::+ (Class.FileDir fd) => ar -> [Component os] -> Maybe (Path os ar fd)+maybePathFromComponents ar pcs =+ fmap (uncurry $ Path ar) $ arrangeComponents pcs++arrangeComponents ::+ (Class.FileDir fd) => [Component os] -> Maybe ([Component os], fd)+arrangeComponents pcs =+ getCompose $+ Class.switchFileDir+ (Compose $ fmap (mapSnd (Part.File . PC.untag)) $ ListHT.viewR pcs)+ (Compose $ Just (pcs, Part.Dir))+ (Compose $ Just (pcs, Part.FileDir))++mkPathComponents ::+ (System os, Class.AbsRel ar) =>+ Tagged os (String -> (ar, [Component os]))+mkPathComponents =+ liftA2+ (\isSep splDriveOS ->+ mapSnd (nonEmptyComponents . ListHT.chop isSep)+ . MS.runState splDriveOS)+ isPathSeparator splitDriveOS++{- |+Parse path string independent from expectations+expressed by the type parameters.+-}+makePathComponents ::+ (System os) =>+ Tagged os+ (String ->+ (Part.AbsRel, [Component os], Either Part.FileDir Part.Dir))+makePathComponents =+ liftA2+ (\isSep splAbsolute str ->+ let (ar, pct) =+ mapSnd (ListHT.chop isSep) $+ MS.runState splAbsolute str+ (pcs1, fd) =+ case ListHT.viewR pct of+ Nothing -> ([], Right Part.Dir)+ Just (pcs, pc) ->+ if null pc -- caused by trailing slash+ then (pcs, Right Part.Dir)+ else (pct, Left Part.FileDir)+ in (ar, nonEmptyComponents pcs1, fd))+ isPathSeparator splitAbsoluteO++nonEmptyComponents :: [String] -> [Component os]+nonEmptyComponents = map Component . filter (not . null)++splitDriveOS ::+ (System os, Class.AbsRel ar) => Tagged os (MS.State String ar)+splitDriveOS =+ liftA2+ (\splDrive splAbsolute ->+ Class.switchAbsRel (fmap absPC splDrive) (return Part.Rel) splAbsolute)+ splitDriveAbs splitAbsoluteO++splitDriveAbs :: (System os) => Tagged os (MS.State String String)+splitDriveAbs =+ liftA2+ (\isSep splDrive -> do+ drive <- splDrive+ xt <- MS.get+ case xt of+ [] -> return drive+ x:xs ->+ if isSep x+ then MS.put xs >> return (drive++[x])+ else return drive)+ isPathSeparator splitDrive++splitAbsoluteO :: (System os) => Tagged os (MS.State String Part.AbsRel)+splitAbsoluteO =+ fmap (\drive -> if null drive then Part.RelO else Part.AbsO $ Component drive)+ <$>+ splitAbsolute++-- | > \p -> uncurry Path.mkPathFromComponents (Path.pathComponents p) == (p::Default.AbsDir)+pathComponents ::+ (Class.FileDir fd) => Path os ar fd -> (ar, [Component os])+pathComponents (Path ar pcs fd) =+ (ar, pcs ++ Class.withFileDir ((:[]) . PC.retag) [] [] fd)++prop_mkPathFromComponents_pathComponents :: (System os) => AbsDir os -> Property+prop_mkPathFromComponents_pathComponents p =+ property $ uncurry mkPathFromComponents (pathComponents p) == p++++------------------------------------------------------------------------+-- Basic Manipulation Functions++combineOperator :: String+combineOperator = "</>"+++instance (Class.Rel ar, Class.Dir fd) => Semigroup (Path os ar fd) where+ Path r pcs0 _dir <> Path _rel pcs1 d = Path r (pcs0 ++ pcs1) d+ sconcat paths =+ Path Class.relVar+ (sconcat $ fmap (\(Path _rel pcs _dir) -> pcs) paths) Class.dirVar++instance (Class.Rel ar, Class.Dir fd) => Monoid (Path os ar fd) where+ mempty = Path Class.relVar [] Class.dirVar+ mconcat paths =+ Path Class.relVar+ (concatMap (\(Path _rel pcs _dir) -> pcs) paths) Class.dirVar+++-- | Infix variant of 'combine'.+--+-- prop> Posix.toString (Posix.absDir "/tmp" </> Posix.relFile "file.txt") == "/tmp/file.txt"+-- prop> Posix.toString (Posix.absDir "/tmp" </> Posix.relDir "dir" </> Posix.relFile "file.txt") == "/tmp/dir/file.txt"+-- prop> Posix.toString (Posix.relDir "dir" </> Posix.relFile "file.txt") == "dir/file.txt"+-- prop> Windows.toString (Windows.absDir "\\tmp" </> Windows.relFile "file.txt") == "\\tmp\\file.txt"+-- prop> Windows.toString (Windows.absDir "c:\\tmp" </> Windows.relFile "file.txt") == "c:\\tmp\\file.txt"+-- prop> Windows.toString (Windows.absDir "c:tmp" </> Windows.relFile "file.txt") == "c:tmp\\file.txt"+-- prop> Windows.toString (Windows.absDir "c:\\" </> Windows.relDir "tmp" </> Windows.relFile "file.txt") == "c:\\tmp\\file.txt"+-- prop> Windows.toString (Windows.absDir "c:" </> Windows.relDir "tmp" </> Windows.relFile "file.txt") == "c:tmp\\file.txt"+-- prop> Windows.toString (Windows.relDir "dir" </> Windows.relFile "file.txt") == "dir\\file.txt"+(</>) :: DirPath os ar -> RelPath os fd -> Path os ar fd+Path ar pcs0 Part.Dir </> Path Part.Rel pcs1 fd = Path ar (pcs0 ++ pcs1) fd++infixr 5 </>++-- | Infix variant of 'addExtension'.+-- 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'.+(<.>) :: FilePath os ar -> String -> FilePath os ar+p <.> ext = mapFilePart (flip PC.addExtension ext) p++infixl 7 <.>++(<++>) :: FilePath os ar -> String -> FilePath os ar+p <++> str = mapFileName (++str) p++infixl 7 <++>++-- | Add an extension, even if there is already one there.+-- E.g. @addExtension \"foo.txt\" \"bat\" -> \"foo.txt.bat\"@.+--+-- prop> Path.addExtension (relFile "file.txt") "bib" == Posix.relFile "file.txt.bib"+-- prop> Path.addExtension (relFile "file.") ".bib" == Posix.relFile "file..bib"+-- prop> Path.addExtension (relFile "file") ".bib" == Posix.relFile "file.bib"+-- prop> Path.addExtension Path.emptyFile "bib" == Posix.relFile ".bib"+-- prop> Path.addExtension Path.emptyFile ".bib" == Posix.relFile ".bib"+-- prop> Path.takeFileName (Path.addExtension Path.emptyFile "ext") == Posix.relFile ".ext"+addExtension :: FilePath os ar -> String -> FilePath os ar+addExtension = (<.>)++-- | Join an (absolute or relative) directory path with a relative+-- (file or directory) path to form a new path.+--+-- prop> \p -> Path.combine Path.currentDir p == (p::Default.RelDir)+combine :: DirPath os ar -> RelPath os fd -> Path os ar fd+combine = (</>)+++-- | Remove last extension, and the \".\" preceding it.+--+-- prop> forAllAbsRel $ \x -> Path.dropExtension x == fst (Path.splitExtension x)+dropExtension :: FilePath os ar -> FilePath os ar+dropExtension = fst . splitExtension++-- | Drop all extensions+--+-- prop> forAllAbsRel $ \x -> not $ Path.hasAnExtension (Path.dropExtensions x)+dropExtensions :: FilePath os ar -> FilePath os ar+dropExtensions = fst . splitExtensions++-- | Synonym for 'takeDirectory'+dropFileName :: FilePath os ar -> DirPath os ar+dropFileName = fst . splitFileName+++-- | Set the extension of a file, overwriting one if already present.+--+-- prop> Path.replaceExtension (relFile "file.txt") ".bob" == Posix.relFile "file.bob"+-- prop> Path.replaceExtension (relFile "file.txt") "bob" == Posix.relFile "file.bob"+-- prop> Path.replaceExtension (relFile "file") ".bob" == Posix.relFile "file.bob"+-- prop> Path.replaceExtension (relFile "file.txt") "" == Posix.relFile "file"+-- prop> Path.replaceExtension (relFile "file.fred.bob") "txt" == Posix.relFile "file.fred.txt"+replaceExtension :: FilePath os ar -> String -> FilePath os ar+replaceExtension p ext = dropExtension p <.> ext++replaceBaseName :: FilePath os ar -> String -> FilePath os ar+replaceBaseName p bn =+ mapFilePart (PC.addExtension (Component bn) . snd . PC.splitExtension) p++replaceDirectory :: FilePath os ar1 -> DirPath os ar2 -> FilePath os ar2+replaceDirectory (Path _ _ fd) (Path ar pcs _) = Path ar pcs fd++replaceFileName :: FilePath os ar -> String -> FilePath os ar+replaceFileName p fn = mapFilePart (const (Component fn)) p+++-- | Split on the extension. 'addExtension' is the inverse.+--+-- prop> forAllAbsRel $ \x -> uncurry (<.>) (Path.splitExtension x) == x+-- prop> forAllAbsRel $ \x -> uncurry Path.addExtension (Path.splitExtension x) == x+-- prop> Path.splitExtension (relFile "file.txt") == (Posix.relFile "file",".txt")+-- prop> Path.splitExtension (relFile ".bashrc") == (Posix.emptyFile, ".bashrc")+-- prop> Path.splitExtension (relFile "file") == (Posix.relFile "file","")+-- prop> Path.splitExtension (relFile "file/file.txt") == (Posix.relFile "file/file",".txt")+-- prop> Path.splitExtension (relFile "file.txt/boris") == (Posix.relFile "file.txt/boris","")+-- prop> Path.splitExtension (relFile "file.txt/boris.ext") == (Posix.relFile "file.txt/boris",".ext")+-- prop> Path.splitExtension (relFile "file/path.txt.bob.fred") == (Posix.relFile "file/path.txt.bob",".fred")+splitExtension :: FilePath os ar -> (FilePath os ar, String)+splitExtension = splitFilePart PC.splitExtension++-- | Split on all extensions+--+-- prop> Path.splitExtensions (relFile "file.tar.gz") == (Posix.relFile "file",".tar.gz")+-- prop> \p -> uncurry (<.>) (Path.splitExtension p) == (p::Default.AbsFile)+splitExtensions :: FilePath os ar -> (FilePath os ar, String)+splitExtensions = splitFilePart PC.splitExtensions++-- | prop> \p -> uncurry Path.combine (Path.splitFileName p) == (p::Default.AbsFile)+splitFileName :: FilePath os ar -> (DirPath os ar, RelFile os)+splitFileName (Path ar pcs fd) = (Path ar pcs Part.Dir, atomicFile fd)++-- | > \p -> (uncurry Path.combine <$> Path.splitDirName p) == toMaybe (not $ Default.isDrive p) (p::Default.AbsDir)+splitDirName :: DirPath os ar -> Maybe (DirPath os ar, RelDir os)+splitDirName = fmap (mapSnd dirFromFile . splitFileName) . fileFromDir++prop_splitDir_combine :: (System os) => AbsDir os -> Property+prop_splitDir_combine p =+ property $+ (uncurry combine <$> splitDirName p) == toMaybe (not $ isDrive p) p+++-- | Get the basename of a file+--+-- prop> Path.takeBaseName (absFile "/tmp/somedir/myfile.txt") == Posix.relFile "myfile"+-- prop> Path.takeBaseName (relFile "./myfile.txt") == Posix.relFile "myfile"+-- prop> Path.takeBaseName (relFile "myfile.txt") == Posix.relFile "myfile"+takeBaseName :: FilePath os ar -> RelFile os+takeBaseName = takeFileName . dropExtension++takeDirectory :: FilePath os ar -> DirPath os ar+takeDirectory = fst . splitFileName++-- prop> Path.takeSuperDirectory (Posix.absDir "/tmp/somedir") == Just (absDir "/tmp")+-- prop> Path.takeSuperDirectory (Posix.absDir "/tmp/") == Just (absDir "/")+-- prop> Path.takeSuperDirectory (Posix.absDir "/") == Nothing+-- prop> Path.takeSuperDirectory (Posix.relDir "tmp/somedir") == Just (relDir "tmp")+-- prop> Path.takeSuperDirectory (Posix.relDir "./somedir") == Just (relDir ".")+-- prop> Path.takeSuperDirectory (Posix.relDir "somedir") == Just Path.currentDir+-- prop> Path.takeSuperDirectory (Posix.relDir "") == Nothing+takeSuperDirectory :: DirPath os ar -> Maybe (DirPath os ar)+takeSuperDirectory = fmap takeDirectory . fileFromDir++-- | Get the extension of a file, returns @\"\"@ for no extension, @.ext@ otherwise.+--+-- prop> forAllAbsRel $ \x -> Path.takeExtension x == snd (Path.splitExtension x)+-- prop> forAllAbsRel $ \x -> Path.takeExtension (Path.addExtension x "ext") == ".ext"+-- prop> forAllAbsRel $ \x -> Path.takeExtension (Path.replaceExtension x "ext") == ".ext"+takeExtension :: FilePath os ar -> String+takeExtension = snd . splitExtension++-- | Get all extensions+--+-- prop> Path.takeExtensions (Posix.relFile "file.tar.gz") == ".tar.gz"+takeExtensions :: FilePath os ar -> String+takeExtensions = snd . splitExtensions++-- | Get the filename component of a file path (ie stripping all parent dirs)+--+-- prop> Path.takeFileName (absFile "/tmp/somedir/myfile.txt") == Posix.relFile "myfile.txt"+-- prop> Path.takeFileName (relFile "./myfile.txt") == Posix.relFile "myfile.txt"+-- prop> Path.takeFileName (relFile "myfile.txt") == Posix.relFile "myfile.txt"+-- prop> \p -> Path.toString (Path.takeFileName p) `isSuffixOf` Path.toString (p::Default.AbsFile)+takeFileName :: FilePath os ar -> RelFile os+takeFileName (Path _ _ fd) = atomicFile fd++-- | > \p -> fmap (\d -> toString d `isSuffixOf` toString p) (takeDirName p) == toMaybe (not $ isDrive p) True+takeDirName :: DirPath os ar -> Maybe (RelDir os)+takeDirName = fmap snd . splitDirName++prop_takeDirName_end :: (System os) => AbsDir os -> Property+prop_takeDirName_end p =+ property $+ fmap (\d -> toString d `isSuffixOf` toString p) (takeDirName p)+ ==+ toMaybe (not $ isDrive p) True++mapFileName :: (String -> String) -> FilePath os ar -> FilePath os ar+mapFileName = mapFilePart . PC.map++mapFileNameF ::+ (Functor f) =>+ (String -> f String) -> FilePath os ar -> f (FilePath os ar)+mapFileNameF = mapFilePartF . PC.mapF+++------------------------------------------------------------------------+-- Auxillary Manipulation Functions++-- | Check whether two strings are equal as file paths.+--+-- prop> Posix.equalFilePath "abc/def" "abc/def"+-- prop> Posix.equalFilePath "abc/def" "abc//def"+-- prop> Posix.equalFilePath "/tmp/" "/tmp"+-- prop> Posix.equalFilePath "/tmp" "//tmp"+-- prop> Posix.equalFilePath "/tmp" "///tmp"+-- prop> not $ Posix.equalFilePath "abc" "def"+-- prop> not $ Posix.equalFilePath "/tmp" "tmp"+-- prop> Windows.equalFilePath "abc\\def" "abc\\def"+-- prop> Windows.equalFilePath "abc\\def" "abc\\\\def"+-- prop> Windows.equalFilePath "file" "File"+-- prop> Windows.equalFilePath "\\file" "\\\\file"+-- prop> Windows.equalFilePath "\\file" "\\\\\\file"+-- prop> not $ Windows.equalFilePath "abc" "def"+-- prop> not $ Windows.equalFilePath "file" "dir"+equalFilePath :: (System os) => Tagged os (String -> String -> Bool)+equalFilePath = equating <$> mkPathAbsOrRelTagged++mkPathAbsOrRelTagged ::+ (System os) =>+ Tagged os (String -> Either (AbsFileDir os) (RelFileDir os))+mkPathAbsOrRelTagged = Tagged mkPathAbsOrRelPriv++-- | Constructs a 'RelPath' from a list of components.+-- It is an unchecked error if the path components contain path separators.+-- It is an unchecked error if a 'RelFile' path is empty.+--+-- prop> Path.joinPath ["tmp","someDir","dir"] == Posix.relDir "tmp/someDir/dir"+-- prop> Path.joinPath ["tmp","someDir","file.txt"] == Posix.relFile "tmp/someDir/file.txt"+joinPath :: (Class.FileDir fd) => [String] -> RelPath os fd+joinPath = mkPathFromComponents Part.Rel . map Component++-- | Currently just transforms:+--+-- prop> Path.normalise (absFile "/tmp/fred/./jim/./file") == Posix.absFile "/tmp/fred/jim/file"+normalise :: (System os) => Path os ar fd -> Path os ar fd+normalise = mapPathDirs (filter (Component currentDirComponent /=))++-- | Deconstructs a path into its components.+--+-- prop> Path.splitPath (Posix.absDir "/tmp/someDir/mydir.dir") == (True, map relDir ["tmp","someDir","mydir.dir"], Nothing)+-- prop> Path.splitPath (Posix.absFile "/tmp/someDir/myfile.txt") == (True, map relDir ["tmp","someDir"], Just $ relFile "myfile.txt")+splitPath ::+ (Class.AbsRel ar, Class.FileOrDir fd) =>+ Path os ar fd -> (Bool, [RelDir os], Maybe (RelFile os))+splitPath (Path ar pcs fd) =+ (Class.isAbsolute ar,+ map (\pc -> Path Part.Rel [pc] Part.Dir) pcs,+ maybeFileDir fd)++maybeFileDir :: (Class.FileOrDir fd) => fd -> Maybe (RelFile os)+maybeFileDir = Class.withFileOrDir (Just . atomicFile . Part.File) Nothing++-- | 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'.+--+-- prop> Path.makeRelative (absDir "/tmp/somedir") (absFile "/tmp/somedir/anotherdir/file.txt") == Posix.relFile "anotherdir/file.txt"+-- prop> Path.makeRelative (absDir "/tmp/somedir") (absDir "/tmp/somedir/anotherdir/dir") == Posix.relDir "anotherdir/dir"+-- prop> Path.makeRelative (absDir "c:\\tmp\\somedir") (absFile "C:\\Tmp\\SomeDir\\AnotherDir\\File.txt") == Windows.relFile "AnotherDir\\File.txt"+-- prop> Path.makeRelative (absDir "c:\\tmp\\somedir") (absDir "c:\\tmp\\somedir\\anotherdir\\dir") == Windows.relDir "anotherdir\\dir"+-- prop> Path.makeRelative (absDir "c:tmp\\somedir") (absDir "c:tmp\\somedir\\anotherdir\\dir") == Windows.relDir "anotherdir\\dir"+makeRelative ::+ (System os, Class.FileDir fd) =>+ AbsDir os -> AbsPath os fd -> RelPath os fd+makeRelative relTo orig =+ fromMaybe+ (error $+ printf "System.Path can't make (%s) relative to (%s)"+ (toString orig) (toString relTo)) $+ makeRelativeMaybe relTo orig++-- prop> Path.makeRelativeMaybe (Posix.absDir "/tmp/somedir") (absFile "/tmp/anotherdir/file.txt") == Nothing+-- prop> Path.makeRelativeMaybe (Posix.absDir "/Tmp") (absFile "/tmp/anotherdir/file.txt") == Nothing+-- prop> Path.makeRelativeMaybe (Windows.absDir "\\Tmp") (absFile "\\tmp\\anotherdir\\file.txt") == Just (relFile "anotherdir\\file.txt")+makeRelativeMaybe ::+ (System os, Class.FileDir fd) =>+ AbsDir os -> AbsPath os fd -> Maybe (RelPath os fd)+makeRelativeMaybe relTo orig =+ case (inspectPath relTo, inspectPath orig) of+ ((relToAR, relToPCs, WrapFileDir Part.Dir),+ (origAR, origPCs, WrapFileDir fd)) ->+ fmap (flip (Path Part.Rel) fd) $+ guard (relToAR == origAR) >> stripPrefix relToPCs origPCs++-- | Joins an absolute directory with a relative path to construct a+-- new absolute path.+--+-- prop> Path.makeAbsolute (absDir "/tmp") (relFile "file.txt") == Posix.absFile "/tmp/file.txt"+-- prop> Path.makeAbsolute (absDir "/tmp") (relFile "adir/file.txt") == Posix.absFile "/tmp/adir/file.txt"+-- prop> Path.makeAbsolute (absDir "/tmp") (relDir "adir/dir") == Posix.absDir "/tmp/adir/dir"+-- prop> \base p -> Default.toString p `isSuffixOf` Path.toString (Path.makeAbsolute base (Path.idFile p))+-- prop> \base p -> Default.toString base `isPrefixOf` Path.toString (Path.makeAbsolute base (Path.idFile p))+makeAbsolute :: (System os) => AbsDir os -> RelPath os fd -> AbsPath os fd+makeAbsolute = genericMakeAbsolute++-- | Converts a relative path into an absolute one by+-- prepending the current working directory.+makeAbsoluteFromCwd :: (System os) => RelPath os fd -> IO (AbsPath os fd)+makeAbsoluteFromCwd = genericMakeAbsoluteFromCwd++dynamicMakeAbsolute ::+ (System os) => AbsDir os -> AbsRelPath os fd -> AbsPath os fd+dynamicMakeAbsolute = genericMakeAbsolute++dynamicMakeAbsoluteFromCwd ::+ (System os) => AbsRelPath os fd -> IO (AbsPath os fd)+dynamicMakeAbsoluteFromCwd = genericMakeAbsoluteFromCwd++-- | As for 'makeAbsolute', but for use when the path may already be+-- absolute (in which case it is left unchanged).+-- You should avoid the use of 'genericMakeAbsolute'-type functions,+-- because then you avoid to absolutize a path that was already absolutized.+--+-- prop> Path.genericMakeAbsolute (absDir "/tmp") (relFile "file.txt") == Posix.absFile "/tmp/file.txt"+-- prop> Path.genericMakeAbsolute (absDir "/tmp") (relFile "adir/file.txt") == Posix.absFile "/tmp/adir/file.txt"+-- prop> Path.genericMakeAbsolute (absDir "/tmp") (absFile "/adir/file.txt") == Posix.absFile "/adir/file.txt"+genericMakeAbsolute ::+ (System os, Class.AbsRel ar) => AbsDir os -> Path os ar fd -> AbsPath os fd+genericMakeAbsolute base p = withAbsRel id (base </>) p++-- | As for 'makeAbsoluteFromCwd', but for use when the path may already be+-- absolute (in which case it is left unchanged).+genericMakeAbsoluteFromCwd ::+ (System os, Class.AbsRel ar) => Path os ar fd -> IO (AbsPath os fd)+genericMakeAbsoluteFromCwd p = do+ cwdString <- SD.getCurrentDirectory -- we don't use System.Path.Directory impl here to avoid module cycle+ return $ genericMakeAbsolute (asAbsDir cwdString) p++-- prop_makeAbsoluteFromDir_startSameAbs :: AbsDir os -> AbsFile -> Property+-- prop_makeAbsoluteFromDir_startSameAbs base p = property $ show base `isPrefixOf` show (makeAbsolute base p)+++-- | Convert a file to a directory path.+-- Obviously, the corresponding disk object won't change accordingly.+-- The purpose of this function is to be an intermediate step+-- when deriving a directory name from a file name.+dirFromFile :: FilePath os ar -> DirPath os ar+dirFromFile p = uncurry Path (pathComponents p) Part.Dir++-- | Convert a directory to a file path.+-- The function returns 'Nothing' if the directory path is empty.+-- The purpose of this function is to be an intermediate step+-- when deriving a file name from a directory name.+fileFromDir :: DirPath os ar -> Maybe (FilePath os ar)+fileFromDir = fileFromAny++toFileDir :: (Class.FileDir fd) => Path os ar fd -> FileDirPath os ar+toFileDir p = uncurry Path (pathComponents p) Part.FileDir++fromFileDir ::+ (Class.FileDir fd) => FileDirPath os ar -> Maybe (Path os ar fd)+fromFileDir p =+ switchFileDir+ (fileFromFileDir p)+ (Just $ dirFromFileDir p)+ (Just p)++fileFromFileDir :: FileDirPath os ar -> Maybe (FilePath os ar)+fileFromFileDir = fileFromAny++fileFromAny :: Path os ar fd -> Maybe (FilePath os ar)+fileFromAny (Path ar pcs _) =+ fmap (uncurry (Path ar) . mapSnd (Part.File . PC.untag)) $ ListHT.viewR pcs++dirFromFileDir :: FileDirPath os ar -> DirPath os ar+dirFromFileDir (Path ar pcs Part.FileDir) = Path ar pcs Part.Dir+++toAbsRel :: (Class.AbsRel ar) => Path os ar fd -> AbsRelPath os fd+toAbsRel (Path ar pcs fd) = Path (Class.toAbsRel ar) pcs fd++fromAbsRel :: (Class.AbsRel ar) => AbsRelPath os fd -> Maybe (Path os ar fd)+fromAbsRel (Path ar0 pcs fd) = (\ar -> Path ar pcs fd) <$> Class.fromAbsRel ar0+++------------------------------------------------------------------------+-- NYI - Not Yet Implemented++{-+splitSearchPath :: String -> [String]+getSearchPath :: IO [String]+splitDrive :: String -> (String, String)+joinDrive :: String -> String -> String+takeDrive :: String -> String+hasDrive :: String -> Bool+dropDrive :: String -> String+isDrive :: String -> Bool+isValid :: String -> Bool+makeValid :: String -> String+-}++isDrive :: AbsDir os -> Bool+isDrive (Path _ pcs _) = null pcs+++------------------------------------------------------------------------+-- Path Predicates++-- | Test whether a @'Path' ar fd@ is absolute.+--+-- prop> Path.isAbsolute (Posix.absFile "/fred")+-- prop> Path.isAbsolute (Windows.absFile "\\fred")+-- prop> Path.isAbsolute (Windows.absFile "c:\\fred")+-- prop> Path.isAbsolute (Windows.absFile "c:fred")+isAbsolute :: Class.AbsRel ar => Path os ar fd -> Bool+isAbsolute = withAbsRel (const True) (const False)++-- | Invariant - this should return True iff arg is of type @'Path' Part.Rel _@+--+-- > isRelative = not . isAbsolute+-- prop> Path.isRelative (Posix.relFile "fred")+-- prop> Path.isRelative (Windows.relFile "fred")+isRelative :: Class.AbsRel ar => Path os ar fd -> Bool+isRelative = not . isAbsolute+++{- |+Test whether the 'String' would correspond+to an absolute path if interpreted as a 'Path'.+-}+isAbsoluteString :: (System os) => Tagged os (String -> Bool)+isAbsoluteString =+ fmap (\split -> not . null . MS.evalState split) splitAbsolute++{- |+Test whether the 'String' would correspond+to a relative path if interpreted as a 'Path'.++> isRelativeString = not . isAbsoluteString+-}+isRelativeString :: (System os) => Tagged os (String -> Bool)+isRelativeString = (not .) <$> isAbsoluteString+++-- | Does the given filename have an extension?+--+-- prop> forAllAbsRel $ \x -> null (Path.takeExtension x) == not (Path.hasAnExtension x)+hasAnExtension :: FilePath os ar -> Bool+hasAnExtension = not . null . snd . splitExtension++-- | Does the given filename have the given extension?+--+-- prop> Path.hasExtension ".hs" (Posix.relFile "MyCode.hs")+-- prop> Path.hasExtension ".hs" (Posix.relFile "MyCode.bak.hs")+-- prop> not $ Path.hasExtension ".hs" (Posix.relFile "MyCode.hs.bak")+hasExtension :: String -> FilePath os ar -> Bool+hasExtension ext = (==ext) . snd . splitExtension+++------------------------------------------------------------------------+-- Separators++-- | Part.File extension character+--+-- prop> Posix.extSeparator == '.'+extSeparator :: Char+extSeparator = Sep.extension++-- | The character that is used to separate the entries in the $PATH environment variable.+--+searchPathSeparator :: Char+searchPathSeparator = Sep.searchPath++-- | Is the character an extension character?+--+-- prop> \a -> Posix.isExtSeparator a == (a == Posix.extSeparator)+isExtSeparator :: Char -> Bool+isExtSeparator = Sep.isExtension++-- | Is the character a file separator?+--+-- prop> \a -> Posix.isSearchPathSeparator a == (a == Posix.searchPathSeparator)+isSearchPathSeparator :: Char -> Bool+isSearchPathSeparator = Sep.isSearchPath+++------------------------------------------------------------------------+-- Generic Manipulation Functions++-- These functions support manipulation of extensions on directories+-- as well as files. They have looser types than the corresponding+-- 'Basic Manipulation Functions', but it is expected that the basic+-- functions will be used more frequently as they provide more checks.++-- | This is a more flexible variant of 'addExtension' / '<.>' which can+-- work with files or directories+--+-- prop> Path.genericAddExtension (absDir "/") "x" == Posix.absDir "/.x"+-- prop> Path.genericAddExtension (absDir "/a") "x" == Posix.absDir "/a.x"+-- prop> Path.genericAddExtension Path.emptyFile "x" == Posix.relFile ".x"+-- prop> Path.genericAddExtension Path.emptyFile "" == Posix.emptyFile+genericAddExtension ::+ (Class.FileDir fd) => Path os ar fd -> String -> Path os ar fd+genericAddExtension =+ flip $ \ext ->+ appEndo $ MonHT.when (not $ null ext) $+ switchFileDir+ (Endo $ flip addExtension ext)+ (Endo $ componentsAddExtension ext)+ (Endo $ componentsAddExtension ext)++componentsAddExtension :: String -> Path os ar fd -> Path os ar fd+componentsAddExtension ext (Path ar pcs0 fd) =+ let pcs = if null pcs0 then [PC.empty] else pcs0+ in Path ar (mapLast (flip PC.addExtension ext) pcs) fd++genericDropExtension :: (Class.FileDir fd) => Path os ar fd -> Path os ar fd+genericDropExtension = fst . genericSplitExtension++genericDropExtensions :: (Class.FileDir fd) => Path os ar fd -> Path os ar fd+genericDropExtensions = fst . genericSplitExtensions++genericSplitExtension ::+ (Class.FileDir fd) => Path os ar fd -> (Path os ar fd, String)+genericSplitExtension =+ runSplitExtension $+ switchFileDir+ (SplitExtension splitExtension)+ (SplitExtension componentsSplitExtension)+ (SplitExtension componentsSplitExtension)++componentsSplitExtension :: Path os ar b -> (Path os ar b, String)+componentsSplitExtension (Path ar pcs fd) =+ mapFst (flip (Path ar) fd) $+ mapLastPair+ (error "genericSplitExtension: empty path")+ PC.splitExtension pcs++genericSplitExtensions ::+ (Class.FileDir fd) => Path os ar fd -> (Path os ar fd, String)+genericSplitExtensions =+ runSplitExtension $+ switchFileDir+ (SplitExtension splitExtensions)+ (SplitExtension componentsSplitExtensions)+ (SplitExtension componentsSplitExtensions)++componentsSplitExtensions :: Path os ar b -> (Path os ar b, String)+componentsSplitExtensions (Path ar pcs fd) =+ mapFst (flip (Path ar) fd) $+ mapLastPair+ (error "genericSplitExtensions: empty path")+ PC.splitExtensions pcs++genericTakeExtension :: (Class.FileDir fd) => Path os ar fd -> String+genericTakeExtension = snd . genericSplitExtension++genericTakeExtensions :: (Class.FileDir fd) => Path os ar fd -> String+genericTakeExtensions = snd . genericSplitExtension++newtype+ SplitExtension path =+ SplitExtension {runSplitExtension :: path -> (path, String)}+++-- move to utility-ht+mapLast :: (a -> a) -> [a] -> [a]+mapLast f xs = zipWith id (drop 1 $ map (const id) xs ++ [f]) xs++mapLastPair :: b -> (a -> (a,b)) -> [a] -> ([a], b)+mapLastPair b f =+ ListHT.switchR ([], b) (\as a -> mapFst ((as++) . (:[])) $ f a)++mapLastPairFoldr :: b -> (a -> (a,b)) -> [a] -> ([a], b)+mapLastPairFoldr b _ [] = ([], b)+mapLastPairFoldr _ f (x:xs) =+ foldr+ (\y1 go y0 -> mapFst (y0:) $ go y1)+ (\y -> mapFst (:[]) $ f y)+ xs x++mapLastPairRec :: b -> (a -> (a,b)) -> [a] -> ([a], b)+mapLastPairRec b _ [] = ([], b)+mapLastPairRec _ f (x:xs) =+ let go y [] = mapFst (:[]) $ f y+ go y0 (y1:ys) = mapFst (y0:) $ go y1 ys+ in go x xs++mapLastPairRev :: b -> (a -> (a,b)) -> [a] -> ([a], b)+mapLastPairRev b0 f xs =+ case reverse xs of+ [] -> (xs, b0)+ y:ys ->+ let (a, b) = f y+ in (reverse ys ++ [a], b)++_prop_mapLastPair :: String -> Int -> [String] -> Bool+_prop_mapLastPair b n strs =+ let f = splitAt n+ in all (mapLastPair b f strs ==) $+ mapLastPairFoldr b f strs :+ mapLastPairRev b f strs :+ mapLastPairRec b f strs :+ []++++{- |+Check internal integrity of the path data structure.+-}+isValid ::+ (System os, Class.AbsRel ar, Class.FileDir fd) =>+ Path os ar fd -> Bool+isValid = untag isValidTagged++isValidTagged ::+ (System os, Class.AbsRel ar, Class.FileDir fd) =>+ Tagged os (Path os ar fd -> Bool)+isValidTagged =+ fmap+ (\isValidPC (Path ar pcs fd) ->+ Class.withAbsRel isValidComponent True ar+ &&+ all isValidPC pcs+ &&+ Class.withFileDir (isValidPC . PC.retag) True True fd)+ isValidPathComponent++isValidComponent :: String -> Bool+isValidComponent = not . null++isValidPathComponent ::+ (System os) => Tagged os (Component os -> Bool)+isValidPathComponent =+ fmap+ (\isSep (Component str) ->+ isValidComponent str && not (any isSep str))+ isPathSeparator++------------------------------------------------------------------------+-- QuickCheck++testAll :: (System os) => os -> [(String, DocTest.T ())]+testAll os =+ ("mkPathFromComponents_pathComponents",+ quickCheck os prop_mkPathFromComponents_pathComponents) :+ ("splitDir_combine",+ quickCheck os prop_splitDir_combine) :+ ("takeDirName_end",+ quickCheck os prop_takeDirName_end) :+ []++quickCheck ::+ (QC.Testable prop, System os, Class.FileDir fd, Class.AbsRel ar) =>+ os -> (Path os ar fd -> prop) -> DocTest.T ()+quickCheck _ = DocTest.property++-- test :: Testable a => a -> IO ()+-- test = quickCheck++qcFileComponent :: Gen (Component os)+qcFileComponent = Component <$> frequency [+ (1, return "someFile"),+ (1, return "fileWith.ext"),+ (1, return "file.with.multiple.exts"),+ (1, return "file with spcs")+ ]++qcDirComponent :: Gen (Component os)+qcDirComponent = Component <$> frequency [+ (1, return "someDir"),+ (1, return "aDir"),+ (1, return "aFolder"),+ (1, return "a folder"),+ (1, return "directory")+ ]+++qcAbsRel :: (System os, Class.AbsRel ar) => Tagged os (Gen ar)+qcAbsRel =+ flip fmap genDrive $ \drive ->+ Class.switchAbsRel (fmap absPC drive) (return Part.Rel)+ (QC.oneof+ [fmap (Part.AbsO . Component) drive, return Part.RelO])++qcGenPath ::+ Tagged os (Gen ar) ->+ (Gen ar -> Gen (Path os ar fd)) ->+ Gen (Path os ar fd)+qcGenPath qcAR gen = gen $ untag qcAR++qcFilePath :: (System os, Class.AbsRel ar) => Gen (FilePath os ar)+qcFilePath = qcGenPath qcAbsRel $ \qcAR -> do+ ar <- qcAR+ pcs <- QC.listOf qcDirComponent+ pc <- qcFileComponent+ return $ Path ar pcs $ Part.File pc++qcDirPath :: (System os, Class.AbsRel ar) => fd -> Gen (Path os ar fd)+qcDirPath fd = qcGenPath qcAbsRel $ \qcAR -> do+ ar <- qcAR+ pcs <- QC.listOf qcDirComponent+ return $ Path ar pcs fd++qcPath ::+ (System os, Class.AbsRel ar, Class.FileDir fd) => Gen (Path os ar fd)+qcPath =+ switchFileDir qcFilePath (qcDirPath Part.Dir) (qcDirPath Part.FileDir)++instance+ (System os, Class.AbsRel ar, Class.FileDir fd) =>+ Arbitrary (Path os ar fd) where arbitrary = qcPath
+ src/System/Path/Internal/Component.hs view
@@ -0,0 +1,88 @@+module System.Path.Internal.Component where++import qualified System.Path.Internal.Separator as Sep+import System.Path.Internal.System (System, canonicalize)++import Control.DeepSeq (NFData(rnf))+import Control.Applicative ((<$>))++import qualified Data.List.HT as ListHT+import Data.Tagged (Tagged(Tagged))+import Data.List (isPrefixOf)+import Data.Maybe.HT (toMaybe)+import Data.Tuple.HT (mapFst)+import Data.Ord.HT (comparing)+import Data.Eq.HT (equating)++import Prelude hiding (map)+++newtype Component os = Component String++empty :: Component os+empty = Component ""++instance NFData (Component os) where+ rnf (Component pc) = rnf pc++instance (System os) => Eq (Component os) where+ (==) = equating (applyComp canonicalize)++instance (System os) => Ord (Component os) where+ compare = comparing (applyComp canonicalize)++applyComp :: Tagged os (String -> String) -> Component os -> String+applyComp (Tagged canon) (Component pc) = canon pc++retag :: GenComponent -> Component os+retag (Component pc) = Component pc++untag :: Component os -> GenComponent+untag (Component pc) = Component pc+++map :: (String -> String) -> Component os -> Component os+map f (Component s) = Component $ f s++mapF ::+ (Functor f) =>+ (String -> f String) -> Component os -> f (Component os)+mapF f (Component s) = Component <$> f s++++addExtension :: Component os -> String -> Component os+addExtension p "" = p+addExtension (Component pc) ext =+ Component $ pc +++ if [Sep.extension] `isPrefixOf` ext+ then ext+ else Sep.extension : ext++splitExtension :: Component os -> (Component os, String)+splitExtension (Component s) =+ mapFst Component $+ maybe (s, "") (mapFst concat) $+ ((\p@(pcs,_) -> toMaybe (not (null pcs)) p) =<<) $ ListHT.viewR $+ ListHT.segmentBefore Sep.isExtension s++_splitExtension :: Component os -> (Component os, String)+_splitExtension (Component s) =+ mapFst Component $+ case break Sep.isExtension $ reverse s of+ (_, "") -> (s, "")+ (rext, dot:rstem) -> (reverse rstem, dot : reverse rext)++splitExtensions :: Component os -> (Component os, String)+splitExtensions (Component s) =+ mapFst Component $ break Sep.isExtension s++++data Generic = Generic++{- |+We cannot have a Component without phantom types plus a Tagged wrapper,+because we need specialised Eq and Ord instances.+-}+type GenComponent = Component Generic
+ src/System/Path/Internal/Part.hs view
@@ -0,0 +1,43 @@+module System.Path.Internal.Part where++import qualified System.Path.Internal.Component as PC+import System.Path.Internal.Component+ (Component(Component), GenComponent)++import Control.DeepSeq (NFData(rnf))+++newtype Abs = Abs GenComponent+data Rel = Rel+data AbsRel = AbsO GenComponent | RelO++absPC :: String -> Abs+absPC = Abs . Component++newtype File = File GenComponent+data Dir = Dir+data FileDir = FileDir+++instance NFData Abs where+ rnf (Abs drive) = rnf drive++instance NFData Rel where+ rnf Rel = ()++instance NFData AbsRel where+ rnf (AbsO drive) = rnf drive+ rnf RelO = ()++instance NFData File where+ rnf (File pc) = rnf pc++instance NFData Dir where+ rnf Dir = ()++instance NFData FileDir where+ rnf FileDir = ()+++fileMap :: (String -> String) -> File -> File+fileMap f (File pc) = File $ PC.map f pc
+ src/System/Path/Internal/PartClass.hs view
@@ -0,0 +1,160 @@+module System.Path.Internal.PartClass where++import qualified System.Path.Internal.Component as PC+import qualified System.Path.Internal.Part as Part+import System.Path.Internal.System (System(..))+import System.Path.Internal.Component+ (Component(Component), GenComponent)++import Data.Monoid (Endo(Endo), appEndo)+import Data.Ord.HT (comparing)+import Data.Eq.HT (equating)++++------------------------------------------------------------------------+-- Type classes and machinery for switching on Part.Abs/Part.Rel and Part.File/Part.Dir++-- | This class provides a way to prevent other modules+-- from making further 'AbsOrRel' or 'FileOrDir'+-- instances+class Private p+instance Private Part.Abs+instance Private Part.Rel+instance Private Part.AbsRel+instance Private Part.File+instance Private Part.Dir+instance Private Part.FileDir+++-- | This class allows selective behaviour for absolute and+-- relative paths and is mostly for internal use.+class Private ar => AbsRel ar where+ {- |+ See <https://wiki.haskell.org/Closed_world_instances>+ for the used technique.+ -}+ switchAbsRel :: f Part.Abs -> f Part.Rel -> f Part.AbsRel -> f ar++instance AbsRel Part.Abs where switchAbsRel f _ _ = f+instance AbsRel Part.Rel where switchAbsRel _ f _ = f+instance AbsRel Part.AbsRel where switchAbsRel _ _ f = f++class AbsRel ar => AbsOrRel ar where+ switchAbsOrRel :: f Part.Abs -> f Part.Rel -> f ar++instance AbsOrRel Part.Abs where switchAbsOrRel f _ = f+instance AbsOrRel Part.Rel where switchAbsOrRel _ f = f+++class AbsOrRel ar => Abs ar where switchAbs :: f Part.Abs -> f ar+instance Abs Part.Abs where switchAbs = id++class AbsOrRel ar => Rel ar where switchRel :: f Part.Rel -> f ar+instance Rel Part.Rel where switchRel = id++relVar :: Rel ar => ar+relVar = unwrapAbsRel $ switchRel $ WrapAbsRel Part.Rel+++-- | This class allows selective behaviour for file and+-- directory paths and is mostly for internal use.+class Private fd => FileDir fd where+ switchFileDir :: f Part.File -> f Part.Dir -> f Part.FileDir -> f fd++instance FileDir Part.File where switchFileDir f _ _ = f+instance FileDir Part.Dir where switchFileDir _ f _ = f+instance FileDir Part.FileDir where switchFileDir _ _ f = f++class FileDir fd => FileOrDir fd where+ switchFileOrDir :: f Part.File -> f Part.Dir -> f fd++instance FileOrDir Part.File where switchFileOrDir f _ = f+instance FileOrDir Part.Dir where switchFileOrDir _ f = f+++class FileOrDir fd => File fd where switchFile :: f Part.File -> f fd+instance File Part.File where switchFile = id++class FileOrDir fd => Dir fd where switchDir :: f Part.Dir -> f fd+instance Dir Part.Dir where switchDir = id++dirVar :: Dir fd => fd+dirVar = unwrapFileDir $ switchDir $ WrapFileDir Part.Dir+++newtype FuncArg b a = FuncArg {runFuncArg :: a -> b}++withAbsRel :: (AbsRel ar) => (String -> a) -> a -> ar -> a+withAbsRel fAbs fRel =+ runFuncArg $+ switchAbsRel+ (FuncArg $ \(Part.Abs (Component drive)) -> fAbs drive)+ (FuncArg $ \Part.Rel -> fRel)+ (FuncArg $ \ar ->+ case ar of+ Part.AbsO (Component drive) -> fAbs drive+ Part.RelO -> fRel)++withFileDir :: (FileDir fd) => (GenComponent -> a) -> a -> a -> fd -> a+withFileDir fFile fDir fFileOrDir =+ runFuncArg $+ switchFileDir (FuncArg $ \(Part.File pc) -> fFile pc)+ (FuncArg $ \Part.Dir -> fDir) (FuncArg $ \Part.FileDir -> fFileOrDir)++withFileOrDir :: (FileOrDir fd) => (GenComponent -> a) -> a -> fd -> a+withFileOrDir fFile fDir =+ runFuncArg $+ switchFileOrDir+ (FuncArg $ \(Part.File pc) -> fFile pc)+ (FuncArg $ \Part.Dir -> fDir)++++isAbsolute :: (AbsRel ar) => ar -> Bool+isAbsolute = withAbsRel (const True) False++toAbsRel :: AbsRel ar => ar -> Part.AbsRel+toAbsRel =+ runFuncArg $+ switchAbsRel+ (FuncArg $ \(Part.Abs drive) -> Part.AbsO drive)+ (FuncArg $ \Part.Rel -> Part.RelO)+ (FuncArg id)++fromAbsRel :: AbsRel ar => Part.AbsRel -> Maybe ar+fromAbsRel ar =+ case ar of+ Part.AbsO pc -> switchAbsRel (Just $ Part.Abs pc) Nothing (Just ar)+ Part.RelO -> switchAbsRel Nothing (Just Part.Rel) (Just ar)++fdMap :: (FileDir fd) => (String -> String) -> fd -> fd+fdMap f = appEndo $ switchFileDir (Endo $ Part.fileMap f) (Endo id) (Endo id)+++newtype WrapAbsRel os ar = WrapAbsRel {unwrapAbsRel :: ar}++inspectAbsRel ::+ (AbsRel ar) => WrapAbsRel os ar -> Either (Component os) ()+inspectAbsRel =+ withAbsRel (Left . Component) (Right ()) . unwrapAbsRel++instance (System os, AbsRel ar) => Eq (WrapAbsRel os ar) where+ (==) = equating inspectAbsRel++instance (System os, AbsRel ar) => Ord (WrapAbsRel os ar) where+ compare = comparing inspectAbsRel+++newtype WrapFileDir os fd = WrapFileDir {unwrapFileDir :: fd}++inspectFileDir ::+ (FileDir ar) => WrapFileDir os ar -> Either (Component os) ()+inspectFileDir =+ withFileDir (Left . PC.retag) (Right ()) (Right ()) . unwrapFileDir++instance (System os, FileDir fd) => Eq (WrapFileDir os fd) where+ (==) = equating inspectFileDir++instance (System os, FileDir fd) => Ord (WrapFileDir os fd) where+ compare = comparing inspectFileDir
+ src/System/Path/Internal/Separator.hs view
@@ -0,0 +1,14 @@+module System.Path.Internal.Separator where+++extension :: Char+extension = '.'++searchPath :: Char+searchPath = ':'++isExtension :: Char -> Bool+isExtension = (== extension)++isSearchPath :: Char -> Bool+isSearchPath = (== searchPath)
+ src/System/Path/Internal/System.hs view
@@ -0,0 +1,37 @@+module System.Path.Internal.System where++import qualified Control.Monad.Trans.State as MS+import Control.Applicative ((<$>))++import Data.Tagged (Tagged)++import Test.QuickCheck (Gen)++++class System os where+ -- | The character that separates directories. In the case where more than+ -- one character is possible, 'pathSeparator' is the \'ideal\' one.+ --+ -- >> Posix.isPathSeparator Posix.pathSeparator+ pathSeparator :: Tagged os Char++ -- | The list of all possible separators.+ --+ -- >> Posix.pathSeparator `elem` Posix.pathSeparators+ pathSeparators :: Tagged os [Char]+ pathSeparators = (:[]) <$> pathSeparator++ -- | Rather than using @(== 'pathSeparator')@, use this. Test if something+ -- is a path separator.+ --+ -- >> Posix.isPathSeparator a == (a `elem` Posix.pathSeparators)+ isPathSeparator :: Tagged os (Char -> Bool)+ isPathSeparator = flip elem <$> pathSeparators++ splitAbsolute :: Tagged os (MS.State String String)++ canonicalize :: Tagged os (String -> String)++ splitDrive :: Tagged os (MS.State String String)+ genDrive :: Tagged os (Gen String)
+ src/System/Path/Part.hs view
@@ -0,0 +1,11 @@+module System.Path.Part (+ -- * Possible types for Path type parameters+ Abs,+ Rel,+ AbsRel,+ File,+ Dir,+ FileDir,+ ) where++import System.Path.Internal.Part
+ src/System/Path/PartClass.hs view
@@ -0,0 +1,6 @@+module System.Path.PartClass (+ AbsRel(..), AbsOrRel(..),+ FileDir(..), FileOrDir(..),+ ) where++import System.Path.Internal.PartClass
src/System/Path/Posix.hs view
@@ -1,8 +1,4 @@-{-# LANGUAGE EmptyDataDecls #-}-{-# LANGUAGE CPP #-}-#define MODULE_NAME Posix-#define IS_WINDOWS False-+{-# OPTIONS_GHC -fno-warn-warnings-deprecations #-} -- | This module provides type-safe access to filepath manipulations. -- -- Normally you would import 'System.Path' (which will use the@@ -10,9 +6,240 @@ -- However, importing this explicitly allows for manipulation of -- non-native paths. ---#ifdef __HADDOCK__-module System.Path.Posix where-#else-#include "Internal.hs"-#endif+module System.Path.Posix (+ Path,+ AbsFile, RelFile, AbsDir, RelDir,+ Abs, Rel, File, Dir,+ AbsRelFile, AbsRelDir, AbsFileDir, RelFileDir,+ AbsRel, FileDir, AbsRelFileDir,+ AbsPath, RelPath, FilePath, DirPath,+ AbsRelPath, FileDirPath,+ asPath,+ asRelFile, asRelDir, asAbsFile, asAbsDir,+ asRelPath, asAbsPath, asFilePath, asDirPath,+ path, maybe, maybePath, parse, parsePath,+ relFile, relDir, absFile, absDir,+ abs, rel, absRel, file, dir, fileDir,+ relPath, absPath, filePath, dirPath,+ rootDir, currentDir, emptyFile,+ toString,+ isAbsoluteString, isRelativeString, equalFilePath,+ pathSeparator, pathSeparators, isPathSeparator,+ Core.extSeparator, Core.isExtSeparator,+ Core.searchPathSeparator, Core.isSearchPathSeparator,+ addTrailingPathSeparator, dropTrailingPathSeparator,+ hasTrailingPathSeparator,+ testAll,+ ) where +import qualified System.Path.RegularExpression as RegEx+import qualified System.Path.Internal.PartClass as Class+import qualified System.Path.Internal as Core++import Data.Tagged (Tagged(Tagged), untag)++import qualified Test.DocTest.Driver as DocTest++import Prelude hiding (FilePath, maybe, abs)+++data Posix = Posix++_osDummy :: Posix+_osDummy = Posix++type System = Posix++type Path = Core.Path System++type AbsFile = Core.AbsFile System+type RelFile = Core.RelFile System+type AbsDir = Core.AbsDir System+type RelDir = Core.RelDir System+type AbsRelFile = Core.AbsRelFile System+type AbsRelDir = Core.AbsRelDir System+type AbsFileDir = Core.AbsFileDir System+type RelFileDir = Core.RelFileDir System+type AbsRelFileDir = Core.AbsRelFileDir System++type Abs fd = Core.Abs System fd+type Rel fd = Core.Rel System fd+type File ar = Core.File System ar+type Dir ar = Core.Dir System ar+type AbsRel fd = Core.AbsRel System fd+type FileDir ar = Core.FileDir System ar++type AbsPath fd = Core.AbsPath System fd+type RelPath fd = Core.RelPath System fd+type FilePath ar = Core.FilePath System ar+type DirPath ar = Core.DirPath System ar+type AbsRelPath fd = Core.AbsRelPath System fd+type FileDirPath ar = Core.FileDirPath System ar++{-# DEPRECATED asPath "Use 'maybePath', 'parsePath' or 'path' instead." #-}+asPath :: (Class.AbsOrRel ar, Class.FileOrDir fd) => String -> Path ar fd+asPath = Core.asPath++{-# DEPRECATED asRelFile "Use 'relFile' instead." #-}+asRelFile :: String -> RelFile+asRelFile = Core.asRelFile++{-# DEPRECATED asRelDir "Use 'relDir' instead." #-}+asRelDir :: String -> RelDir+asRelDir = Core.asRelDir++{-# DEPRECATED asAbsFile "Use 'absFile' instead." #-}+asAbsFile :: String -> AbsFile+asAbsFile = Core.asAbsFile++{-# DEPRECATED asAbsDir "Use 'absDir' instead." #-}+asAbsDir :: String -> AbsDir+asAbsDir = Core.asAbsDir++{-# DEPRECATED asRelPath "Use 'relPath' instead." #-}+asRelPath :: (Class.FileOrDir fd) => String -> RelPath fd+asRelPath = Core.asRelPath++{-# DEPRECATED asAbsPath "Use 'absPath' instead." #-}+asAbsPath :: (Class.FileOrDir fd) => String -> AbsPath fd+asAbsPath = Core.asAbsPath++{-# DEPRECATED asFilePath "Use 'filePath' instead." #-}+asFilePath :: (Class.AbsOrRel ar) => String -> FilePath ar+asFilePath = Core.asFilePath++{-# DEPRECATED asDirPath "Use 'dirPath' instead." #-}+asDirPath :: (Class.AbsOrRel ar) => String -> DirPath ar+asDirPath = Core.asDirPath+++{-# DEPRECATED maybePath "Use Path.maybe instead." #-}+{-# DEPRECATED parsePath "Use Path.parse instead." #-}++maybe, maybePath ::+ (Class.AbsRel ar, Class.FileDir fd) => String -> Maybe (Path ar fd)+maybe = Core.maybe+maybePath = Core.maybe++parse, parsePath ::+ (Class.AbsRel ar, Class.FileDir fd) => String -> Either String (Path ar fd)+parse = Core.parse+parsePath = Core.parse+++path :: (Class.AbsRel ar, Class.FileDir fd) => String -> Path ar fd+path = Core.path++relFile :: String -> RelFile+relFile = Core.relFile++relDir :: String -> RelDir+relDir = Core.relDir++absFile :: String -> AbsFile+absFile = Core.absFile++absDir :: String -> AbsDir+absDir = Core.absDir+++rel :: (Class.FileDir fd) => String -> Rel fd+rel = Core.rel++abs :: (Class.FileDir fd) => String -> Abs fd+abs = Core.abs++absRel :: (Class.FileDir fd) => String -> AbsRel fd+absRel = Core.absRel++file :: (Class.AbsRel ar) => String -> File ar+file = Core.file++dir :: (Class.AbsRel ar) => String -> Dir ar+dir = Core.dir++fileDir :: (Class.AbsRel ar) => String -> FileDir ar+fileDir = Core.fileDir+++relPath :: (Class.FileDir fd) => String -> RelPath fd+relPath = Core.relPath++absPath :: (Class.FileDir fd) => String -> AbsPath fd+absPath = Core.absPath++filePath :: (Class.AbsRel ar) => String -> FilePath ar+filePath = Core.filePath++dirPath :: (Class.AbsRel ar) => String -> DirPath ar+dirPath = Core.dirPath+++rootDir :: AbsDir+rootDir = Core.rootDir++currentDir :: RelDir+currentDir = Core.currentDir++emptyFile :: RelFile+emptyFile = Core.emptyFile+++toString :: (Class.AbsRel ar, Class.FileDir fd) => Path ar fd -> String+toString = Core.toString+++instance Core.System Posix where+ pathSeparator = Tagged pathSeparator+ splitAbsolute = Tagged $ RegEx.run $ RegEx.single isPathSeparator+ canonicalize = Tagged id+ splitDrive = Tagged $ return ""+ genDrive = Tagged $ return ""++withOS :: Tagged System a -> a+withOS = untag+++{-# DEPRECATED equalFilePath "Use System.FilePath.equalFilePath instead." #-}+{-# DEPRECATED isAbsoluteString "Use System.FilePath.isAbsolute instead." #-}+{-# DEPRECATED isRelativeString "Use System.FilePath.isRelative instead." #-}++equalFilePath :: String -> String -> Bool+equalFilePath = withOS Core.equalFilePath++isAbsoluteString :: String -> Bool+isAbsoluteString = withOS Core.isAbsoluteString++isRelativeString :: String -> Bool+isRelativeString = withOS Core.isRelativeString+++pathSeparator :: Char+pathSeparator = '/'++pathSeparators :: [Char]+pathSeparators = withOS Core.pathSeparators++isPathSeparator :: Char -> Bool+isPathSeparator = withOS Core.isPathSeparator+++{-# DEPRECATED addTrailingPathSeparator "Use System.FilePath.addTrailingPathSeparator instead." #-}+{-# DEPRECATED dropTrailingPathSeparator "Use System.FilePath.dropTrailingPathSeparator instead." #-}+{-# DEPRECATED hasTrailingPathSeparator "Use System.FilePath.hasTrailingPathSeparator instead." #-}++-- | This is largely for 'System.FilePath' compatibility+addTrailingPathSeparator :: String -> String+addTrailingPathSeparator = (++[pathSeparator])++-- | This is largely for 'System.FilePath' compatibility+dropTrailingPathSeparator :: String -> String+dropTrailingPathSeparator = init++-- | This is largely for 'System.FilePath' compatibility+hasTrailingPathSeparator :: String -> Bool+hasTrailingPathSeparator = isPathSeparator . last+++testAll :: [(String, DocTest.T ())]+testAll = Core.testAll Posix
+ src/System/Path/RegularExpression.hs view
@@ -0,0 +1,34 @@+module System.Path.RegularExpression where++import qualified Control.Monad.Trans.State as MS+import Control.Monad (guard)+import Control.Applicative (liftA2, (<|>))++import qualified Data.List.HT as ListHT+import Data.Monoid (Monoid, mempty)+import Data.Semigroup (Semigroup, (<>))+import Data.Maybe (fromMaybe)+++newtype Parser a = Parser (MS.StateT [a] Maybe [a])++instance Semigroup (Parser a) where+ Parser x <> Parser y = Parser $ liftA2 (++) x y++instance Monoid (Parser a) where+ mempty = Parser $ return []++infixr 5 -|-++(-|-) :: Parser a -> Parser a -> Parser a+Parser x -|- Parser y = Parser $ x <|> y++single :: (a -> Bool) -> Parser a+single p = Parser $ do+ c <- MS.StateT ListHT.viewL+ guard $ p c+ return [c]++run :: Parser a -> MS.State [a] [a]+run (Parser x) =+ MS.state $ \str -> fromMaybe ([], str) $ MS.runStateT x str
src/System/Path/Windows.hs view
@@ -1,8 +1,4 @@-{-# LANGUAGE EmptyDataDecls #-}-{-# LANGUAGE CPP #-}-#define MODULE_NAME Windows-#define IS_WINDOWS True-+{-# OPTIONS_GHC -fno-warn-warnings-deprecations #-} -- | This module provides type-safe access to filepath manipulations. -- -- Normally you would import 'System.Path' (which will use the@@ -10,9 +6,250 @@ -- However, importing this explicitly allows for manipulation of -- non-native paths. ---#ifdef __HADDOCK__-module System.Path.Windows where-#else-#include "Internal.hs"-#endif+module System.Path.Windows (+ Path,+ AbsFile, RelFile, AbsDir, RelDir,+ Abs, Rel, File, Dir,+ AbsRelFile, AbsRelDir, AbsFileDir, RelFileDir,+ AbsRel, FileDir, AbsRelFileDir,+ AbsPath, RelPath, FilePath, DirPath,+ AbsRelPath, FileDirPath,+ asPath,+ asRelFile, asRelDir, asAbsFile, asAbsDir,+ asRelPath, asAbsPath, asFilePath, asDirPath,+ path, maybe, maybePath, parse, parsePath,+ relFile, relDir, absFile, absDir,+ abs, rel, absRel, file, dir, fileDir,+ relPath, absPath, filePath, dirPath,+ rootDir, currentDir, emptyFile,+ toString,+ isAbsoluteString, isRelativeString, equalFilePath,+ pathSeparator, pathSeparators, isPathSeparator,+ Core.extSeparator, Core.isExtSeparator,+ Core.searchPathSeparator, Core.isSearchPathSeparator,+ addTrailingPathSeparator, dropTrailingPathSeparator,+ hasTrailingPathSeparator,+ testAll,+ ) where +import qualified System.Path.RegularExpression as RegEx+import qualified System.Path.Internal.PartClass as Class+import qualified System.Path.Internal as Core+import System.Path.RegularExpression ((-|-))++import Data.Tagged (Tagged(Tagged), untag)+import Data.Char (isAlpha, toLower)+import Data.Monoid (mempty, (<>))++import qualified Test.DocTest.Driver as DocTest+import qualified Test.QuickCheck as QC++import Prelude hiding (FilePath, maybe, abs)+++data Windows = Windows++_osDummy :: Windows+_osDummy = Windows++type System = Windows++type Path = Core.Path System++type AbsFile = Core.AbsFile System+type RelFile = Core.RelFile System+type AbsDir = Core.AbsDir System+type RelDir = Core.RelDir System+type AbsRelFile = Core.AbsRelFile System+type AbsRelDir = Core.AbsRelDir System+type AbsFileDir = Core.AbsFileDir System+type RelFileDir = Core.RelFileDir System+type AbsRelFileDir = Core.AbsRelFileDir System++type Abs fd = Core.Abs System fd+type Rel fd = Core.Rel System fd+type File ar = Core.File System ar+type Dir ar = Core.Dir System ar+type AbsRel fd = Core.AbsRel System fd+type FileDir ar = Core.FileDir System ar++type AbsPath fd = Core.AbsPath System fd+type RelPath fd = Core.RelPath System fd+type FilePath ar = Core.FilePath System ar+type DirPath ar = Core.DirPath System ar+type AbsRelPath fd = Core.AbsRelPath System fd+type FileDirPath ar = Core.FileDirPath System ar++{-# DEPRECATED asPath "Use 'maybePath', 'parsePath' or 'path' instead." #-}+asPath :: (Class.AbsOrRel ar, Class.FileOrDir fd) => String -> Path ar fd+asPath = Core.asPath++{-# DEPRECATED asRelFile "Use 'relFile' instead." #-}+asRelFile :: String -> RelFile+asRelFile = Core.asRelFile++{-# DEPRECATED asRelDir "Use 'relDir' instead." #-}+asRelDir :: String -> RelDir+asRelDir = Core.asRelDir++{-# DEPRECATED asAbsFile "Use 'absFile' instead." #-}+asAbsFile :: String -> AbsFile+asAbsFile = Core.asAbsFile++{-# DEPRECATED asAbsDir "Use 'absDir' instead." #-}+asAbsDir :: String -> AbsDir+asAbsDir = Core.asAbsDir++{-# DEPRECATED asRelPath "Use 'relPath' instead." #-}+asRelPath :: (Class.FileOrDir fd) => String -> RelPath fd+asRelPath = Core.asRelPath++{-# DEPRECATED asAbsPath "Use 'absPath' instead." #-}+asAbsPath :: (Class.FileOrDir fd) => String -> AbsPath fd+asAbsPath = Core.asAbsPath++{-# DEPRECATED asFilePath "Use 'filePath' instead." #-}+asFilePath :: (Class.AbsOrRel ar) => String -> FilePath ar+asFilePath = Core.asFilePath++{-# DEPRECATED asDirPath "Use 'dirPath' instead." #-}+asDirPath :: (Class.AbsOrRel ar) => String -> DirPath ar+asDirPath = Core.asDirPath+++{-# DEPRECATED maybePath "Use Path.maybe instead." #-}+{-# DEPRECATED parsePath "Use Path.parse instead." #-}++maybe, maybePath ::+ (Class.AbsRel ar, Class.FileDir fd) => String -> Maybe (Path ar fd)+maybe = Core.maybe+maybePath = Core.maybe++parse, parsePath ::+ (Class.AbsRel ar, Class.FileDir fd) => String -> Either String (Path ar fd)+parse = Core.parse+parsePath = Core.parse+++path :: (Class.AbsRel ar, Class.FileDir fd) => String -> Path ar fd+path = Core.path++relFile :: String -> RelFile+relFile = Core.relFile++relDir :: String -> RelDir+relDir = Core.relDir++absFile :: String -> AbsFile+absFile = Core.absFile++absDir :: String -> AbsDir+absDir = Core.absDir+++rel :: (Class.FileDir fd) => String -> Rel fd+rel = Core.rel++abs :: (Class.FileDir fd) => String -> Abs fd+abs = Core.abs++absRel :: (Class.FileDir fd) => String -> AbsRel fd+absRel = Core.absRel++file :: (Class.AbsRel ar) => String -> File ar+file = Core.file++dir :: (Class.AbsRel ar) => String -> Dir ar+dir = Core.dir++fileDir :: (Class.AbsRel ar) => String -> FileDir ar+fileDir = Core.fileDir+++relPath :: (Class.FileDir fd) => String -> RelPath fd+relPath = Core.relPath++absPath :: (Class.FileDir fd) => String -> AbsPath fd+absPath = Core.absPath++filePath :: (Class.AbsRel ar) => String -> FilePath ar+filePath = Core.filePath++dirPath :: (Class.AbsRel ar) => String -> DirPath ar+dirPath = Core.dirPath+++rootDir :: AbsDir+rootDir = Core.rootDir++currentDir :: RelDir+currentDir = Core.currentDir++emptyFile :: RelFile+emptyFile = Core.emptyFile+++toString :: (Class.AbsRel ar, Class.FileDir fd) => Path ar fd -> String+toString = Core.toString+++instance Core.System Windows where+ pathSeparator = Tagged pathSeparator+ splitAbsolute = Tagged $ RegEx.run $+ RegEx.single isPathSeparator+ -|-+ driveRegEx <> (RegEx.single isPathSeparator -|- mempty)+ canonicalize = Tagged $ map toLower+ splitDrive = Tagged $ RegEx.run driveRegEx+ genDrive = Tagged $ fmap (:":") $ QC.choose ('a', 'z')++driveRegEx :: RegEx.Parser Char+driveRegEx = RegEx.single isAlpha <> RegEx.single (':'==)++withOS :: Tagged System a -> a+withOS = untag+++{-# DEPRECATED equalFilePath "Use System.FilePath.equalFilePath instead." #-}+{-# DEPRECATED isAbsoluteString "Use System.FilePath.isAbsolute instead." #-}+{-# DEPRECATED isRelativeString "Use System.FilePath.isRelative instead." #-}++equalFilePath :: String -> String -> Bool+equalFilePath = withOS Core.equalFilePath++isAbsoluteString :: String -> Bool+isAbsoluteString = withOS Core.isAbsoluteString++isRelativeString :: String -> Bool+isRelativeString = withOS Core.isRelativeString+++pathSeparator :: Char+pathSeparator = '\\'++pathSeparators :: [Char]+pathSeparators = withOS Core.pathSeparators++isPathSeparator :: Char -> Bool+isPathSeparator = withOS Core.isPathSeparator+++{-# DEPRECATED addTrailingPathSeparator "Use System.FilePath.addTrailingPathSeparator instead." #-}+{-# DEPRECATED dropTrailingPathSeparator "Use System.FilePath.dropTrailingPathSeparator instead." #-}+{-# DEPRECATED hasTrailingPathSeparator "Use System.FilePath.hasTrailingPathSeparator instead." #-}++-- | This is largely for 'System.FilePath' compatibility+addTrailingPathSeparator :: String -> String+addTrailingPathSeparator = (++[pathSeparator])++-- | This is largely for 'System.FilePath' compatibility+dropTrailingPathSeparator :: String -> String+dropTrailingPathSeparator = init++-- | This is largely for 'System.FilePath' compatibility+hasTrailingPathSeparator :: String -> Bool+hasTrailingPathSeparator = isPathSeparator . last+++testAll :: [(String, DocTest.T ())]+testAll = Core.testAll Windows
test/Test.hs view
@@ -1,29 +1,24 @@ module Main (main) where -import TestResult (results)+import qualified Test.Posix.System.Path.Internal as TestPosix+import qualified Test.Windows.System.Path.Internal as TestWindows -import System.Path (rootDir, asRelDir, asRelFile, (</>), (<.>))-import System.Random (newStdGen, random)-import System.Exit (exitFailure)-import Control.Monad (void)-import Text.Printf (printf)+import qualified Test.DocTest.Driver as DocTest +import qualified System.Path.Posix as Posix+import qualified System.Path.Windows as Windows -main :: IO ()-main = do- g <- newStdGen- let (a,_g') = random g- -- TODO - integrate with QuickCheck- x = rootDir </> asRelDir "tmp" </> asRelFile "someFile" <.> "ext" - let allResults = results a x- void $ printf "Running %d tests...\n" $ length allResults+main :: IO ()+main = DocTest.run $ do+ DocTest.printLine "\nPosix"+ TestPosix.test+ DocTest.printLine "\nWindows"+ TestWindows.test - let fails = map fst $ filter (not . snd) allResults- if null fails- then do- putStrLn "Passed."- else do- putStrLn "Failed tests:"- mapM_ putStrLn fails- exitFailure+ DocTest.printLine "\nTests of internal functions"+ let runQC prefix =+ mapM_ $ \(name, test) ->+ DocTest.printPrefix (prefix ++ name ++ ": ") >> test+ runQC "Posix." Posix.testAll+ runQC "Windows." Windows.testAll
+ test/Test/Posix/System/Path/Internal.hs view
@@ -0,0 +1,1044 @@+-- Do not edit! Automatically created with doctest-extract from src/System/Path/Internal.hs+{-# LINE 199 "src/System/Path/Internal.hs" #-}++{-# OPTIONS_GHC -fno-warn-warnings-deprecations #-}+module Test.Posix.System.Path.Internal where++import qualified System.Path.Posix as Default+import Test.DocTest.Base+import qualified Test.DocTest.Driver as DocTest++{-# LINE 201 "src/System/Path/Internal.hs" #-}+import qualified System.Path.PartClass as Class+import qualified System.Path.Generic as Path+import qualified System.Path.Posix as Posix+import qualified System.Path.Windows as Windows+import System.Path.Generic ((</>), (<.>), relFile, relDir, absFile, absDir)+import Data.List (isSuffixOf, isPrefixOf)+import Data.Char (toLower)+import qualified Test.QuickCheck as QC+forAllAbsRel :: (Class.FileDir fd, QC.Testable prop) => (Default.AbsRel fd -> prop) -> QC.Property+forAllAbsRel = QC.forAll QC.arbitrary++test :: DocTest.T ()+test = do+ DocTest.printPrefix "System.Path.Internal:281: "+{-# LINE 281 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 281 "src/System/Path/Internal.hs" #-}+ Path.pathMap (map toLower) (absDir "/tmp/Reports/SpreadSheets") == Posix.absDir "/tmp/reports/spreadsheets"+ )+ DocTest.printPrefix "System.Path.Internal:354: "+{-# LINE 354 "src/System/Path/Internal.hs" #-}+ DocTest.example(+{-# LINE 354 "src/System/Path/Internal.hs" #-}+ Posix.rootDir </> relDir "bla" </> relFile "blub"+ )+ [ExpectedLine [LineChunk "rootDir </> relPath \"bla\" </> relPath \"blub\""]]+ DocTest.printPrefix "System.Path.Internal:356: "+{-# LINE 356 "src/System/Path/Internal.hs" #-}+ DocTest.example(+{-# LINE 356 "src/System/Path/Internal.hs" #-}+ Just (Posix.rootDir </> relDir "bla" </> relFile "blub")+ )+ [ExpectedLine [LineChunk "Just (rootDir </> relPath \"bla\" </> relPath \"blub\")"]]+ DocTest.printPrefix "System.Path.Internal:358: "+{-# LINE 358 "src/System/Path/Internal.hs" #-}+ DocTest.example(+{-# LINE 358 "src/System/Path/Internal.hs" #-}+ Posix.currentDir </> relDir "bla" </> relFile "blub"+ )+ [ExpectedLine [LineChunk "currentDir </> relPath \"bla\" </> relPath \"blub\""]]+ DocTest.printPrefix "System.Path.Internal:360: "+{-# LINE 360 "src/System/Path/Internal.hs" #-}+ DocTest.example(+{-# LINE 360 "src/System/Path/Internal.hs" #-}+ Just (Posix.currentDir </> relDir "bla" </> relFile "blub")+ )+ [ExpectedLine [LineChunk "Just (currentDir </> relPath \"bla\" </> relPath \"blub\")"]]+ DocTest.printPrefix "System.Path.Internal:362: "+{-# LINE 362 "src/System/Path/Internal.hs" #-}+ DocTest.example(+{-# LINE 362 "src/System/Path/Internal.hs" #-}+ Windows.absDir "c:" </> relDir "bla" </> relFile "blub"+ )+ [ExpectedLine [LineChunk "absDir \"c:\" </> relPath \"bla\" </> relPath \"blub\""]]+ DocTest.printPrefix "System.Path.Internal:364: "+{-# LINE 364 "src/System/Path/Internal.hs" #-}+ DocTest.example(+{-# LINE 364 "src/System/Path/Internal.hs" #-}+ Just (Windows.absDir "c:\\" </> relDir "bla" </> relFile "blub")+ )+ [ExpectedLine [LineChunk "Just (absDir \"c:\\\\\" </> relPath \"bla\" </> relPath \"blub\")"]]+ DocTest.printPrefix "System.Path.Internal:476: "+{-# LINE 476 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 476 "src/System/Path/Internal.hs" #-}+ \p -> Path.asPath (Path.toString p) == (p::Default.AbsFile)+ )+ DocTest.printPrefix "System.Path.Internal:558: "+{-# LINE 558 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 558 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "/" :: Maybe Posix.AbsDir) == Just "/"+ )+ DocTest.printPrefix "System.Path.Internal:559: "+{-# LINE 559 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 559 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "/" :: Maybe Posix.AbsFile) == Nothing+ )+ DocTest.printPrefix "System.Path.Internal:560: "+{-# LINE 560 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 560 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "/" :: Maybe Posix.RelDir) == Nothing+ )+ DocTest.printPrefix "System.Path.Internal:561: "+{-# LINE 561 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 561 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "/" :: Maybe Posix.RelFile) == Nothing+ )+ DocTest.printPrefix "System.Path.Internal:562: "+{-# LINE 562 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 562 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "/tmp" :: Maybe Posix.AbsDir) == Just "/tmp"+ )+ DocTest.printPrefix "System.Path.Internal:563: "+{-# LINE 563 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 563 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "/tmp" :: Maybe Posix.AbsFile) == Just "/tmp"+ )+ DocTest.printPrefix "System.Path.Internal:564: "+{-# LINE 564 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 564 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "/tmp" :: Maybe Posix.RelDir) == Nothing+ )+ DocTest.printPrefix "System.Path.Internal:565: "+{-# LINE 565 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 565 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "/tmp" :: Maybe Posix.RelFile) == Nothing+ )+ DocTest.printPrefix "System.Path.Internal:566: "+{-# LINE 566 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 566 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "/tmp/" :: Maybe Posix.AbsDir) == Just "/tmp"+ )+ DocTest.printPrefix "System.Path.Internal:567: "+{-# LINE 567 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 567 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "/tmp/" :: Maybe Posix.AbsFile) == Nothing+ )+ DocTest.printPrefix "System.Path.Internal:568: "+{-# LINE 568 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 568 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "/tmp/" :: Maybe Posix.RelDir) == Nothing+ )+ DocTest.printPrefix "System.Path.Internal:569: "+{-# LINE 569 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 569 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "/tmp/" :: Maybe Posix.RelFile) == Nothing+ )+ DocTest.printPrefix "System.Path.Internal:570: "+{-# LINE 570 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 570 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "/tmp" :: Maybe Posix.AbsRelFileDir) == Just "/tmp"+ )+ DocTest.printPrefix "System.Path.Internal:571: "+{-# LINE 571 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 571 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "/tmp/" :: Maybe Posix.AbsRelFileDir) == Just "/tmp"+ )+ DocTest.printPrefix "System.Path.Internal:572: "+{-# LINE 572 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 572 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "file.txt" :: Maybe Posix.RelFile) == Just "file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:573: "+{-# LINE 573 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 573 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "file.txt" :: Maybe Posix.AbsFile) == Nothing+ )+ DocTest.printPrefix "System.Path.Internal:574: "+{-# LINE 574 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 574 "src/System/Path/Internal.hs" #-}+ fmap Windows.toString (Windows.maybePath "\\tmp" :: Maybe Windows.AbsDir) == Just "\\tmp"+ )+ DocTest.printPrefix "System.Path.Internal:575: "+{-# LINE 575 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 575 "src/System/Path/Internal.hs" #-}+ fmap Windows.toString (Windows.maybePath "a:\\tmp" :: Maybe Windows.AbsDir) == Just "a:\\tmp"+ )+ DocTest.printPrefix "System.Path.Internal:576: "+{-# LINE 576 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 576 "src/System/Path/Internal.hs" #-}+ fmap Windows.toString (Windows.maybePath "a:tmp" :: Maybe Windows.AbsDir) == Just "a:tmp"+ )+ DocTest.printPrefix "System.Path.Internal:577: "+{-# LINE 577 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 577 "src/System/Path/Internal.hs" #-}+ fmap Windows.toString (Windows.maybePath "a:\\" :: Maybe Windows.AbsDir) == Just "a:\\"+ )+ DocTest.printPrefix "System.Path.Internal:578: "+{-# LINE 578 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 578 "src/System/Path/Internal.hs" #-}+ fmap Windows.toString (Windows.maybePath "a:" :: Maybe Windows.AbsDir) == Just "a:"+ )+ DocTest.printPrefix "System.Path.Internal:579: "+{-# LINE 579 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 579 "src/System/Path/Internal.hs" #-}+ fmap Windows.toString (Windows.maybePath "tmp" :: Maybe Windows.RelDir) == Just "tmp"+ )+ DocTest.printPrefix "System.Path.Internal:580: "+{-# LINE 580 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 580 "src/System/Path/Internal.hs" #-}+ fmap Windows.toString (Windows.maybePath "\\tmp" :: Maybe Windows.RelDir) == Nothing+ )+ DocTest.printPrefix "System.Path.Internal:581: "+{-# LINE 581 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 581 "src/System/Path/Internal.hs" #-}+ fmap Windows.toString (Windows.maybePath "a:\\tmp" :: Maybe Windows.RelDir) == Nothing+ )+ DocTest.printPrefix "System.Path.Internal:582: "+{-# LINE 582 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 582 "src/System/Path/Internal.hs" #-}+ fmap Windows.toString (Windows.maybePath "a:tmp" :: Maybe Windows.RelDir) == Nothing+ )+ DocTest.printPrefix "System.Path.Internal:583: "+{-# LINE 583 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 583 "src/System/Path/Internal.hs" #-}+ fmap Windows.toString (Windows.maybePath "tmp" :: Maybe Windows.AbsDir) == Nothing+ )+ DocTest.printPrefix "System.Path.Internal:632: "+{-# LINE 632 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 632 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.relFile "file.txt") == "file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:633: "+{-# LINE 633 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 633 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.relFile "tmp") == "tmp"+ )+ DocTest.printPrefix "System.Path.Internal:639: "+{-# LINE 639 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 639 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.relDir ".") == "."+ )+ DocTest.printPrefix "System.Path.Internal:640: "+{-# LINE 640 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 640 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.relDir "file.txt") == "file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:641: "+{-# LINE 641 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 641 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.relDir "tmp") == "tmp"+ )+ DocTest.printPrefix "System.Path.Internal:647: "+{-# LINE 647 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 647 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.absFile "/file.txt") == "/file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:648: "+{-# LINE 648 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 648 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.absFile "/tmp") == "/tmp"+ )+ DocTest.printPrefix "System.Path.Internal:654: "+{-# LINE 654 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 654 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.absDir "/file.txt") == "/file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:655: "+{-# LINE 655 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 655 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.absDir "/tmp") == "/tmp"+ )+ DocTest.printPrefix "System.Path.Internal:750: "+{-# LINE 750 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 750 "src/System/Path/Internal.hs" #-}+ Posix.asPath "/tmp" == Posix.absDir "/tmp"+ )+ DocTest.printPrefix "System.Path.Internal:751: "+{-# LINE 751 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 751 "src/System/Path/Internal.hs" #-}+ Posix.asPath "file.txt" == Posix.relFile "file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:752: "+{-# LINE 752 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 752 "src/System/Path/Internal.hs" #-}+ Path.isAbsolute (Posix.asAbsDir "/tmp")+ )+ DocTest.printPrefix "System.Path.Internal:753: "+{-# LINE 753 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 753 "src/System/Path/Internal.hs" #-}+ Path.isRelative (Posix.asRelDir "/tmp")+ )+ DocTest.printPrefix "System.Path.Internal:754: "+{-# LINE 754 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 754 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.asPath "/tmp" :: Posix.AbsDir) == "/tmp"+ )+ DocTest.printPrefix "System.Path.Internal:755: "+{-# LINE 755 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 755 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.asPath "/tmp" :: Posix.RelDir) == "tmp"+ )+ DocTest.printPrefix "System.Path.Internal:756: "+{-# LINE 756 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 756 "src/System/Path/Internal.hs" #-}+ Windows.toString (Windows.asPath "\\tmp" :: Windows.AbsDir) == "\\tmp"+ )+ DocTest.printPrefix "System.Path.Internal:757: "+{-# LINE 757 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 757 "src/System/Path/Internal.hs" #-}+ Windows.toString (Windows.asPath "a:\\tmp" :: Windows.AbsDir) == "a:\\tmp"+ )+ DocTest.printPrefix "System.Path.Internal:758: "+{-# LINE 758 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 758 "src/System/Path/Internal.hs" #-}+ Windows.toString (Windows.asPath "a:tmp" :: Windows.AbsDir) == "a:tmp"+ )+ DocTest.printPrefix "System.Path.Internal:759: "+{-# LINE 759 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 759 "src/System/Path/Internal.hs" #-}+ Windows.toString (Windows.asPath "tmp" :: Windows.RelDir) == "tmp"+ )+ DocTest.printPrefix "System.Path.Internal:767: "+{-# LINE 767 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 767 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.asRelFile "file.txt") == "file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:768: "+{-# LINE 768 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 768 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.asRelFile "/file.txt") == "file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:769: "+{-# LINE 769 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 769 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.asRelFile "tmp") == "tmp"+ )+ DocTest.printPrefix "System.Path.Internal:770: "+{-# LINE 770 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 770 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.asRelFile "/tmp") == "tmp"+ )+ DocTest.printPrefix "System.Path.Internal:776: "+{-# LINE 776 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 776 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.asRelDir ".") == "."+ )+ DocTest.printPrefix "System.Path.Internal:777: "+{-# LINE 777 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 777 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.asRelDir "file.txt") == "file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:778: "+{-# LINE 778 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 778 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.asRelDir "/file.txt") == "file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:779: "+{-# LINE 779 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 779 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.asRelDir "tmp") == "tmp"+ )+ DocTest.printPrefix "System.Path.Internal:780: "+{-# LINE 780 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 780 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.asRelDir "/tmp") == "tmp"+ )+ DocTest.printPrefix "System.Path.Internal:786: "+{-# LINE 786 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 786 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.asAbsFile "/file.txt") == "/file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:787: "+{-# LINE 787 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 787 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.asAbsFile "/tmp") == "/tmp"+ )+ DocTest.printPrefix "System.Path.Internal:793: "+{-# LINE 793 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 793 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.asAbsDir "/file.txt") == "/file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:794: "+{-# LINE 794 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 794 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.asAbsDir "/tmp") == "/tmp"+ )+ DocTest.printPrefix "System.Path.Internal:833: "+{-# LINE 833 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 833 "src/System/Path/Internal.hs" #-}+ Path.mkPathAbsOrRel "/tmp" == Left (Posix.absDir "/tmp")+ )+ DocTest.printPrefix "System.Path.Internal:834: "+{-# LINE 834 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 834 "src/System/Path/Internal.hs" #-}+ Path.mkPathAbsOrRel "tmp" == Right (Posix.relDir "tmp")+ )+ DocTest.printPrefix "System.Path.Internal:835: "+{-# LINE 835 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 835 "src/System/Path/Internal.hs" #-}+ Path.mkPathAbsOrRel "\\tmp" == Left (Windows.absDir "\\tmp")+ )+ DocTest.printPrefix "System.Path.Internal:836: "+{-# LINE 836 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 836 "src/System/Path/Internal.hs" #-}+ Path.mkPathAbsOrRel "d:\\tmp" == Left (Windows.absDir "d:\\tmp")+ )+ DocTest.printPrefix "System.Path.Internal:837: "+{-# LINE 837 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 837 "src/System/Path/Internal.hs" #-}+ Path.mkPathAbsOrRel "d:tmp" == Left (Windows.absDir "d:tmp")+ )+ DocTest.printPrefix "System.Path.Internal:838: "+{-# LINE 838 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 838 "src/System/Path/Internal.hs" #-}+ Path.mkPathAbsOrRel "tmp" == Right (Windows.relDir "tmp")+ )+ DocTest.printPrefix "System.Path.Internal:867: "+{-# LINE 867 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 867 "src/System/Path/Internal.hs" #-}+ Path.mkAbsPath (absDir "/tmp") "foo.txt" == Posix.absFile "/tmp/foo.txt"+ )+ DocTest.printPrefix "System.Path.Internal:868: "+{-# LINE 868 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 868 "src/System/Path/Internal.hs" #-}+ Path.mkAbsPath (absDir "/tmp") "/etc/foo.txt" == Posix.absFile "/etc/foo.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1009: "+{-# LINE 1009 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1009 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.absDir "/tmp" </> Posix.relFile "file.txt") == "/tmp/file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1010: "+{-# LINE 1010 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1010 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.absDir "/tmp" </> Posix.relDir "dir" </> Posix.relFile "file.txt") == "/tmp/dir/file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1011: "+{-# LINE 1011 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1011 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.relDir "dir" </> Posix.relFile "file.txt") == "dir/file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1012: "+{-# LINE 1012 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1012 "src/System/Path/Internal.hs" #-}+ Windows.toString (Windows.absDir "\\tmp" </> Windows.relFile "file.txt") == "\\tmp\\file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1013: "+{-# LINE 1013 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1013 "src/System/Path/Internal.hs" #-}+ Windows.toString (Windows.absDir "c:\\tmp" </> Windows.relFile "file.txt") == "c:\\tmp\\file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1014: "+{-# LINE 1014 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1014 "src/System/Path/Internal.hs" #-}+ Windows.toString (Windows.absDir "c:tmp" </> Windows.relFile "file.txt") == "c:tmp\\file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1015: "+{-# LINE 1015 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1015 "src/System/Path/Internal.hs" #-}+ Windows.toString (Windows.absDir "c:\\" </> Windows.relDir "tmp" </> Windows.relFile "file.txt") == "c:\\tmp\\file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1016: "+{-# LINE 1016 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1016 "src/System/Path/Internal.hs" #-}+ Windows.toString (Windows.absDir "c:" </> Windows.relDir "tmp" </> Windows.relFile "file.txt") == "c:tmp\\file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1017: "+{-# LINE 1017 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1017 "src/System/Path/Internal.hs" #-}+ Windows.toString (Windows.relDir "dir" </> Windows.relFile "file.txt") == "dir\\file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1044: "+{-# LINE 1044 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1044 "src/System/Path/Internal.hs" #-}+ Path.addExtension (relFile "file.txt") "bib" == Posix.relFile "file.txt.bib"+ )+ DocTest.printPrefix "System.Path.Internal:1045: "+{-# LINE 1045 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1045 "src/System/Path/Internal.hs" #-}+ Path.addExtension (relFile "file.") ".bib" == Posix.relFile "file..bib"+ )+ DocTest.printPrefix "System.Path.Internal:1046: "+{-# LINE 1046 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1046 "src/System/Path/Internal.hs" #-}+ Path.addExtension (relFile "file") ".bib" == Posix.relFile "file.bib"+ )+ DocTest.printPrefix "System.Path.Internal:1047: "+{-# LINE 1047 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1047 "src/System/Path/Internal.hs" #-}+ Path.addExtension Path.emptyFile "bib" == Posix.relFile ".bib"+ )+ DocTest.printPrefix "System.Path.Internal:1048: "+{-# LINE 1048 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1048 "src/System/Path/Internal.hs" #-}+ Path.addExtension Path.emptyFile ".bib" == Posix.relFile ".bib"+ )+ DocTest.printPrefix "System.Path.Internal:1049: "+{-# LINE 1049 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1049 "src/System/Path/Internal.hs" #-}+ Path.takeFileName (Path.addExtension Path.emptyFile "ext") == Posix.relFile ".ext"+ )+ DocTest.printPrefix "System.Path.Internal:1056: "+{-# LINE 1056 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1056 "src/System/Path/Internal.hs" #-}+ \p -> Path.combine Path.currentDir p == (p::Default.RelDir)+ )+ DocTest.printPrefix "System.Path.Internal:1063: "+{-# LINE 1063 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1063 "src/System/Path/Internal.hs" #-}+ forAllAbsRel $ \x -> Path.dropExtension x == fst (Path.splitExtension x)+ )+ DocTest.printPrefix "System.Path.Internal:1069: "+{-# LINE 1069 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1069 "src/System/Path/Internal.hs" #-}+ forAllAbsRel $ \x -> not $ Path.hasAnExtension (Path.dropExtensions x)+ )+ DocTest.printPrefix "System.Path.Internal:1080: "+{-# LINE 1080 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1080 "src/System/Path/Internal.hs" #-}+ Path.replaceExtension (relFile "file.txt") ".bob" == Posix.relFile "file.bob"+ )+ DocTest.printPrefix "System.Path.Internal:1081: "+{-# LINE 1081 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1081 "src/System/Path/Internal.hs" #-}+ Path.replaceExtension (relFile "file.txt") "bob" == Posix.relFile "file.bob"+ )+ DocTest.printPrefix "System.Path.Internal:1082: "+{-# LINE 1082 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1082 "src/System/Path/Internal.hs" #-}+ Path.replaceExtension (relFile "file") ".bob" == Posix.relFile "file.bob"+ )+ DocTest.printPrefix "System.Path.Internal:1083: "+{-# LINE 1083 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1083 "src/System/Path/Internal.hs" #-}+ Path.replaceExtension (relFile "file.txt") "" == Posix.relFile "file"+ )+ DocTest.printPrefix "System.Path.Internal:1084: "+{-# LINE 1084 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1084 "src/System/Path/Internal.hs" #-}+ Path.replaceExtension (relFile "file.fred.bob") "txt" == Posix.relFile "file.fred.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1101: "+{-# LINE 1101 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1101 "src/System/Path/Internal.hs" #-}+ forAllAbsRel $ \x -> uncurry (<.>) (Path.splitExtension x) == x+ )+ DocTest.printPrefix "System.Path.Internal:1102: "+{-# LINE 1102 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1102 "src/System/Path/Internal.hs" #-}+ forAllAbsRel $ \x -> uncurry Path.addExtension (Path.splitExtension x) == x+ )+ DocTest.printPrefix "System.Path.Internal:1103: "+{-# LINE 1103 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1103 "src/System/Path/Internal.hs" #-}+ Path.splitExtension (relFile "file.txt") == (Posix.relFile "file",".txt")+ )+ DocTest.printPrefix "System.Path.Internal:1104: "+{-# LINE 1104 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1104 "src/System/Path/Internal.hs" #-}+ Path.splitExtension (relFile ".bashrc") == (Posix.emptyFile, ".bashrc")+ )+ DocTest.printPrefix "System.Path.Internal:1105: "+{-# LINE 1105 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1105 "src/System/Path/Internal.hs" #-}+ Path.splitExtension (relFile "file") == (Posix.relFile "file","")+ )+ DocTest.printPrefix "System.Path.Internal:1106: "+{-# LINE 1106 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1106 "src/System/Path/Internal.hs" #-}+ Path.splitExtension (relFile "file/file.txt") == (Posix.relFile "file/file",".txt")+ )+ DocTest.printPrefix "System.Path.Internal:1107: "+{-# LINE 1107 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1107 "src/System/Path/Internal.hs" #-}+ Path.splitExtension (relFile "file.txt/boris") == (Posix.relFile "file.txt/boris","")+ )+ DocTest.printPrefix "System.Path.Internal:1108: "+{-# LINE 1108 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1108 "src/System/Path/Internal.hs" #-}+ Path.splitExtension (relFile "file.txt/boris.ext") == (Posix.relFile "file.txt/boris",".ext")+ )+ DocTest.printPrefix "System.Path.Internal:1109: "+{-# LINE 1109 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1109 "src/System/Path/Internal.hs" #-}+ Path.splitExtension (relFile "file/path.txt.bob.fred") == (Posix.relFile "file/path.txt.bob",".fred")+ )+ DocTest.printPrefix "System.Path.Internal:1115: "+{-# LINE 1115 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1115 "src/System/Path/Internal.hs" #-}+ Path.splitExtensions (relFile "file.tar.gz") == (Posix.relFile "file",".tar.gz")+ )+ DocTest.printPrefix "System.Path.Internal:1116: "+{-# LINE 1116 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1116 "src/System/Path/Internal.hs" #-}+ \p -> uncurry (<.>) (Path.splitExtension p) == (p::Default.AbsFile)+ )+ DocTest.printPrefix "System.Path.Internal:1120: "+{-# LINE 1120 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1120 "src/System/Path/Internal.hs" #-}+ \p -> uncurry Path.combine (Path.splitFileName p) == (p::Default.AbsFile)+ )+ DocTest.printPrefix "System.Path.Internal:1136: "+{-# LINE 1136 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1136 "src/System/Path/Internal.hs" #-}+ Path.takeBaseName (absFile "/tmp/somedir/myfile.txt") == Posix.relFile "myfile"+ )+ DocTest.printPrefix "System.Path.Internal:1137: "+{-# LINE 1137 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1137 "src/System/Path/Internal.hs" #-}+ Path.takeBaseName (relFile "./myfile.txt") == Posix.relFile "myfile"+ )+ DocTest.printPrefix "System.Path.Internal:1138: "+{-# LINE 1138 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1138 "src/System/Path/Internal.hs" #-}+ Path.takeBaseName (relFile "myfile.txt") == Posix.relFile "myfile"+ )+ DocTest.printPrefix "System.Path.Internal:1157: "+{-# LINE 1157 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1157 "src/System/Path/Internal.hs" #-}+ forAllAbsRel $ \x -> Path.takeExtension x == snd (Path.splitExtension x)+ )+ DocTest.printPrefix "System.Path.Internal:1158: "+{-# LINE 1158 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1158 "src/System/Path/Internal.hs" #-}+ forAllAbsRel $ \x -> Path.takeExtension (Path.addExtension x "ext") == ".ext"+ )+ DocTest.printPrefix "System.Path.Internal:1159: "+{-# LINE 1159 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1159 "src/System/Path/Internal.hs" #-}+ forAllAbsRel $ \x -> Path.takeExtension (Path.replaceExtension x "ext") == ".ext"+ )+ DocTest.printPrefix "System.Path.Internal:1165: "+{-# LINE 1165 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1165 "src/System/Path/Internal.hs" #-}+ Path.takeExtensions (Posix.relFile "file.tar.gz") == ".tar.gz"+ )+ DocTest.printPrefix "System.Path.Internal:1171: "+{-# LINE 1171 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1171 "src/System/Path/Internal.hs" #-}+ Path.takeFileName (absFile "/tmp/somedir/myfile.txt") == Posix.relFile "myfile.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1172: "+{-# LINE 1172 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1172 "src/System/Path/Internal.hs" #-}+ Path.takeFileName (relFile "./myfile.txt") == Posix.relFile "myfile.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1173: "+{-# LINE 1173 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1173 "src/System/Path/Internal.hs" #-}+ Path.takeFileName (relFile "myfile.txt") == Posix.relFile "myfile.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1174: "+{-# LINE 1174 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1174 "src/System/Path/Internal.hs" #-}+ \p -> Path.toString (Path.takeFileName p) `isSuffixOf` Path.toString (p::Default.AbsFile)+ )+ DocTest.printPrefix "System.Path.Internal:1203: "+{-# LINE 1203 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1203 "src/System/Path/Internal.hs" #-}+ Posix.equalFilePath "abc/def" "abc/def"+ )+ DocTest.printPrefix "System.Path.Internal:1204: "+{-# LINE 1204 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1204 "src/System/Path/Internal.hs" #-}+ Posix.equalFilePath "abc/def" "abc//def"+ )+ DocTest.printPrefix "System.Path.Internal:1205: "+{-# LINE 1205 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1205 "src/System/Path/Internal.hs" #-}+ Posix.equalFilePath "/tmp/" "/tmp"+ )+ DocTest.printPrefix "System.Path.Internal:1206: "+{-# LINE 1206 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1206 "src/System/Path/Internal.hs" #-}+ Posix.equalFilePath "/tmp" "//tmp"+ )+ DocTest.printPrefix "System.Path.Internal:1207: "+{-# LINE 1207 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1207 "src/System/Path/Internal.hs" #-}+ Posix.equalFilePath "/tmp" "///tmp"+ )+ DocTest.printPrefix "System.Path.Internal:1208: "+{-# LINE 1208 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1208 "src/System/Path/Internal.hs" #-}+ not $ Posix.equalFilePath "abc" "def"+ )+ DocTest.printPrefix "System.Path.Internal:1209: "+{-# LINE 1209 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1209 "src/System/Path/Internal.hs" #-}+ not $ Posix.equalFilePath "/tmp" "tmp"+ )+ DocTest.printPrefix "System.Path.Internal:1210: "+{-# LINE 1210 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1210 "src/System/Path/Internal.hs" #-}+ Windows.equalFilePath "abc\\def" "abc\\def"+ )+ DocTest.printPrefix "System.Path.Internal:1211: "+{-# LINE 1211 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1211 "src/System/Path/Internal.hs" #-}+ Windows.equalFilePath "abc\\def" "abc\\\\def"+ )+ DocTest.printPrefix "System.Path.Internal:1212: "+{-# LINE 1212 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1212 "src/System/Path/Internal.hs" #-}+ Windows.equalFilePath "file" "File"+ )+ DocTest.printPrefix "System.Path.Internal:1213: "+{-# LINE 1213 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1213 "src/System/Path/Internal.hs" #-}+ Windows.equalFilePath "\\file" "\\\\file"+ )+ DocTest.printPrefix "System.Path.Internal:1214: "+{-# LINE 1214 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1214 "src/System/Path/Internal.hs" #-}+ Windows.equalFilePath "\\file" "\\\\\\file"+ )+ DocTest.printPrefix "System.Path.Internal:1215: "+{-# LINE 1215 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1215 "src/System/Path/Internal.hs" #-}+ not $ Windows.equalFilePath "abc" "def"+ )+ DocTest.printPrefix "System.Path.Internal:1216: "+{-# LINE 1216 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1216 "src/System/Path/Internal.hs" #-}+ not $ Windows.equalFilePath "file" "dir"+ )+ DocTest.printPrefix "System.Path.Internal:1229: "+{-# LINE 1229 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1229 "src/System/Path/Internal.hs" #-}+ Path.joinPath ["tmp","someDir","dir"] == Posix.relDir "tmp/someDir/dir"+ )+ DocTest.printPrefix "System.Path.Internal:1230: "+{-# LINE 1230 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1230 "src/System/Path/Internal.hs" #-}+ Path.joinPath ["tmp","someDir","file.txt"] == Posix.relFile "tmp/someDir/file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1236: "+{-# LINE 1236 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1236 "src/System/Path/Internal.hs" #-}+ Path.normalise (absFile "/tmp/fred/./jim/./file") == Posix.absFile "/tmp/fred/jim/file"+ )+ DocTest.printPrefix "System.Path.Internal:1242: "+{-# LINE 1242 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1242 "src/System/Path/Internal.hs" #-}+ Path.splitPath (Posix.absDir "/tmp/someDir/mydir.dir") == (True, map relDir ["tmp","someDir","mydir.dir"], Nothing)+ )+ DocTest.printPrefix "System.Path.Internal:1243: "+{-# LINE 1243 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1243 "src/System/Path/Internal.hs" #-}+ Path.splitPath (Posix.absFile "/tmp/someDir/myfile.txt") == (True, map relDir ["tmp","someDir"], Just $ relFile "myfile.txt")+ )+ DocTest.printPrefix "System.Path.Internal:1259: "+{-# LINE 1259 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1259 "src/System/Path/Internal.hs" #-}+ Path.makeRelative (absDir "/tmp/somedir") (absFile "/tmp/somedir/anotherdir/file.txt") == Posix.relFile "anotherdir/file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1260: "+{-# LINE 1260 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1260 "src/System/Path/Internal.hs" #-}+ Path.makeRelative (absDir "/tmp/somedir") (absDir "/tmp/somedir/anotherdir/dir") == Posix.relDir "anotherdir/dir"+ )+ DocTest.printPrefix "System.Path.Internal:1261: "+{-# LINE 1261 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1261 "src/System/Path/Internal.hs" #-}+ Path.makeRelative (absDir "c:\\tmp\\somedir") (absFile "C:\\Tmp\\SomeDir\\AnotherDir\\File.txt") == Windows.relFile "AnotherDir\\File.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1262: "+{-# LINE 1262 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1262 "src/System/Path/Internal.hs" #-}+ Path.makeRelative (absDir "c:\\tmp\\somedir") (absDir "c:\\tmp\\somedir\\anotherdir\\dir") == Windows.relDir "anotherdir\\dir"+ )+ DocTest.printPrefix "System.Path.Internal:1263: "+{-# LINE 1263 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1263 "src/System/Path/Internal.hs" #-}+ Path.makeRelative (absDir "c:tmp\\somedir") (absDir "c:tmp\\somedir\\anotherdir\\dir") == Windows.relDir "anotherdir\\dir"+ )+ DocTest.printPrefix "System.Path.Internal:1290: "+{-# LINE 1290 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1290 "src/System/Path/Internal.hs" #-}+ Path.makeAbsolute (absDir "/tmp") (relFile "file.txt") == Posix.absFile "/tmp/file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1291: "+{-# LINE 1291 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1291 "src/System/Path/Internal.hs" #-}+ Path.makeAbsolute (absDir "/tmp") (relFile "adir/file.txt") == Posix.absFile "/tmp/adir/file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1292: "+{-# LINE 1292 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1292 "src/System/Path/Internal.hs" #-}+ Path.makeAbsolute (absDir "/tmp") (relDir "adir/dir") == Posix.absDir "/tmp/adir/dir"+ )+ DocTest.printPrefix "System.Path.Internal:1293: "+{-# LINE 1293 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1293 "src/System/Path/Internal.hs" #-}+ \base p -> Default.toString p `isSuffixOf` Path.toString (Path.makeAbsolute base (Path.idFile p))+ )+ DocTest.printPrefix "System.Path.Internal:1294: "+{-# LINE 1294 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1294 "src/System/Path/Internal.hs" #-}+ \base p -> Default.toString base `isPrefixOf` Path.toString (Path.makeAbsolute base (Path.idFile p))+ )+ DocTest.printPrefix "System.Path.Internal:1316: "+{-# LINE 1316 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1316 "src/System/Path/Internal.hs" #-}+ Path.genericMakeAbsolute (absDir "/tmp") (relFile "file.txt") == Posix.absFile "/tmp/file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1317: "+{-# LINE 1317 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1317 "src/System/Path/Internal.hs" #-}+ Path.genericMakeAbsolute (absDir "/tmp") (relFile "adir/file.txt") == Posix.absFile "/tmp/adir/file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1318: "+{-# LINE 1318 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1318 "src/System/Path/Internal.hs" #-}+ Path.genericMakeAbsolute (absDir "/tmp") (absFile "/adir/file.txt") == Posix.absFile "/adir/file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1403: "+{-# LINE 1403 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1403 "src/System/Path/Internal.hs" #-}+ Path.isAbsolute (Posix.absFile "/fred")+ )+ DocTest.printPrefix "System.Path.Internal:1404: "+{-# LINE 1404 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1404 "src/System/Path/Internal.hs" #-}+ Path.isAbsolute (Windows.absFile "\\fred")+ )+ DocTest.printPrefix "System.Path.Internal:1405: "+{-# LINE 1405 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1405 "src/System/Path/Internal.hs" #-}+ Path.isAbsolute (Windows.absFile "c:\\fred")+ )+ DocTest.printPrefix "System.Path.Internal:1406: "+{-# LINE 1406 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1406 "src/System/Path/Internal.hs" #-}+ Path.isAbsolute (Windows.absFile "c:fred")+ )+ DocTest.printPrefix "System.Path.Internal:1413: "+{-# LINE 1413 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1413 "src/System/Path/Internal.hs" #-}+ Path.isRelative (Posix.relFile "fred")+ )+ DocTest.printPrefix "System.Path.Internal:1414: "+{-# LINE 1414 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1414 "src/System/Path/Internal.hs" #-}+ Path.isRelative (Windows.relFile "fred")+ )+ DocTest.printPrefix "System.Path.Internal:1439: "+{-# LINE 1439 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1439 "src/System/Path/Internal.hs" #-}+ forAllAbsRel $ \x -> null (Path.takeExtension x) == not (Path.hasAnExtension x)+ )+ DocTest.printPrefix "System.Path.Internal:1445: "+{-# LINE 1445 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1445 "src/System/Path/Internal.hs" #-}+ Path.hasExtension ".hs" (Posix.relFile "MyCode.hs")+ )+ DocTest.printPrefix "System.Path.Internal:1446: "+{-# LINE 1446 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1446 "src/System/Path/Internal.hs" #-}+ Path.hasExtension ".hs" (Posix.relFile "MyCode.bak.hs")+ )+ DocTest.printPrefix "System.Path.Internal:1447: "+{-# LINE 1447 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1447 "src/System/Path/Internal.hs" #-}+ not $ Path.hasExtension ".hs" (Posix.relFile "MyCode.hs.bak")+ )+ DocTest.printPrefix "System.Path.Internal:1457: "+{-# LINE 1457 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1457 "src/System/Path/Internal.hs" #-}+ Posix.extSeparator == '.'+ )+ DocTest.printPrefix "System.Path.Internal:1468: "+{-# LINE 1468 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1468 "src/System/Path/Internal.hs" #-}+ \a -> Posix.isExtSeparator a == (a == Posix.extSeparator)+ )+ DocTest.printPrefix "System.Path.Internal:1474: "+{-# LINE 1474 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1474 "src/System/Path/Internal.hs" #-}+ \a -> Posix.isSearchPathSeparator a == (a == Posix.searchPathSeparator)+ )+ DocTest.printPrefix "System.Path.Internal:1490: "+{-# LINE 1490 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1490 "src/System/Path/Internal.hs" #-}+ Path.genericAddExtension (absDir "/") "x" == Posix.absDir "/.x"+ )+ DocTest.printPrefix "System.Path.Internal:1491: "+{-# LINE 1491 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1491 "src/System/Path/Internal.hs" #-}+ Path.genericAddExtension (absDir "/a") "x" == Posix.absDir "/a.x"+ )+ DocTest.printPrefix "System.Path.Internal:1492: "+{-# LINE 1492 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1492 "src/System/Path/Internal.hs" #-}+ Path.genericAddExtension Path.emptyFile "x" == Posix.relFile ".x"+ )+ DocTest.printPrefix "System.Path.Internal:1493: "+{-# LINE 1493 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1493 "src/System/Path/Internal.hs" #-}+ Path.genericAddExtension Path.emptyFile "" == Posix.emptyFile+ )
+ test/Test/Windows/System/Path/Internal.hs view
@@ -0,0 +1,1044 @@+-- Do not edit! Automatically created with doctest-extract from src/System/Path/Internal.hs+{-# LINE 199 "src/System/Path/Internal.hs" #-}++{-# OPTIONS_GHC -fno-warn-warnings-deprecations #-}+module Test.Windows.System.Path.Internal where++import qualified System.Path.Windows as Default+import Test.DocTest.Base+import qualified Test.DocTest.Driver as DocTest++{-# LINE 201 "src/System/Path/Internal.hs" #-}+import qualified System.Path.PartClass as Class+import qualified System.Path.Generic as Path+import qualified System.Path.Posix as Posix+import qualified System.Path.Windows as Windows+import System.Path.Generic ((</>), (<.>), relFile, relDir, absFile, absDir)+import Data.List (isSuffixOf, isPrefixOf)+import Data.Char (toLower)+import qualified Test.QuickCheck as QC+forAllAbsRel :: (Class.FileDir fd, QC.Testable prop) => (Default.AbsRel fd -> prop) -> QC.Property+forAllAbsRel = QC.forAll QC.arbitrary++test :: DocTest.T ()+test = do+ DocTest.printPrefix "System.Path.Internal:281: "+{-# LINE 281 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 281 "src/System/Path/Internal.hs" #-}+ Path.pathMap (map toLower) (absDir "/tmp/Reports/SpreadSheets") == Posix.absDir "/tmp/reports/spreadsheets"+ )+ DocTest.printPrefix "System.Path.Internal:354: "+{-# LINE 354 "src/System/Path/Internal.hs" #-}+ DocTest.example(+{-# LINE 354 "src/System/Path/Internal.hs" #-}+ Posix.rootDir </> relDir "bla" </> relFile "blub"+ )+ [ExpectedLine [LineChunk "rootDir </> relPath \"bla\" </> relPath \"blub\""]]+ DocTest.printPrefix "System.Path.Internal:356: "+{-# LINE 356 "src/System/Path/Internal.hs" #-}+ DocTest.example(+{-# LINE 356 "src/System/Path/Internal.hs" #-}+ Just (Posix.rootDir </> relDir "bla" </> relFile "blub")+ )+ [ExpectedLine [LineChunk "Just (rootDir </> relPath \"bla\" </> relPath \"blub\")"]]+ DocTest.printPrefix "System.Path.Internal:358: "+{-# LINE 358 "src/System/Path/Internal.hs" #-}+ DocTest.example(+{-# LINE 358 "src/System/Path/Internal.hs" #-}+ Posix.currentDir </> relDir "bla" </> relFile "blub"+ )+ [ExpectedLine [LineChunk "currentDir </> relPath \"bla\" </> relPath \"blub\""]]+ DocTest.printPrefix "System.Path.Internal:360: "+{-# LINE 360 "src/System/Path/Internal.hs" #-}+ DocTest.example(+{-# LINE 360 "src/System/Path/Internal.hs" #-}+ Just (Posix.currentDir </> relDir "bla" </> relFile "blub")+ )+ [ExpectedLine [LineChunk "Just (currentDir </> relPath \"bla\" </> relPath \"blub\")"]]+ DocTest.printPrefix "System.Path.Internal:362: "+{-# LINE 362 "src/System/Path/Internal.hs" #-}+ DocTest.example(+{-# LINE 362 "src/System/Path/Internal.hs" #-}+ Windows.absDir "c:" </> relDir "bla" </> relFile "blub"+ )+ [ExpectedLine [LineChunk "absDir \"c:\" </> relPath \"bla\" </> relPath \"blub\""]]+ DocTest.printPrefix "System.Path.Internal:364: "+{-# LINE 364 "src/System/Path/Internal.hs" #-}+ DocTest.example(+{-# LINE 364 "src/System/Path/Internal.hs" #-}+ Just (Windows.absDir "c:\\" </> relDir "bla" </> relFile "blub")+ )+ [ExpectedLine [LineChunk "Just (absDir \"c:\\\\\" </> relPath \"bla\" </> relPath \"blub\")"]]+ DocTest.printPrefix "System.Path.Internal:476: "+{-# LINE 476 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 476 "src/System/Path/Internal.hs" #-}+ \p -> Path.asPath (Path.toString p) == (p::Default.AbsFile)+ )+ DocTest.printPrefix "System.Path.Internal:558: "+{-# LINE 558 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 558 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "/" :: Maybe Posix.AbsDir) == Just "/"+ )+ DocTest.printPrefix "System.Path.Internal:559: "+{-# LINE 559 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 559 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "/" :: Maybe Posix.AbsFile) == Nothing+ )+ DocTest.printPrefix "System.Path.Internal:560: "+{-# LINE 560 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 560 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "/" :: Maybe Posix.RelDir) == Nothing+ )+ DocTest.printPrefix "System.Path.Internal:561: "+{-# LINE 561 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 561 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "/" :: Maybe Posix.RelFile) == Nothing+ )+ DocTest.printPrefix "System.Path.Internal:562: "+{-# LINE 562 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 562 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "/tmp" :: Maybe Posix.AbsDir) == Just "/tmp"+ )+ DocTest.printPrefix "System.Path.Internal:563: "+{-# LINE 563 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 563 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "/tmp" :: Maybe Posix.AbsFile) == Just "/tmp"+ )+ DocTest.printPrefix "System.Path.Internal:564: "+{-# LINE 564 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 564 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "/tmp" :: Maybe Posix.RelDir) == Nothing+ )+ DocTest.printPrefix "System.Path.Internal:565: "+{-# LINE 565 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 565 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "/tmp" :: Maybe Posix.RelFile) == Nothing+ )+ DocTest.printPrefix "System.Path.Internal:566: "+{-# LINE 566 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 566 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "/tmp/" :: Maybe Posix.AbsDir) == Just "/tmp"+ )+ DocTest.printPrefix "System.Path.Internal:567: "+{-# LINE 567 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 567 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "/tmp/" :: Maybe Posix.AbsFile) == Nothing+ )+ DocTest.printPrefix "System.Path.Internal:568: "+{-# LINE 568 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 568 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "/tmp/" :: Maybe Posix.RelDir) == Nothing+ )+ DocTest.printPrefix "System.Path.Internal:569: "+{-# LINE 569 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 569 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "/tmp/" :: Maybe Posix.RelFile) == Nothing+ )+ DocTest.printPrefix "System.Path.Internal:570: "+{-# LINE 570 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 570 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "/tmp" :: Maybe Posix.AbsRelFileDir) == Just "/tmp"+ )+ DocTest.printPrefix "System.Path.Internal:571: "+{-# LINE 571 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 571 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "/tmp/" :: Maybe Posix.AbsRelFileDir) == Just "/tmp"+ )+ DocTest.printPrefix "System.Path.Internal:572: "+{-# LINE 572 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 572 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "file.txt" :: Maybe Posix.RelFile) == Just "file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:573: "+{-# LINE 573 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 573 "src/System/Path/Internal.hs" #-}+ fmap Posix.toString (Posix.maybePath "file.txt" :: Maybe Posix.AbsFile) == Nothing+ )+ DocTest.printPrefix "System.Path.Internal:574: "+{-# LINE 574 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 574 "src/System/Path/Internal.hs" #-}+ fmap Windows.toString (Windows.maybePath "\\tmp" :: Maybe Windows.AbsDir) == Just "\\tmp"+ )+ DocTest.printPrefix "System.Path.Internal:575: "+{-# LINE 575 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 575 "src/System/Path/Internal.hs" #-}+ fmap Windows.toString (Windows.maybePath "a:\\tmp" :: Maybe Windows.AbsDir) == Just "a:\\tmp"+ )+ DocTest.printPrefix "System.Path.Internal:576: "+{-# LINE 576 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 576 "src/System/Path/Internal.hs" #-}+ fmap Windows.toString (Windows.maybePath "a:tmp" :: Maybe Windows.AbsDir) == Just "a:tmp"+ )+ DocTest.printPrefix "System.Path.Internal:577: "+{-# LINE 577 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 577 "src/System/Path/Internal.hs" #-}+ fmap Windows.toString (Windows.maybePath "a:\\" :: Maybe Windows.AbsDir) == Just "a:\\"+ )+ DocTest.printPrefix "System.Path.Internal:578: "+{-# LINE 578 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 578 "src/System/Path/Internal.hs" #-}+ fmap Windows.toString (Windows.maybePath "a:" :: Maybe Windows.AbsDir) == Just "a:"+ )+ DocTest.printPrefix "System.Path.Internal:579: "+{-# LINE 579 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 579 "src/System/Path/Internal.hs" #-}+ fmap Windows.toString (Windows.maybePath "tmp" :: Maybe Windows.RelDir) == Just "tmp"+ )+ DocTest.printPrefix "System.Path.Internal:580: "+{-# LINE 580 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 580 "src/System/Path/Internal.hs" #-}+ fmap Windows.toString (Windows.maybePath "\\tmp" :: Maybe Windows.RelDir) == Nothing+ )+ DocTest.printPrefix "System.Path.Internal:581: "+{-# LINE 581 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 581 "src/System/Path/Internal.hs" #-}+ fmap Windows.toString (Windows.maybePath "a:\\tmp" :: Maybe Windows.RelDir) == Nothing+ )+ DocTest.printPrefix "System.Path.Internal:582: "+{-# LINE 582 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 582 "src/System/Path/Internal.hs" #-}+ fmap Windows.toString (Windows.maybePath "a:tmp" :: Maybe Windows.RelDir) == Nothing+ )+ DocTest.printPrefix "System.Path.Internal:583: "+{-# LINE 583 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 583 "src/System/Path/Internal.hs" #-}+ fmap Windows.toString (Windows.maybePath "tmp" :: Maybe Windows.AbsDir) == Nothing+ )+ DocTest.printPrefix "System.Path.Internal:632: "+{-# LINE 632 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 632 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.relFile "file.txt") == "file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:633: "+{-# LINE 633 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 633 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.relFile "tmp") == "tmp"+ )+ DocTest.printPrefix "System.Path.Internal:639: "+{-# LINE 639 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 639 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.relDir ".") == "."+ )+ DocTest.printPrefix "System.Path.Internal:640: "+{-# LINE 640 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 640 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.relDir "file.txt") == "file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:641: "+{-# LINE 641 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 641 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.relDir "tmp") == "tmp"+ )+ DocTest.printPrefix "System.Path.Internal:647: "+{-# LINE 647 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 647 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.absFile "/file.txt") == "/file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:648: "+{-# LINE 648 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 648 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.absFile "/tmp") == "/tmp"+ )+ DocTest.printPrefix "System.Path.Internal:654: "+{-# LINE 654 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 654 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.absDir "/file.txt") == "/file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:655: "+{-# LINE 655 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 655 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.absDir "/tmp") == "/tmp"+ )+ DocTest.printPrefix "System.Path.Internal:750: "+{-# LINE 750 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 750 "src/System/Path/Internal.hs" #-}+ Posix.asPath "/tmp" == Posix.absDir "/tmp"+ )+ DocTest.printPrefix "System.Path.Internal:751: "+{-# LINE 751 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 751 "src/System/Path/Internal.hs" #-}+ Posix.asPath "file.txt" == Posix.relFile "file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:752: "+{-# LINE 752 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 752 "src/System/Path/Internal.hs" #-}+ Path.isAbsolute (Posix.asAbsDir "/tmp")+ )+ DocTest.printPrefix "System.Path.Internal:753: "+{-# LINE 753 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 753 "src/System/Path/Internal.hs" #-}+ Path.isRelative (Posix.asRelDir "/tmp")+ )+ DocTest.printPrefix "System.Path.Internal:754: "+{-# LINE 754 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 754 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.asPath "/tmp" :: Posix.AbsDir) == "/tmp"+ )+ DocTest.printPrefix "System.Path.Internal:755: "+{-# LINE 755 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 755 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.asPath "/tmp" :: Posix.RelDir) == "tmp"+ )+ DocTest.printPrefix "System.Path.Internal:756: "+{-# LINE 756 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 756 "src/System/Path/Internal.hs" #-}+ Windows.toString (Windows.asPath "\\tmp" :: Windows.AbsDir) == "\\tmp"+ )+ DocTest.printPrefix "System.Path.Internal:757: "+{-# LINE 757 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 757 "src/System/Path/Internal.hs" #-}+ Windows.toString (Windows.asPath "a:\\tmp" :: Windows.AbsDir) == "a:\\tmp"+ )+ DocTest.printPrefix "System.Path.Internal:758: "+{-# LINE 758 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 758 "src/System/Path/Internal.hs" #-}+ Windows.toString (Windows.asPath "a:tmp" :: Windows.AbsDir) == "a:tmp"+ )+ DocTest.printPrefix "System.Path.Internal:759: "+{-# LINE 759 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 759 "src/System/Path/Internal.hs" #-}+ Windows.toString (Windows.asPath "tmp" :: Windows.RelDir) == "tmp"+ )+ DocTest.printPrefix "System.Path.Internal:767: "+{-# LINE 767 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 767 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.asRelFile "file.txt") == "file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:768: "+{-# LINE 768 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 768 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.asRelFile "/file.txt") == "file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:769: "+{-# LINE 769 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 769 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.asRelFile "tmp") == "tmp"+ )+ DocTest.printPrefix "System.Path.Internal:770: "+{-# LINE 770 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 770 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.asRelFile "/tmp") == "tmp"+ )+ DocTest.printPrefix "System.Path.Internal:776: "+{-# LINE 776 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 776 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.asRelDir ".") == "."+ )+ DocTest.printPrefix "System.Path.Internal:777: "+{-# LINE 777 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 777 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.asRelDir "file.txt") == "file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:778: "+{-# LINE 778 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 778 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.asRelDir "/file.txt") == "file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:779: "+{-# LINE 779 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 779 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.asRelDir "tmp") == "tmp"+ )+ DocTest.printPrefix "System.Path.Internal:780: "+{-# LINE 780 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 780 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.asRelDir "/tmp") == "tmp"+ )+ DocTest.printPrefix "System.Path.Internal:786: "+{-# LINE 786 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 786 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.asAbsFile "/file.txt") == "/file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:787: "+{-# LINE 787 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 787 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.asAbsFile "/tmp") == "/tmp"+ )+ DocTest.printPrefix "System.Path.Internal:793: "+{-# LINE 793 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 793 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.asAbsDir "/file.txt") == "/file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:794: "+{-# LINE 794 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 794 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.asAbsDir "/tmp") == "/tmp"+ )+ DocTest.printPrefix "System.Path.Internal:833: "+{-# LINE 833 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 833 "src/System/Path/Internal.hs" #-}+ Path.mkPathAbsOrRel "/tmp" == Left (Posix.absDir "/tmp")+ )+ DocTest.printPrefix "System.Path.Internal:834: "+{-# LINE 834 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 834 "src/System/Path/Internal.hs" #-}+ Path.mkPathAbsOrRel "tmp" == Right (Posix.relDir "tmp")+ )+ DocTest.printPrefix "System.Path.Internal:835: "+{-# LINE 835 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 835 "src/System/Path/Internal.hs" #-}+ Path.mkPathAbsOrRel "\\tmp" == Left (Windows.absDir "\\tmp")+ )+ DocTest.printPrefix "System.Path.Internal:836: "+{-# LINE 836 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 836 "src/System/Path/Internal.hs" #-}+ Path.mkPathAbsOrRel "d:\\tmp" == Left (Windows.absDir "d:\\tmp")+ )+ DocTest.printPrefix "System.Path.Internal:837: "+{-# LINE 837 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 837 "src/System/Path/Internal.hs" #-}+ Path.mkPathAbsOrRel "d:tmp" == Left (Windows.absDir "d:tmp")+ )+ DocTest.printPrefix "System.Path.Internal:838: "+{-# LINE 838 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 838 "src/System/Path/Internal.hs" #-}+ Path.mkPathAbsOrRel "tmp" == Right (Windows.relDir "tmp")+ )+ DocTest.printPrefix "System.Path.Internal:867: "+{-# LINE 867 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 867 "src/System/Path/Internal.hs" #-}+ Path.mkAbsPath (absDir "/tmp") "foo.txt" == Posix.absFile "/tmp/foo.txt"+ )+ DocTest.printPrefix "System.Path.Internal:868: "+{-# LINE 868 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 868 "src/System/Path/Internal.hs" #-}+ Path.mkAbsPath (absDir "/tmp") "/etc/foo.txt" == Posix.absFile "/etc/foo.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1009: "+{-# LINE 1009 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1009 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.absDir "/tmp" </> Posix.relFile "file.txt") == "/tmp/file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1010: "+{-# LINE 1010 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1010 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.absDir "/tmp" </> Posix.relDir "dir" </> Posix.relFile "file.txt") == "/tmp/dir/file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1011: "+{-# LINE 1011 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1011 "src/System/Path/Internal.hs" #-}+ Posix.toString (Posix.relDir "dir" </> Posix.relFile "file.txt") == "dir/file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1012: "+{-# LINE 1012 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1012 "src/System/Path/Internal.hs" #-}+ Windows.toString (Windows.absDir "\\tmp" </> Windows.relFile "file.txt") == "\\tmp\\file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1013: "+{-# LINE 1013 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1013 "src/System/Path/Internal.hs" #-}+ Windows.toString (Windows.absDir "c:\\tmp" </> Windows.relFile "file.txt") == "c:\\tmp\\file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1014: "+{-# LINE 1014 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1014 "src/System/Path/Internal.hs" #-}+ Windows.toString (Windows.absDir "c:tmp" </> Windows.relFile "file.txt") == "c:tmp\\file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1015: "+{-# LINE 1015 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1015 "src/System/Path/Internal.hs" #-}+ Windows.toString (Windows.absDir "c:\\" </> Windows.relDir "tmp" </> Windows.relFile "file.txt") == "c:\\tmp\\file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1016: "+{-# LINE 1016 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1016 "src/System/Path/Internal.hs" #-}+ Windows.toString (Windows.absDir "c:" </> Windows.relDir "tmp" </> Windows.relFile "file.txt") == "c:tmp\\file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1017: "+{-# LINE 1017 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1017 "src/System/Path/Internal.hs" #-}+ Windows.toString (Windows.relDir "dir" </> Windows.relFile "file.txt") == "dir\\file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1044: "+{-# LINE 1044 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1044 "src/System/Path/Internal.hs" #-}+ Path.addExtension (relFile "file.txt") "bib" == Posix.relFile "file.txt.bib"+ )+ DocTest.printPrefix "System.Path.Internal:1045: "+{-# LINE 1045 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1045 "src/System/Path/Internal.hs" #-}+ Path.addExtension (relFile "file.") ".bib" == Posix.relFile "file..bib"+ )+ DocTest.printPrefix "System.Path.Internal:1046: "+{-# LINE 1046 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1046 "src/System/Path/Internal.hs" #-}+ Path.addExtension (relFile "file") ".bib" == Posix.relFile "file.bib"+ )+ DocTest.printPrefix "System.Path.Internal:1047: "+{-# LINE 1047 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1047 "src/System/Path/Internal.hs" #-}+ Path.addExtension Path.emptyFile "bib" == Posix.relFile ".bib"+ )+ DocTest.printPrefix "System.Path.Internal:1048: "+{-# LINE 1048 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1048 "src/System/Path/Internal.hs" #-}+ Path.addExtension Path.emptyFile ".bib" == Posix.relFile ".bib"+ )+ DocTest.printPrefix "System.Path.Internal:1049: "+{-# LINE 1049 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1049 "src/System/Path/Internal.hs" #-}+ Path.takeFileName (Path.addExtension Path.emptyFile "ext") == Posix.relFile ".ext"+ )+ DocTest.printPrefix "System.Path.Internal:1056: "+{-# LINE 1056 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1056 "src/System/Path/Internal.hs" #-}+ \p -> Path.combine Path.currentDir p == (p::Default.RelDir)+ )+ DocTest.printPrefix "System.Path.Internal:1063: "+{-# LINE 1063 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1063 "src/System/Path/Internal.hs" #-}+ forAllAbsRel $ \x -> Path.dropExtension x == fst (Path.splitExtension x)+ )+ DocTest.printPrefix "System.Path.Internal:1069: "+{-# LINE 1069 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1069 "src/System/Path/Internal.hs" #-}+ forAllAbsRel $ \x -> not $ Path.hasAnExtension (Path.dropExtensions x)+ )+ DocTest.printPrefix "System.Path.Internal:1080: "+{-# LINE 1080 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1080 "src/System/Path/Internal.hs" #-}+ Path.replaceExtension (relFile "file.txt") ".bob" == Posix.relFile "file.bob"+ )+ DocTest.printPrefix "System.Path.Internal:1081: "+{-# LINE 1081 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1081 "src/System/Path/Internal.hs" #-}+ Path.replaceExtension (relFile "file.txt") "bob" == Posix.relFile "file.bob"+ )+ DocTest.printPrefix "System.Path.Internal:1082: "+{-# LINE 1082 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1082 "src/System/Path/Internal.hs" #-}+ Path.replaceExtension (relFile "file") ".bob" == Posix.relFile "file.bob"+ )+ DocTest.printPrefix "System.Path.Internal:1083: "+{-# LINE 1083 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1083 "src/System/Path/Internal.hs" #-}+ Path.replaceExtension (relFile "file.txt") "" == Posix.relFile "file"+ )+ DocTest.printPrefix "System.Path.Internal:1084: "+{-# LINE 1084 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1084 "src/System/Path/Internal.hs" #-}+ Path.replaceExtension (relFile "file.fred.bob") "txt" == Posix.relFile "file.fred.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1101: "+{-# LINE 1101 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1101 "src/System/Path/Internal.hs" #-}+ forAllAbsRel $ \x -> uncurry (<.>) (Path.splitExtension x) == x+ )+ DocTest.printPrefix "System.Path.Internal:1102: "+{-# LINE 1102 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1102 "src/System/Path/Internal.hs" #-}+ forAllAbsRel $ \x -> uncurry Path.addExtension (Path.splitExtension x) == x+ )+ DocTest.printPrefix "System.Path.Internal:1103: "+{-# LINE 1103 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1103 "src/System/Path/Internal.hs" #-}+ Path.splitExtension (relFile "file.txt") == (Posix.relFile "file",".txt")+ )+ DocTest.printPrefix "System.Path.Internal:1104: "+{-# LINE 1104 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1104 "src/System/Path/Internal.hs" #-}+ Path.splitExtension (relFile ".bashrc") == (Posix.emptyFile, ".bashrc")+ )+ DocTest.printPrefix "System.Path.Internal:1105: "+{-# LINE 1105 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1105 "src/System/Path/Internal.hs" #-}+ Path.splitExtension (relFile "file") == (Posix.relFile "file","")+ )+ DocTest.printPrefix "System.Path.Internal:1106: "+{-# LINE 1106 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1106 "src/System/Path/Internal.hs" #-}+ Path.splitExtension (relFile "file/file.txt") == (Posix.relFile "file/file",".txt")+ )+ DocTest.printPrefix "System.Path.Internal:1107: "+{-# LINE 1107 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1107 "src/System/Path/Internal.hs" #-}+ Path.splitExtension (relFile "file.txt/boris") == (Posix.relFile "file.txt/boris","")+ )+ DocTest.printPrefix "System.Path.Internal:1108: "+{-# LINE 1108 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1108 "src/System/Path/Internal.hs" #-}+ Path.splitExtension (relFile "file.txt/boris.ext") == (Posix.relFile "file.txt/boris",".ext")+ )+ DocTest.printPrefix "System.Path.Internal:1109: "+{-# LINE 1109 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1109 "src/System/Path/Internal.hs" #-}+ Path.splitExtension (relFile "file/path.txt.bob.fred") == (Posix.relFile "file/path.txt.bob",".fred")+ )+ DocTest.printPrefix "System.Path.Internal:1115: "+{-# LINE 1115 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1115 "src/System/Path/Internal.hs" #-}+ Path.splitExtensions (relFile "file.tar.gz") == (Posix.relFile "file",".tar.gz")+ )+ DocTest.printPrefix "System.Path.Internal:1116: "+{-# LINE 1116 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1116 "src/System/Path/Internal.hs" #-}+ \p -> uncurry (<.>) (Path.splitExtension p) == (p::Default.AbsFile)+ )+ DocTest.printPrefix "System.Path.Internal:1120: "+{-# LINE 1120 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1120 "src/System/Path/Internal.hs" #-}+ \p -> uncurry Path.combine (Path.splitFileName p) == (p::Default.AbsFile)+ )+ DocTest.printPrefix "System.Path.Internal:1136: "+{-# LINE 1136 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1136 "src/System/Path/Internal.hs" #-}+ Path.takeBaseName (absFile "/tmp/somedir/myfile.txt") == Posix.relFile "myfile"+ )+ DocTest.printPrefix "System.Path.Internal:1137: "+{-# LINE 1137 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1137 "src/System/Path/Internal.hs" #-}+ Path.takeBaseName (relFile "./myfile.txt") == Posix.relFile "myfile"+ )+ DocTest.printPrefix "System.Path.Internal:1138: "+{-# LINE 1138 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1138 "src/System/Path/Internal.hs" #-}+ Path.takeBaseName (relFile "myfile.txt") == Posix.relFile "myfile"+ )+ DocTest.printPrefix "System.Path.Internal:1157: "+{-# LINE 1157 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1157 "src/System/Path/Internal.hs" #-}+ forAllAbsRel $ \x -> Path.takeExtension x == snd (Path.splitExtension x)+ )+ DocTest.printPrefix "System.Path.Internal:1158: "+{-# LINE 1158 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1158 "src/System/Path/Internal.hs" #-}+ forAllAbsRel $ \x -> Path.takeExtension (Path.addExtension x "ext") == ".ext"+ )+ DocTest.printPrefix "System.Path.Internal:1159: "+{-# LINE 1159 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1159 "src/System/Path/Internal.hs" #-}+ forAllAbsRel $ \x -> Path.takeExtension (Path.replaceExtension x "ext") == ".ext"+ )+ DocTest.printPrefix "System.Path.Internal:1165: "+{-# LINE 1165 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1165 "src/System/Path/Internal.hs" #-}+ Path.takeExtensions (Posix.relFile "file.tar.gz") == ".tar.gz"+ )+ DocTest.printPrefix "System.Path.Internal:1171: "+{-# LINE 1171 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1171 "src/System/Path/Internal.hs" #-}+ Path.takeFileName (absFile "/tmp/somedir/myfile.txt") == Posix.relFile "myfile.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1172: "+{-# LINE 1172 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1172 "src/System/Path/Internal.hs" #-}+ Path.takeFileName (relFile "./myfile.txt") == Posix.relFile "myfile.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1173: "+{-# LINE 1173 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1173 "src/System/Path/Internal.hs" #-}+ Path.takeFileName (relFile "myfile.txt") == Posix.relFile "myfile.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1174: "+{-# LINE 1174 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1174 "src/System/Path/Internal.hs" #-}+ \p -> Path.toString (Path.takeFileName p) `isSuffixOf` Path.toString (p::Default.AbsFile)+ )+ DocTest.printPrefix "System.Path.Internal:1203: "+{-# LINE 1203 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1203 "src/System/Path/Internal.hs" #-}+ Posix.equalFilePath "abc/def" "abc/def"+ )+ DocTest.printPrefix "System.Path.Internal:1204: "+{-# LINE 1204 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1204 "src/System/Path/Internal.hs" #-}+ Posix.equalFilePath "abc/def" "abc//def"+ )+ DocTest.printPrefix "System.Path.Internal:1205: "+{-# LINE 1205 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1205 "src/System/Path/Internal.hs" #-}+ Posix.equalFilePath "/tmp/" "/tmp"+ )+ DocTest.printPrefix "System.Path.Internal:1206: "+{-# LINE 1206 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1206 "src/System/Path/Internal.hs" #-}+ Posix.equalFilePath "/tmp" "//tmp"+ )+ DocTest.printPrefix "System.Path.Internal:1207: "+{-# LINE 1207 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1207 "src/System/Path/Internal.hs" #-}+ Posix.equalFilePath "/tmp" "///tmp"+ )+ DocTest.printPrefix "System.Path.Internal:1208: "+{-# LINE 1208 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1208 "src/System/Path/Internal.hs" #-}+ not $ Posix.equalFilePath "abc" "def"+ )+ DocTest.printPrefix "System.Path.Internal:1209: "+{-# LINE 1209 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1209 "src/System/Path/Internal.hs" #-}+ not $ Posix.equalFilePath "/tmp" "tmp"+ )+ DocTest.printPrefix "System.Path.Internal:1210: "+{-# LINE 1210 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1210 "src/System/Path/Internal.hs" #-}+ Windows.equalFilePath "abc\\def" "abc\\def"+ )+ DocTest.printPrefix "System.Path.Internal:1211: "+{-# LINE 1211 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1211 "src/System/Path/Internal.hs" #-}+ Windows.equalFilePath "abc\\def" "abc\\\\def"+ )+ DocTest.printPrefix "System.Path.Internal:1212: "+{-# LINE 1212 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1212 "src/System/Path/Internal.hs" #-}+ Windows.equalFilePath "file" "File"+ )+ DocTest.printPrefix "System.Path.Internal:1213: "+{-# LINE 1213 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1213 "src/System/Path/Internal.hs" #-}+ Windows.equalFilePath "\\file" "\\\\file"+ )+ DocTest.printPrefix "System.Path.Internal:1214: "+{-# LINE 1214 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1214 "src/System/Path/Internal.hs" #-}+ Windows.equalFilePath "\\file" "\\\\\\file"+ )+ DocTest.printPrefix "System.Path.Internal:1215: "+{-# LINE 1215 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1215 "src/System/Path/Internal.hs" #-}+ not $ Windows.equalFilePath "abc" "def"+ )+ DocTest.printPrefix "System.Path.Internal:1216: "+{-# LINE 1216 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1216 "src/System/Path/Internal.hs" #-}+ not $ Windows.equalFilePath "file" "dir"+ )+ DocTest.printPrefix "System.Path.Internal:1229: "+{-# LINE 1229 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1229 "src/System/Path/Internal.hs" #-}+ Path.joinPath ["tmp","someDir","dir"] == Posix.relDir "tmp/someDir/dir"+ )+ DocTest.printPrefix "System.Path.Internal:1230: "+{-# LINE 1230 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1230 "src/System/Path/Internal.hs" #-}+ Path.joinPath ["tmp","someDir","file.txt"] == Posix.relFile "tmp/someDir/file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1236: "+{-# LINE 1236 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1236 "src/System/Path/Internal.hs" #-}+ Path.normalise (absFile "/tmp/fred/./jim/./file") == Posix.absFile "/tmp/fred/jim/file"+ )+ DocTest.printPrefix "System.Path.Internal:1242: "+{-# LINE 1242 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1242 "src/System/Path/Internal.hs" #-}+ Path.splitPath (Posix.absDir "/tmp/someDir/mydir.dir") == (True, map relDir ["tmp","someDir","mydir.dir"], Nothing)+ )+ DocTest.printPrefix "System.Path.Internal:1243: "+{-# LINE 1243 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1243 "src/System/Path/Internal.hs" #-}+ Path.splitPath (Posix.absFile "/tmp/someDir/myfile.txt") == (True, map relDir ["tmp","someDir"], Just $ relFile "myfile.txt")+ )+ DocTest.printPrefix "System.Path.Internal:1259: "+{-# LINE 1259 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1259 "src/System/Path/Internal.hs" #-}+ Path.makeRelative (absDir "/tmp/somedir") (absFile "/tmp/somedir/anotherdir/file.txt") == Posix.relFile "anotherdir/file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1260: "+{-# LINE 1260 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1260 "src/System/Path/Internal.hs" #-}+ Path.makeRelative (absDir "/tmp/somedir") (absDir "/tmp/somedir/anotherdir/dir") == Posix.relDir "anotherdir/dir"+ )+ DocTest.printPrefix "System.Path.Internal:1261: "+{-# LINE 1261 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1261 "src/System/Path/Internal.hs" #-}+ Path.makeRelative (absDir "c:\\tmp\\somedir") (absFile "C:\\Tmp\\SomeDir\\AnotherDir\\File.txt") == Windows.relFile "AnotherDir\\File.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1262: "+{-# LINE 1262 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1262 "src/System/Path/Internal.hs" #-}+ Path.makeRelative (absDir "c:\\tmp\\somedir") (absDir "c:\\tmp\\somedir\\anotherdir\\dir") == Windows.relDir "anotherdir\\dir"+ )+ DocTest.printPrefix "System.Path.Internal:1263: "+{-# LINE 1263 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1263 "src/System/Path/Internal.hs" #-}+ Path.makeRelative (absDir "c:tmp\\somedir") (absDir "c:tmp\\somedir\\anotherdir\\dir") == Windows.relDir "anotherdir\\dir"+ )+ DocTest.printPrefix "System.Path.Internal:1290: "+{-# LINE 1290 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1290 "src/System/Path/Internal.hs" #-}+ Path.makeAbsolute (absDir "/tmp") (relFile "file.txt") == Posix.absFile "/tmp/file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1291: "+{-# LINE 1291 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1291 "src/System/Path/Internal.hs" #-}+ Path.makeAbsolute (absDir "/tmp") (relFile "adir/file.txt") == Posix.absFile "/tmp/adir/file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1292: "+{-# LINE 1292 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1292 "src/System/Path/Internal.hs" #-}+ Path.makeAbsolute (absDir "/tmp") (relDir "adir/dir") == Posix.absDir "/tmp/adir/dir"+ )+ DocTest.printPrefix "System.Path.Internal:1293: "+{-# LINE 1293 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1293 "src/System/Path/Internal.hs" #-}+ \base p -> Default.toString p `isSuffixOf` Path.toString (Path.makeAbsolute base (Path.idFile p))+ )+ DocTest.printPrefix "System.Path.Internal:1294: "+{-# LINE 1294 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1294 "src/System/Path/Internal.hs" #-}+ \base p -> Default.toString base `isPrefixOf` Path.toString (Path.makeAbsolute base (Path.idFile p))+ )+ DocTest.printPrefix "System.Path.Internal:1316: "+{-# LINE 1316 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1316 "src/System/Path/Internal.hs" #-}+ Path.genericMakeAbsolute (absDir "/tmp") (relFile "file.txt") == Posix.absFile "/tmp/file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1317: "+{-# LINE 1317 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1317 "src/System/Path/Internal.hs" #-}+ Path.genericMakeAbsolute (absDir "/tmp") (relFile "adir/file.txt") == Posix.absFile "/tmp/adir/file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1318: "+{-# LINE 1318 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1318 "src/System/Path/Internal.hs" #-}+ Path.genericMakeAbsolute (absDir "/tmp") (absFile "/adir/file.txt") == Posix.absFile "/adir/file.txt"+ )+ DocTest.printPrefix "System.Path.Internal:1403: "+{-# LINE 1403 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1403 "src/System/Path/Internal.hs" #-}+ Path.isAbsolute (Posix.absFile "/fred")+ )+ DocTest.printPrefix "System.Path.Internal:1404: "+{-# LINE 1404 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1404 "src/System/Path/Internal.hs" #-}+ Path.isAbsolute (Windows.absFile "\\fred")+ )+ DocTest.printPrefix "System.Path.Internal:1405: "+{-# LINE 1405 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1405 "src/System/Path/Internal.hs" #-}+ Path.isAbsolute (Windows.absFile "c:\\fred")+ )+ DocTest.printPrefix "System.Path.Internal:1406: "+{-# LINE 1406 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1406 "src/System/Path/Internal.hs" #-}+ Path.isAbsolute (Windows.absFile "c:fred")+ )+ DocTest.printPrefix "System.Path.Internal:1413: "+{-# LINE 1413 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1413 "src/System/Path/Internal.hs" #-}+ Path.isRelative (Posix.relFile "fred")+ )+ DocTest.printPrefix "System.Path.Internal:1414: "+{-# LINE 1414 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1414 "src/System/Path/Internal.hs" #-}+ Path.isRelative (Windows.relFile "fred")+ )+ DocTest.printPrefix "System.Path.Internal:1439: "+{-# LINE 1439 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1439 "src/System/Path/Internal.hs" #-}+ forAllAbsRel $ \x -> null (Path.takeExtension x) == not (Path.hasAnExtension x)+ )+ DocTest.printPrefix "System.Path.Internal:1445: "+{-# LINE 1445 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1445 "src/System/Path/Internal.hs" #-}+ Path.hasExtension ".hs" (Posix.relFile "MyCode.hs")+ )+ DocTest.printPrefix "System.Path.Internal:1446: "+{-# LINE 1446 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1446 "src/System/Path/Internal.hs" #-}+ Path.hasExtension ".hs" (Posix.relFile "MyCode.bak.hs")+ )+ DocTest.printPrefix "System.Path.Internal:1447: "+{-# LINE 1447 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1447 "src/System/Path/Internal.hs" #-}+ not $ Path.hasExtension ".hs" (Posix.relFile "MyCode.hs.bak")+ )+ DocTest.printPrefix "System.Path.Internal:1457: "+{-# LINE 1457 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1457 "src/System/Path/Internal.hs" #-}+ Posix.extSeparator == '.'+ )+ DocTest.printPrefix "System.Path.Internal:1468: "+{-# LINE 1468 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1468 "src/System/Path/Internal.hs" #-}+ \a -> Posix.isExtSeparator a == (a == Posix.extSeparator)+ )+ DocTest.printPrefix "System.Path.Internal:1474: "+{-# LINE 1474 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1474 "src/System/Path/Internal.hs" #-}+ \a -> Posix.isSearchPathSeparator a == (a == Posix.searchPathSeparator)+ )+ DocTest.printPrefix "System.Path.Internal:1490: "+{-# LINE 1490 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1490 "src/System/Path/Internal.hs" #-}+ Path.genericAddExtension (absDir "/") "x" == Posix.absDir "/.x"+ )+ DocTest.printPrefix "System.Path.Internal:1491: "+{-# LINE 1491 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1491 "src/System/Path/Internal.hs" #-}+ Path.genericAddExtension (absDir "/a") "x" == Posix.absDir "/a.x"+ )+ DocTest.printPrefix "System.Path.Internal:1492: "+{-# LINE 1492 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1492 "src/System/Path/Internal.hs" #-}+ Path.genericAddExtension Path.emptyFile "x" == Posix.relFile ".x"+ )+ DocTest.printPrefix "System.Path.Internal:1493: "+{-# LINE 1493 "src/System/Path/Internal.hs" #-}+ DocTest.property(+{-# LINE 1493 "src/System/Path/Internal.hs" #-}+ Path.genericAddExtension Path.emptyFile "" == Posix.emptyFile+ )
− test/TestResult.hs
@@ -1,215 +0,0 @@-{- Do not edit! Created from test/TestTemplate.hs -}-{-# LANGUAGE OverloadedStrings #-}-module TestResult (results) where--import System.Path.Posix as Path-import Data.Char (toLower)---results :: Char -> Path.FilePath ar -> [(String, Bool)]-results a x =- ("pathMap (map toLower) \"/tmp/Reports/SpreadSheets\" == \"/tmp/reports/spreadsheets\"",- pathMap (map toLower) "/tmp/Reports/SpreadSheets" == "/tmp/reports/spreadsheets") :- ("show (rootDir </> \"bla\" </> \"blub\") == \"rootDir </> \\\"bla\\\" </> \\\"blub\\\"\"",- show (rootDir </> "bla" </> "blub") == "rootDir </> \"bla\" </> \"blub\"") :- ("show (Just (rootDir </> \"bla\" </> \"blub\")) == \"Just (rootDir </> \\\"bla\\\" </> \\\"blub\\\")\"",- show (Just (rootDir </> "bla" </> "blub")) == "Just (rootDir </> \"bla\" </> \"blub\")") :- ("show (currentDir </> \"bla\" </> \"blub\") == \"currentDir </> \\\"bla\\\" </> \\\"blub\\\"\"",- show (currentDir </> "bla" </> "blub") == "currentDir </> \"bla\" </> \"blub\"") :- ("show (Just (currentDir </> \"bla\" </> \"blub\")) == \"Just (currentDir </> \\\"bla\\\" </> \\\"blub\\\")\"",- show (Just (currentDir </> "bla" </> "blub")) == "Just (currentDir </> \"bla\" </> \"blub\")") :- ("read (show (rootDir </> \"bla\" </> \"blub\")) == rootDir </> \"bla\" </> \"blub\"",- read (show (rootDir </> "bla" </> "blub")) == rootDir </> "bla" </> "blub") :- ("read (show (Just (rootDir </> \"bla\" </> \"blub\"))) == Just (rootDir </> \"bla\" </> \"blub\")",- read (show (Just (rootDir </> "bla" </> "blub"))) == Just (rootDir </> "bla" </> "blub")) :- ("read (show (currentDir </> \"bla\" </> \"blub\")) == currentDir </> \"bla\" </> \"blub\"",- read (show (currentDir </> "bla" </> "blub")) == currentDir </> "bla" </> "blub") :- ("read (show (Just (currentDir </> \"bla\" </> \"blub\"))) == Just (currentDir </> \"bla\" </> \"blub\")",- read (show (Just (currentDir </> "bla" </> "blub"))) == Just (currentDir </> "bla" </> "blub")) :- ("asPath \"/tmp\" == \"/tmp\"",- asPath "/tmp" == "/tmp") :- ("asPath \"file.txt\" == \"file.txt\"",- asPath "file.txt" == "file.txt") :- ("isAbsolute (asPath \"/tmp\" :: AbsDir) == True",- isAbsolute (asPath "/tmp" :: AbsDir) == True) :- ("isAbsolute (asPath \"/tmp\" :: RelDir) == False",- isAbsolute (asPath "/tmp" :: RelDir) == False) :- ("getPathString (asPath \"/tmp\" :: AbsDir) == \"/tmp\"",- getPathString (asPath "/tmp" :: AbsDir) == "/tmp") :- ("getPathString (asPath \"/tmp\" :: RelDir) == \"tmp\"",- getPathString (asPath "/tmp" :: RelDir) == "tmp") :- ("getPathString (asRelFile \"file.txt\") == \"file.txt\"",- getPathString (asRelFile "file.txt") == "file.txt") :- ("getPathString (asRelFile \"/file.txt\") == \"file.txt\"",- getPathString (asRelFile "/file.txt") == "file.txt") :- ("getPathString (asRelFile \"tmp\") == \"tmp\"",- getPathString (asRelFile "tmp") == "tmp") :- ("getPathString (asRelFile \"/tmp\") == \"tmp\"",- getPathString (asRelFile "/tmp") == "tmp") :- ("getPathString (asRelDir \".\") == \".\"",- getPathString (asRelDir ".") == ".") :- ("getPathString (asRelDir \"file.txt\") == \"file.txt\"",- getPathString (asRelDir "file.txt") == "file.txt") :- ("getPathString (asRelDir \"/file.txt\") == \"file.txt\"",- getPathString (asRelDir "/file.txt") == "file.txt") :- ("getPathString (asRelDir \"tmp\") == \"tmp\"",- getPathString (asRelDir "tmp") == "tmp") :- ("getPathString (asRelDir \"/tmp\") == \"tmp\"",- getPathString (asRelDir "/tmp") == "tmp") :- ("getPathString (asAbsFile \"file.txt\") == \"/file.txt\"",- getPathString (asAbsFile "file.txt") == "/file.txt") :- ("getPathString (asAbsFile \"/file.txt\") == \"/file.txt\"",- getPathString (asAbsFile "/file.txt") == "/file.txt") :- ("getPathString (asAbsFile \"tmp\") == \"/tmp\"",- getPathString (asAbsFile "tmp") == "/tmp") :- ("getPathString (asAbsFile \"/tmp\") == \"/tmp\"",- getPathString (asAbsFile "/tmp") == "/tmp") :- ("getPathString (asAbsDir \"file.txt\") == \"/file.txt\"",- getPathString (asAbsDir "file.txt") == "/file.txt") :- ("getPathString (asAbsDir \"/file.txt\") == \"/file.txt\"",- getPathString (asAbsDir "/file.txt") == "/file.txt") :- ("getPathString (asAbsDir \"tmp\") == \"/tmp\"",- getPathString (asAbsDir "tmp") == "/tmp") :- ("getPathString (asAbsDir \"/tmp\") == \"/tmp\"",- getPathString (asAbsDir "/tmp") == "/tmp") :- ("mkPathAbsOrRel \"/tmp\" == Left (asAbsDir \"/tmp\")",- mkPathAbsOrRel "/tmp" == Left (asAbsDir "/tmp")) :- ("mkPathAbsOrRel \"tmp\" == Right (asRelDir \"tmp\")",- mkPathAbsOrRel "tmp" == Right (asRelDir "tmp")) :- ("mkAbsPath \"/tmp\" \"foo.txt\" == \"/tmp/foo.txt\"",- mkAbsPath "/tmp" "foo.txt" == "/tmp/foo.txt") :- ("mkAbsPath \"/tmp\" \"/etc/foo.txt\" == \"/etc/foo.txt\"",- mkAbsPath "/tmp" "/etc/foo.txt" == "/etc/foo.txt") :- ("addExtension \"file.txt\" \"bib\" == \"file.txt.bib\"",- addExtension "file.txt" "bib" == "file.txt.bib") :- ("addExtension \"file.\" \".bib\" == \"file..bib\"",- addExtension "file." ".bib" == "file..bib") :- ("addExtension \"file\" \".bib\" == \"file.bib\"",- addExtension "file" ".bib" == "file.bib") :- ("addExtension \"\" \"bib\" == \".bib\"",- addExtension "" "bib" == ".bib") :- ("addExtension \"\" \".bib\" == \".bib\"",- addExtension "" ".bib" == ".bib") :- ("takeFileName (addExtension \"\" \"ext\") == \".ext\"",- takeFileName (addExtension "" "ext") == ".ext") :- ("dropExtension x == fst (splitExtension x)",- dropExtension x == fst (splitExtension x)) :- ("not $ hasAnExtension (dropExtensions x)",- not $ hasAnExtension (dropExtensions x)) :- ("replaceExtension \"file.txt\" \".bob\" == \"file.bob\"",- replaceExtension "file.txt" ".bob" == "file.bob") :- ("replaceExtension \"file.txt\" \"bob\" == \"file.bob\"",- replaceExtension "file.txt" "bob" == "file.bob") :- ("replaceExtension \"file\" \".bob\" == \"file.bob\"",- replaceExtension "file" ".bob" == "file.bob") :- ("replaceExtension \"file.txt\" \"\" == \"file\"",- replaceExtension "file.txt" "" == "file") :- ("replaceExtension \"file.fred.bob\" \"txt\" == \"file.fred.txt\"",- replaceExtension "file.fred.bob" "txt" == "file.fred.txt") :- ("uncurry (<.>) (splitExtension x) == x",- uncurry (<.>) (splitExtension x) == x) :- ("uncurry addExtension (splitExtension x) == x",- uncurry addExtension (splitExtension x) == x) :- ("splitExtension \"file.txt\" == (\"file\",\".txt\")",- splitExtension "file.txt" == ("file",".txt")) :- ("splitExtension \"file\" == (\"file\",\"\")",- splitExtension "file" == ("file","")) :- ("splitExtension \"file/file.txt\" == (\"file/file\",\".txt\")",- splitExtension "file/file.txt" == ("file/file",".txt")) :- ("splitExtension \"file.txt/boris\" == (\"file.txt/boris\",\"\")",- splitExtension "file.txt/boris" == ("file.txt/boris","")) :- ("splitExtension \"file.txt/boris.ext\" == (\"file.txt/boris\",\".ext\")",- splitExtension "file.txt/boris.ext" == ("file.txt/boris",".ext")) :- ("splitExtension \"file/path.txt.bob.fred\" == (\"file/path.txt.bob\",\".fred\")",- splitExtension "file/path.txt.bob.fred" == ("file/path.txt.bob",".fred")) :- ("splitExtensions \"file.tar.gz\" == (\"file\",\".tar.gz\")",- splitExtensions "file.tar.gz" == ("file",".tar.gz")) :- ("takeBaseName \"/tmp/somedir/myfile.txt\" == \"myfile\"",- takeBaseName "/tmp/somedir/myfile.txt" == "myfile") :- ("takeBaseName \"./myfile.txt\" == \"myfile\"",- takeBaseName "./myfile.txt" == "myfile") :- ("takeBaseName \"myfile.txt\" == \"myfile\"",- takeBaseName "myfile.txt" == "myfile") :- ("takeExtension x == snd (splitExtension x)",- takeExtension x == snd (splitExtension x)) :- ("takeExtension (addExtension x \"ext\") == \".ext\"",- takeExtension (addExtension x "ext") == ".ext") :- ("takeExtension (replaceExtension x \"ext\") == \".ext\"",- takeExtension (replaceExtension x "ext") == ".ext") :- ("takeExtensions \"file.tar.gz\" == \".tar.gz\"",- takeExtensions "file.tar.gz" == ".tar.gz") :- ("takeFileName \"/tmp/somedir/myfile.txt\" == \"myfile.txt\"",- takeFileName "/tmp/somedir/myfile.txt" == "myfile.txt") :- ("takeFileName \"./myfile.txt\" == \"myfile.txt\"",- takeFileName "./myfile.txt" == "myfile.txt") :- ("takeFileName \"myfile.txt\" == \"myfile.txt\"",- takeFileName "myfile.txt" == "myfile.txt") :- ("equalFilePath \"/tmp/\" \"/tmp\" == True",- equalFilePath "/tmp/" "/tmp" == True) :- ("equalFilePath \"/tmp\" \"tmp\" == False",- equalFilePath "/tmp" "tmp" == False) :- ("joinPath [\"/tmp\",\"someDir\",\"file.txt\"] == \"/tmp/someDir/file.txt\"",- joinPath ["/tmp","someDir","file.txt"] == "/tmp/someDir/file.txt") :- ("joinPath [\"/tmp\",\"someDir\",\"file.txt\"] == asRelFile \"tmp/someDir/file.txt\"",- joinPath ["/tmp","someDir","file.txt"] == asRelFile "tmp/someDir/file.txt") :- ("normalise \"/tmp/fred/./jim/./file\" == \"/tmp/fred/jim/file\"",- normalise "/tmp/fred/./jim/./file" == "/tmp/fred/jim/file") :- ("splitPath (asAbsDir \"/tmp/someDir/mydir.dir\") == ([\"tmp\",\"someDir\",\"mydir.dir\"], Nothing)",- splitPath (asAbsDir "/tmp/someDir/mydir.dir") == (["tmp","someDir","mydir.dir"], Nothing)) :- ("splitPath (asAbsFile \"/tmp/someDir/myfile.txt\") == ([\"tmp\",\"someDir\"], Just \"myfile.txt\")",- splitPath (asAbsFile "/tmp/someDir/myfile.txt") == (["tmp","someDir"], Just "myfile.txt")) :- ("makeRelative \"/tmp/somedir\" \"/tmp/somedir/anotherdir/file.txt\" == asRelFile \"anotherdir/file.txt\"",- makeRelative "/tmp/somedir" "/tmp/somedir/anotherdir/file.txt" == asRelFile "anotherdir/file.txt") :- ("makeRelative \"/tmp/somedir\" \"/tmp/somedir/anotherdir/dir\" == asRelDir \"anotherdir/dir\"",- makeRelative "/tmp/somedir" "/tmp/somedir/anotherdir/dir" == asRelDir "anotherdir/dir") :- ("makeAbsolute \"/tmp\" \"file.txt\" == asAbsFile \"/tmp/file.txt\"",- makeAbsolute "/tmp" "file.txt" == asAbsFile "/tmp/file.txt") :- ("makeAbsolute \"/tmp\" \"adir/file.txt\" == asAbsFile \"/tmp/adir/file.txt\"",- makeAbsolute "/tmp" "adir/file.txt" == asAbsFile "/tmp/adir/file.txt") :- ("makeAbsolute \"/tmp\" \"adir/dir\" == asAbsDir \"/tmp/adir/dir\"",- makeAbsolute "/tmp" "adir/dir" == asAbsDir "/tmp/adir/dir") :- ("genericMakeAbsolute \"/tmp\" (asRelFile \"file.txt\") == \"/tmp/file.txt\"",- genericMakeAbsolute "/tmp" (asRelFile "file.txt") == "/tmp/file.txt") :- ("genericMakeAbsolute \"/tmp\" (asRelFile \"adir/file.txt\") == \"/tmp/adir/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") :- ("genericMakeAbsolute \"/tmp\" (asAbsFile \"/adir/file.txt\") == \"/adir/file.txt\"",- genericMakeAbsolute "/tmp" (asAbsFile "/adir/file.txt") == "/adir/file.txt") :- ("isAbsolute (asAbsFile \"fred\") == True",- isAbsolute (asAbsFile "fred") == True) :- ("isAbsolute (asRelFile \"fred\") == False",- isAbsolute (asRelFile "fred") == False) :- ("isAbsolute (asAbsFile \"/fred\") == True",- isAbsolute (asAbsFile "/fred") == True) :- ("isAbsolute (asRelFile \"/fred\") == False",- isAbsolute (asRelFile "/fred") == False) :- ("null (takeExtension x) == not (hasAnExtension x)",- null (takeExtension x) == not (hasAnExtension x)) :- ("hasExtension \".hs\" \"MyCode.hs\" == True",- hasExtension ".hs" "MyCode.hs" == True) :- ("hasExtension \".hs\" \"MyCode.hs.bak\" == False",- hasExtension ".hs" "MyCode.hs.bak" == False) :- ("hasExtension \".hs\" \"MyCode.bak.hs\" == True",- hasExtension ".hs" "MyCode.bak.hs" == True) :- ("extSeparator == '.'",- extSeparator == '.') :- ("isPathSeparator pathSeparator",- isPathSeparator pathSeparator) :- ("pathSeparator `elem` pathSeparators",- pathSeparator `elem` pathSeparators) :- ("isExtSeparator a == (a == extSeparator)",- isExtSeparator a == (a == extSeparator)) :- ("isPathSeparator a == (a `elem` pathSeparators)",- isPathSeparator a == (a `elem` pathSeparators)) :- ("isSearchPathSeparator a == (a == searchPathSeparator)",- isSearchPathSeparator a == (a == searchPathSeparator)) :- ("genericAddExtension \"/\" \"x\" == asAbsDir \"/.x\"",- genericAddExtension "/" "x" == asAbsDir "/.x") :- ("genericAddExtension \"/a\" \"x\" == asAbsDir \"/a.x\"",- genericAddExtension "/a" "x" == asAbsDir "/a.x") :- ("genericAddExtension \"\" \"x\" == asRelFile \".x\"",- genericAddExtension "" "x" == asRelFile ".x") :- ("genericAddExtension \"\" \"\" == asRelFile \"\"",- genericAddExtension "" "" == asRelFile "") :- []
− test/TestTemplate.hs
@@ -1,11 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-module TestResult (results) where--import System.Path.Posix as Path-import Data.Char (toLower)---results :: Char -> Path.FilePath ar -> [(String, Bool)]-results a x =- <TESTS_GO_HERE>- []
− tool/CreateTest.hs
@@ -1,31 +0,0 @@-module Main where--import Control.Applicative ((<$>))-import Data.List (stripPrefix, isInfixOf)-import Data.Maybe (mapMaybe)--import Text.Printf (printf)---srcfiles :: [String]-template, testModule, tok, testPrefix :: String--srcfiles =- map ("src/System/Path/" ++) $- ["Internal.hs", "Directory.hs", "IO.hs"]-template = "test/TestTemplate.hs"-testModule = "test/TestResult.hs"-tok = "<TESTS_GO_HERE>"-testPrefix = "-- >> "--main :: IO ()-main = do- testLines <-- mapMaybe (stripPrefix testPrefix) . concatMap lines <$> mapM readFile srcfiles- (templateHead,_:templateTail) <-- break (tok `isInfixOf`) . lines <$> readFile template- let outLines = (\t -> printf " (%s,\n %s) :" (show t) t) <$> testLines-- writeFile testModule $ unlines $- ("{- Do not edit! Created from " ++ template ++ " -}") :- templateHead ++ outLines ++ templateTail
+ windows/System/Path/Host.hs view
@@ -0,0 +1,2 @@+module System.Path.Host (module System.Path.Windows) where+import System.Path.Windows