pathtype 0.5.5 → 0.6
raw patch · 8 files changed
+951/−496 lines, 8 files
Files
- pathtype.cabal +10/−2
- src/System/Path/Directory.hs +12/−6
- src/System/Path/Internal.hs +529/−276
- src/System/Path/Posix.hs +0/−1
- src/System/Path/Windows.hs +0/−1
- test/TestResult.hs +382/−206
- test/TestTemplate.hs +4/−2
- tool/CreateTest.hs +14/−2
pathtype.cabal view
@@ -1,5 +1,5 @@ Name: pathtype-Version: 0.5.5+Version: 0.6 Synopsis: Type-safe replacement for System.FilePath etc Description: This package provides type-safe access to filepath manipulations. .@@ -73,7 +73,15 @@ The basic API (and properties satisfied) are heavily influenced by Neil Mitchell's "System.FilePath" module. .+ Related packages: .+ * @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. Stability: experimental License: BSD3 Category: System@@ -94,7 +102,7 @@ Location: http://hub.darcs.net/thielema/pathtype/ Source-Repository this- Tag: 0.5.5+ Tag: 0.6 Type: darcs Location: http://hub.darcs.net/thielema/pathtype/
src/System/Path/Directory.hs view
@@ -166,11 +166,14 @@ copyFile :: (AbsRelClass ar1, AbsRelClass ar2) => FilePath ar1 -> FilePath ar2 -> IO () copyFile p1 p2 = SD.copyFile (getPathString p1) (getPathString p2) -canonicalizePath :: AbsRelClass ar => Path ar fd -> IO (AbsPath fd)+canonicalizePath ::+ (AbsRelClass ar, FileDirClass fd) => Path ar fd -> IO (AbsPath fd) canonicalizePath p = asPath <$> SD.canonicalizePath (getPathString p) -makeRelativeToCurrentDirectory :: AbsRelClass ar => Path ar fd -> IO (RelPath fd)-makeRelativeToCurrentDirectory p = asPath <$> SD.makeRelativeToCurrentDirectory (getPathString p)+makeRelativeToCurrentDirectory ::+ (AbsRelClass ar, FileDirClass fd) => Path ar fd -> IO (RelPath fd)+makeRelativeToCurrentDirectory p =+ asPath <$> SD.makeRelativeToCurrentDirectory (getPathString p) findExecutable :: String -> IO (Maybe AbsFile) findExecutable s = fmap asPath <$> SD.findExecutable s@@ -189,15 +192,18 @@ ------------------------------------------------------------------------ -- Permissions -getPermissions :: AbsRelClass ar => Path ar fd -> IO Permissions+getPermissions ::+ (AbsRelClass ar, FileDirClass fd) => Path ar fd -> IO Permissions getPermissions p = SD.getPermissions (getPathString p) -setPermissions :: AbsRelClass ar => Path ar fd -> Permissions -> IO ()+setPermissions ::+ (AbsRelClass ar, FileDirClass fd) => Path ar fd -> Permissions -> IO () setPermissions p perms = SD.setPermissions (getPathString p) perms ------------------------------------------------------------------------ -- Timestamps -getModificationTime :: AbsRelClass ar => Path ar fd -> IO UTCTime+getModificationTime ::+ (AbsRelClass ar, FileDirClass fd) => Path ar fd -> IO UTCTime getModificationTime p = convertTime <$> SD.getModificationTime (getPathString p)
src/System/Path/Internal.hs view
@@ -116,12 +116,14 @@ import qualified System.Directory as SD -import Control.Arrow (first, (|||), (***))+import Control.Arrow (first, second, (|||), (***))+import Control.Monad (guard, mplus) import Control.Applicative ((<$>)) import Control.DeepSeq (NFData(rnf))-import Data.List (isSuffixOf, isPrefixOf, stripPrefix, intercalate)+import Data.List (isSuffixOf, isPrefixOf, stripPrefix, intersperse) import Data.String (IsString(fromString))-import Data.Char (isSpace)+import Data.Maybe (fromMaybe, maybeToList)+import Data.Char (toLower, isAlpha, isSpace) import Text.Printf (printf) @@ -136,29 +138,75 @@ ------------------------------------------------------------------------ -- Types -data Abs-data Rel-data File-data Dir+newtype Abs = Abs String deriving (Eq, Ord)+data Rel = Rel deriving (Eq, Ord) +newtype File = File PathComponent deriving (Eq, Ord)+data Dir = Dir deriving (Eq, Ord)+ -- | 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)+data Path ar fd = Path ar [PathComponent] fd --- 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.+instance (AbsRelClass ar, FileDirClass fd) => Eq (Path ar fd) where+ Path ar0 pcs0 fd0 == Path ar1 pcs1 fd1 =+ (WrapAbsRel ar0, pcs0, WrapFileDir fd0)+ ==+ (WrapAbsRel ar1, pcs1, WrapFileDir fd1) -newtype PathComponent = PathComponent String deriving (Eq,Ord)+instance (AbsRelClass ar, FileDirClass fd) => Ord (Path ar fd) where+ compare (Path ar0 pcs0 fd0) (Path ar1 pcs1 fd1) =+ compare+ (WrapAbsRel ar0, pcs0, WrapFileDir fd0)+ (WrapAbsRel ar1, pcs1, WrapFileDir fd1) ++newtype WrapAbsRel ar = WrapAbsRel {unwrapAbsRel :: ar}++instance (AbsRelClass ar) => Eq (WrapAbsRel ar) where+ (==) = switchRelation switchAbsRel unwrapAbsRel (==) (==)++instance (AbsRelClass ar) => Ord (WrapAbsRel ar) where+ compare = switchRelation switchAbsRel unwrapAbsRel compare compare+++newtype WrapFileDir fd = WrapFileDir {unwrapFileDir :: fd}++instance (FileDirClass fd) => Eq (WrapFileDir fd) where+ (==) = switchRelation switchFileDir unwrapFileDir (==) (==)++instance (FileDirClass fd) => Ord (WrapFileDir fd) where+ compare = switchRelation switchFileDir unwrapFileDir compare compare+++newtype Relation res a = Relation {runRelation :: a -> a -> res}++switchRelation ::+ (Relation res a -> Relation res b -> Relation res c) ->+ (wrapped -> c) ->+ (a -> a -> res) ->+ (b -> b -> res) ->+ wrapped -> wrapped -> res+switchRelation switch unwrap fFile fDir ar0 ar1 =+ runRelation+ (switch (Relation fFile) (Relation fDir))+ (unwrap ar0) (unwrap ar1)+++newtype PathComponent = PathComponent String++instance Eq PathComponent where+ PathComponent x == PathComponent y =+ if isPosix+ then x==y+ else map toLower x == map toLower y++instance Ord PathComponent where+ compare (PathComponent x) (PathComponent y) =+ if isPosix+ then compare x y+ else compare (map toLower x) (map toLower y)++ type AbsFile = Path Abs File type RelFile = Path Rel File type AbsDir = Path Abs Dir@@ -172,10 +220,32 @@ instance NFData PathComponent where rnf (PathComponent pc) = rnf pc -instance NFData (Path ar fd) where- rnf PathRoot = ()- rnf (FileDir d pc) = rnf (d, pc)+instance NFData Abs where+ rnf (Abs drive) = rnf drive +instance NFData Rel where+ rnf Rel = ()++instance NFData File where+ rnf (File pc) = rnf pc++instance NFData Dir where+ rnf Dir = ()++instance (AbsRelClass ar, FileDirClass fd) => NFData (Path ar fd) where+ rnf (Path ar pcs fd) =+ rnf (absRelPlain rnf rnf ar, pcs, fileDirPlain rnf rnf fd)++absRelPlain :: (AbsRelClass ar) => (Abs -> a) -> (Rel -> a) -> ar -> a+absRelPlain fAbs fRel =+ runFuncArg $ switchAbsRel (FuncArg fAbs) (FuncArg fRel)++fileDirPlain :: (FileDirClass fd) => (File -> a) -> (Dir -> a) -> fd -> a+fileDirPlain fFile fDir =+ runFuncArg $ switchFileDir (FuncArg fFile) (FuncArg fDir)++newtype FuncArg b a = FuncArg {runFuncArg :: a -> b}+ -- 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@@ -183,12 +253,17 @@ -- | 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)+-- >> Posix.pathMap (map toLower) "/tmp/Reports/SpreadSheets" == Posix.asAbsDir "/tmp/reports/spreadsheets"+pathMap :: (FileDirClass fd) => (String -> String) -> Path ar fd -> Path ar fd+pathMap f (Path ar pcs fd) = Path ar (map (pcMap f) pcs) (fdMap f fd) --- Private fn+newtype FDMap ar fd = FDMap {runFDMap :: fd -> fd}++fdMap :: (FileDirClass fd) => (String -> String) -> fd -> fd+fdMap f =+ runFDMap $+ switchFileDir (FDMap $ \(File pc) -> File $ pcMap f pc) (FDMap id)+ pcMap :: (String -> String) -> PathComponent -> PathComponent pcMap f (PathComponent s) = PathComponent (f s) @@ -226,9 +301,9 @@ 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)+ fileDir f g = runFileDir $ switchFileDir (FileDir f) (FileDir g) -newtype FileDir ar a fd = FileDirFunc {runFileDir :: Path ar fd -> a}+newtype FileDir ar a fd = FileDir {runFileDir :: Path ar fd -> a} instance FileDirClass File where switchFileDir f _g = f instance FileDirClass Dir where switchFileDir _f g = g@@ -245,62 +320,86 @@ ------------------------------------------------------------------------ -- 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+-- >> show (Posix.rootDir </> "bla" </> Posix.asRelFile "blub") == "rootDir </> \"bla\" </> \"blub\""+-- >> show (Just (Posix.rootDir </> "bla" </> Posix.asRelFile "blub")) == "Just (rootDir </> \"bla\" </> \"blub\")"+-- >> show (Posix.currentDir </> "bla" </> Posix.asRelFile "blub") == "currentDir </> \"bla\" </> \"blub\""+-- >> show (Just (Posix.currentDir </> "bla" </> Posix.asRelFile "blub")) == "Just (currentDir </> \"bla\" </> \"blub\")"+-- >> show (Windows.asAbsDir "c:" Windows.</> "bla" Windows.</> Windows.asRelFile "blub") == "asAbsDir \"c:\" </> \"bla\" </> \"blub\""+-- >> show (Just (Windows.asAbsDir "c:\\" Windows.</> "bla" Windows.</> Windows.asRelFile "blub")) == "Just (asAbsDir \"c:\" </> \"bla\" </> \"blub\")"+instance (AbsRelClass ar, FileDirClass fd) => Show (Path ar fd) where+ showsPrec d x =+ case pathComponents x of+ (ar, pcs) ->+ showParen (d>9) $+ foldr (.) id $+ intersperse+ (showChar ' ' .+ showString combineOperator . showChar ' ') $+ absRelPlain+ (\(Abs drive) ->+ if null drive+ then showString rootName+ else showString absDirName .+ showString drive .+ showChar '"')+ (const $ showString currentName)+ ar :+ map (\(PathComponent pc) -> shows pc) pcs --- >> 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+-- >> let path = Posix.rootDir </> "bla" </> Posix.asRelFile "blub" in read (show path) == path+-- >> let path = Just (Posix.rootDir </> "bla" </> Posix.asRelFile "blub") in read (show path) == path+-- >> let path = Posix.currentDir </> "bla" </> Posix.asRelFile "blub" in read (show path) == path+-- >> let path = Just (Posix.currentDir </> "bla" </> Posix.asRelFile "blub") in read (show path) == path+-- >> let path = Windows.rootDir Windows.</> "bla" Windows.</> Windows.asRelFile "blub" in read (show path) == path+-- >> let path = Just (Windows.rootDir Windows.</> "bla" Windows.</> Windows.asRelFile "blub") in read (show path) == path+instance (AbsRelClass ar, FileDirClass fd) => 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 =+ let go :: ReadS [PathComponent]+ go s0 = case stripPrefix combineOperator $ dropWhile isSpace s0 of- Nothing -> [(relaxDir path, s0)]+ Nothing -> [([], 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+ (pcs, s3) <- go s2+ return (PathComponent pc : pcs, s3)+ in do+ (ar, s0) <- maybeToList $ readsSplitDrive $ dropWhile isSpace str+ (pcs, s1) <- go s0+ path <- maybeToList $ maybePathFromComponents ar pcs+ return (path, s1) -relaxDir :: Path ar Dir -> Path ar fd-relaxDir PathRoot = PathRoot-relaxDir (FileDir p pc) = FileDir p pc+newtype+ ReadsSplitDrive ar =+ ReadsSplitDrive {runReadsSplitDrive :: Maybe (ar, String)} +readsSplitDrive :: (AbsRelClass ar) => String -> Maybe (ar, String)+readsSplitDrive str0 =+ runReadsSplitDrive $+ switchAbsRel+ (ReadsSplitDrive $+ (fmap ((,) (Abs "")) $ stripPrefix rootName str0)+ `mplus`+ do str1 <- stripPrefix absDirName str0+ (drive, '"':str2) <- Just $ break ('"'==) str1+ return (Abs drive, str2))+ (ReadsSplitDrive $+ fmap ((,) Rel) $ stripPrefix currentName str0)+ -- | Convert the 'Path' into a plain 'String' as required for OS calls.-getPathString :: AbsRelClass ar => Path ar fd -> String+getPathString :: (AbsRelClass ar, FileDirClass fd) => 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+getPathStringS :: (AbsRelClass ar, FileDirClass fd) => Path ar fd -> ShowS+getPathStringS x =+ case pathComponents x of+ (ar, []) ->+ absRelPlain+ (\(Abs drive) -> showString drive . showChar pathSeparator)+ (const $ showString currentDirComponent) ar+ (ar, pcs) ->+ foldr (.) id $ intersperse (showChar pathSeparator) $+ absRelPlain (\(Abs drive) -> (showString drive :)) (const id) ar $+ map (\(PathComponent pc) -> showString pc) pcs prop_asPath_getPathString :: AbsFile -> Property prop_asPath_getPathString p = property $ p == asPath (getPathString p)@@ -309,8 +408,8 @@ ------------------------------------------------------------------------ -- Windows / Posix -_isPosix :: Bool-_isPosix = not isWindows+isPosix :: Bool+isPosix = not isWindows isWindows :: Bool isWindows = IS_WINDOWS@@ -319,10 +418,10 @@ -- Constants rootDir :: AbsDir-rootDir = PathRoot+rootDir = Path (Abs "") [] Dir currentDir :: RelDir-currentDir = PathRoot+currentDir = Path Rel [] Dir rootName :: String rootName = "rootDir"@@ -333,6 +432,8 @@ currentDirComponent :: String currentDirComponent = "." +absDirName :: String+absDirName = "asAbsDir \"" ------------------------------------------------------------------------ -- Unchecked Construction Functions@@ -341,70 +442,82 @@ -- | 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+-- >> Posix.asPath "/tmp" == Posix.asAbsDir "/tmp"+-- >> Posix.asPath "file.txt" == Posix.asRelFile "file.txt"+-- >> Posix.isAbsolute (Posix.asAbsDir "/tmp")+-- >> Posix.isRelative (Posix.asRelDir "/tmp")+-- >> Posix.getPathString (Posix.asPath "/tmp" :: Posix.AbsDir) == "/tmp"+-- >> Posix.getPathString (Posix.asPath "/tmp" :: Posix.RelDir) == "tmp"+-- >> Windows.getPathString (Windows.asPath "\\tmp" :: Windows.AbsDir) == "\\tmp"+-- >> Windows.getPathString (Windows.asPath "a:\\tmp" :: Windows.AbsDir) == "a:\\tmp"+-- >> Windows.getPathString (Windows.asPath "tmp" :: Windows.RelDir) == "tmp"+asPath :: (AbsRelClass ar, FileDirClass fd) => String -> Path ar fd+asPath = uncurry mkPathFromComponents . mkPathComponents +newtype AbsRelDefault ar = AbsRelDefault {getAbsRelDefault :: ar}++absRelDefault :: (AbsRelClass ar) => ar+absRelDefault =+ getAbsRelDefault $ switchAbsRel (AbsRelDefault $ Abs "") (AbsRelDefault Rel)++ -- | 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"+-- >> Posix.getPathString (Posix.asRelFile "file.txt") == "file.txt"+-- >> Posix.getPathString (Posix.asRelFile "/file.txt") == "file.txt"+-- >> Posix.getPathString (Posix.asRelFile "tmp") == "tmp"+-- >> Posix.getPathString (Posix.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"+-- >> Posix.getPathString (Posix.asRelDir ".") == "."+-- >> Posix.getPathString (Posix.asRelDir "file.txt") == "file.txt"+-- >> Posix.getPathString (Posix.asRelDir "/file.txt") == "file.txt"+-- >> Posix.getPathString (Posix.asRelDir "tmp") == "tmp"+-- >> Posix.getPathString (Posix.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"+-- >> Posix.getPathString (Posix.asAbsFile "file.txt") == "/file.txt"+-- >> Posix.getPathString (Posix.asAbsFile "/file.txt") == "/file.txt"+-- >> Posix.getPathString (Posix.asAbsFile "tmp") == "/tmp"+-- >> Posix.getPathString (Posix.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"+-- >> Posix.getPathString (Posix.asAbsDir "file.txt") == "/file.txt"+-- >> Posix.getPathString (Posix.asAbsDir "/file.txt") == "/file.txt"+-- >> Posix.getPathString (Posix.asAbsDir "tmp") == "/tmp"+-- >> Posix.getPathString (Posix.asAbsDir "/tmp") == "/tmp" asAbsDir :: String -> AbsDir asAbsDir = asPath -- | Use a 'String' as a 'RelPath fd'. No checking is done.-asRelPath :: String -> RelPath fd+asRelPath :: (FileDirClass fd) => String -> RelPath fd asRelPath = asPath -- | Use a 'String' as an 'AbsPath fd'. No checking is done.-asAbsPath :: String -> AbsPath fd+asAbsPath :: (FileDirClass fd) => String -> AbsPath fd asAbsPath = asPath -- | Use a 'String' as a 'FilePath ar'. No checking is done.-asFilePath :: String -> FilePath ar+asFilePath :: (AbsRelClass ar) => String -> FilePath ar asFilePath = asPath -- | Use a 'String' as a 'DirPath ar'. No checking is done.-asDirPath :: String -> DirPath ar+asDirPath :: (AbsRelClass ar) => String -> DirPath ar asDirPath = asPath -- | Allow use of OverloadedStrings if desired-instance IsString (Path ar fd) where fromString = asPath+instance+ (AbsRelClass ar, FileDirClass fd) =>+ IsString (Path ar fd) where fromString = asPath ------------------------------------------------------------------------ -- Checked Construction Functions@@ -412,9 +525,13 @@ -- | 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)+-- >> Posix.mkPathAbsOrRel "/tmp" == Left (Posix.asAbsDir "/tmp")+-- >> Posix.mkPathAbsOrRel "tmp" == Right (Posix.asRelDir "tmp")+-- >> Windows.mkPathAbsOrRel "\\tmp" == Left (Windows.asAbsDir "\\tmp")+-- >> Windows.mkPathAbsOrRel "d:\\tmp" == Left (Windows.asAbsDir "d:\\tmp")+-- >> Windows.mkPathAbsOrRel "tmp" == Right (Windows.asRelDir "tmp")+mkPathAbsOrRel ::+ (FileDirClass fd) => String -> Either (AbsPath fd) (RelPath fd) mkPathAbsOrRel s = if isAbsoluteString s then Left $ asAbsPath s@@ -437,39 +554,88 @@ -- | 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+-- >> Posix.mkAbsPath "/tmp" "foo.txt" == Posix.asAbsFile "/tmp/foo.txt"+-- >> Posix.mkAbsPath "/tmp" "/etc/foo.txt" == Posix.asAbsFile "/etc/foo.txt"+mkAbsPath :: (FileDirClass fd) => 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 :: (FileDirClass fd) => 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+mkPathFromComponents :: (FileDirClass fd) => ar -> [PathComponent] -> Path ar fd+mkPathFromComponents ar pcs =+ switchFileDir+ (fromMaybe (Path ar [] $ File $ PathComponent "") $+ mkFilePathFromComponents ar pcs)+ (mkDirPathFromComponents ar pcs) -mkPathComponents :: String -> [PathComponent]-mkPathComponents xs =- case break isPathSeparator (dropWhile isPathSeparator xs) of- ("","") -> []- (s,rest) -> PathComponent s : mkPathComponents rest+maybePathFromComponents ::+ (FileDirClass fd) => ar -> [PathComponent] -> Maybe (Path ar fd)+maybePathFromComponents ar pcs =+ getFunctorPath $+ switchFileDir+ (FunctorPath $ mkFilePathFromComponents ar pcs)+ (FunctorPath $ Just $ mkDirPathFromComponents ar pcs) -pathComponents :: Path ar fd -> [PathComponent]-pathComponents PathRoot = []-pathComponents (FileDir p pc) = pathComponents p ++ [pc]+newtype+ FunctorPath f ar fd =+ FunctorPath {getFunctorPath :: f (Path ar fd)} -prop_mkPathFromComponents_pathComponents :: AbsFile -> Property+mkDirPathFromComponents :: ar -> [PathComponent] -> Path ar Dir+mkDirPathFromComponents ar pcs = Path ar pcs Dir++mkFilePathFromComponents :: ar -> [PathComponent] -> Maybe (Path ar File)+mkFilePathFromComponents _ [] = Nothing+mkFilePathFromComponents ar0 (q:qs) =+ let mapPathDirs f ~(Path ar pcs fd) = Path ar (f pcs) fd+ go p [] = Path ar0 [] (File p)+ go p0 (p1:ps) = mapPathDirs (p0:) $ go p1 ps+ in Just $ go q qs++mkPathComponents :: (AbsRelClass ar) => String -> (ar, [PathComponent])+mkPathComponents =+ let go xs =+ case break isPathSeparator $ dropWhile isPathSeparator xs of+ ("","") -> []+ (s,rest) -> s : go rest+ split [] = (absRelDefault, [])+ split (pc:pcs) =+ second (map PathComponent) $+ case splitDrive pc of+ (drive, "") -> (drive, pcs)+ (drive, pc0) -> (drive, pc0:pcs)+ in split . go++newtype SplitDrive ar = SplitDrive {runSplitDrive :: (ar, String)}++splitDrive :: (AbsRelClass ar) => String -> (ar, String)+splitDrive str =+ runSplitDrive $+ switchAbsRel+ (SplitDrive $ first Abs $+ if isPosix+ then ("", str)+ else+ case break (':'==) str of+ (drive, ':':rest) -> (drive++":", rest)+ _ -> ("", str))+ (SplitDrive (Rel, str))++pathComponents :: (FileDirClass fd) => Path ar fd -> (ar, [PathComponent])+pathComponents (Path ar pcs fd) = (ar, pcs ++ fileDirComponent fd)++fileDirComponent :: (FileDirClass fd) => fd -> [PathComponent]+fileDirComponent = fileDirPlain (\(File pc) -> [pc]) (\Dir -> [])++prop_mkPathFromComponents_pathComponents :: AbsDir -> Property prop_mkPathFromComponents_pathComponents p =- property $ mkPathFromComponents (pathComponents p) == p+ property $ uncurry mkPathFromComponents (pathComponents p) == p @@ -480,10 +646,16 @@ combineOperator = "</>" -- | Infix variant of 'combine'.+--+-- >> Posix.getPathString (Posix.asAbsDir "/tmp" </> Posix.asRelFile "file.txt") == "/tmp/file.txt"+-- >> Posix.getPathString (Posix.asAbsDir "/tmp" </> Posix.asRelDir "dir" </> Posix.asRelFile "file.txt") == "/tmp/dir/file.txt"+-- >> Posix.getPathString (Posix.asRelDir "dir" </> Posix.asRelFile "file.txt") == "dir/file.txt"+-- >> Windows.getPathString (Windows.asAbsDir "\\tmp" Windows.</> Windows.asRelFile "file.txt") == "\\tmp\\file.txt"+-- >> Windows.getPathString (Windows.asAbsDir "c:\\tmp" Windows.</> Windows.asRelFile "file.txt") == "c:\\tmp\\file.txt"+-- >> Windows.getPathString (Windows.asAbsDir "c:" Windows.</> Windows.asRelDir "tmp" Windows.</> Windows.asRelFile "file.txt") == "c:\\tmp\\file.txt"+-- >> Windows.getPathString (Windows.asRelDir "dir" Windows.</> Windows.asRelFile "file.txt") == "dir\\file.txt" (</>) :: 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+(Path ar pcs0 Dir) </> (Path Rel pcs1 fd) = Path ar (pcs0 ++ pcs1) fd -- | Infix variant of 'addExtension'. -- We only allow files (and not directories) to have extensions added@@ -494,17 +666,17 @@ -- directories, and so we provide a function that is more flexible: -- 'genericAddExtension'. (<.>) :: FilePath ar -> String -> FilePath ar-(<.>) = genericAddExtension+Path ar pcs (File pc) <.> ext = Path ar pcs (File $ addExtensionPC pc ext) -- | 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"+-- >> Posix.addExtension (Posix.asRelFile "file.txt") "bib" == "file.txt.bib"+-- >> Posix.addExtension (Posix.asRelFile "file.") ".bib" == "file..bib"+-- >> Posix.addExtension (Posix.asRelFile "file") ".bib" == "file.bib"+-- >> Posix.addExtension (Posix.asRelFile "") "bib" == ".bib"+-- >> Posix.addExtension (Posix.asRelFile "") ".bib" == ".bib"+-- >> Posix.takeFileName (Posix.addExtension (Posix.asRelFile "") "ext") == ".ext" addExtension :: FilePath ar -> String -> FilePath ar addExtension = (<.>) @@ -516,67 +688,69 @@ -- | Remove last extension, and the \".\" preceding it. ----- >> dropExtension x == fst (splitExtension x)+-- >> Posix.dropExtension x == fst (Posix.splitExtension x) dropExtension :: FilePath ar -> FilePath ar dropExtension = fst . splitExtension -- | Drop all extensions ----- >> not $ hasAnExtension (dropExtensions x)+-- >> not $ Posix.hasAnExtension (Posix.dropExtensions x) dropExtensions :: FilePath ar -> FilePath ar dropExtensions = fst . splitExtensions -- | Synonym for 'takeDirectory'-dropFileName :: Path ar fd -> DirPath ar+dropFileName :: FilePath ar -> 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"+-- >> Posix.replaceExtension (Posix.asRelFile "file.txt") ".bob" == "file.bob"+-- >> Posix.replaceExtension (Posix.asRelFile "file.txt") "bob" == "file.bob"+-- >> Posix.replaceExtension (Posix.asRelFile "file") ".bob" == "file.bob"+-- >> Posix.replaceExtension (Posix.asRelFile "file.txt") "" == "file"+-- >> Posix.replaceExtension (Posix.asRelFile "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)+replaceBaseName :: FilePath ar -> String -> FilePath ar+replaceBaseName (Path ar pcs (File pc)) bn =+ Path ar pcs $ File $+ addExtensionPC (PathComponent bn) $ snd $ splitExtensionPC pc -replaceDirectory :: Path ar1 fd -> DirPath ar2 -> Path ar2 fd-replaceDirectory p d = d </> takeFileName p+replaceDirectory :: FilePath ar1 -> DirPath ar2 -> FilePath ar2+replaceDirectory (Path _ _ fd) (Path ar pcs _) = Path ar pcs fd -replaceFileName :: Path ar fd -> String -> Path ar fd-replaceFileName p fn = takeDirectory p </> asPath fn+replaceFileName :: FilePath ar -> String -> FilePath ar+replaceFileName (Path ar pcs _) fn = Path ar pcs (File (PathComponent 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")+-- >> uncurry (<.>) (Posix.splitExtension x) == x+-- >> uncurry Posix.addExtension (Posix.splitExtension x) == x+-- >> Posix.splitExtension (Posix.asRelFile "file.txt") == ("file",".txt")+-- >> Posix.splitExtension (Posix.asRelFile "file") == ("file","")+-- >> Posix.splitExtension (Posix.asRelFile "file/file.txt") == ("file/file",".txt")+-- >> Posix.splitExtension (Posix.asRelFile "file.txt/boris") == ("file.txt/boris","")+-- >> Posix.splitExtension (Posix.asRelFile "file.txt/boris.ext") == ("file.txt/boris",".ext")+-- >> Posix.splitExtension (Posix.asRelFile "file/path.txt.bob.fred") == ("file/path.txt.bob",".fred") splitExtension :: FilePath ar -> (FilePath ar, String)-splitExtension = genericSplitExtension+splitExtension (Path ar pcs (File pc)) =+ first (Path ar pcs . File) $ splitExtensionPC pc -- | Split on all extensions ----- >> splitExtensions "file.tar.gz" == ("file",".tar.gz")+-- >> Posix.splitExtensions (Posix.asRelFile "file.tar.gz") == ("file",".tar.gz") splitExtensions :: FilePath ar -> (FilePath ar, String)-splitExtensions = genericSplitExtensions+splitExtensions (Path ar pcs (File pc)) =+ first (Path ar pcs . File) $ splitExtensionsPC pc 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"+splitFileName :: FilePath ar -> (DirPath ar, RelFile)+splitFileName (Path ar pcs fd) = (Path ar pcs Dir, Path Rel [] fd) prop_split_combine :: AbsFile -> Property prop_split_combine p = property $ uncurry combine (splitFileName p) == p@@ -584,37 +758,36 @@ -- | 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+-- >> Posix.takeBaseName (Posix.asAbsFile "/tmp/somedir/myfile.txt") == "myfile"+-- >> Posix.takeBaseName (Posix.asRelFile "./myfile.txt") == "myfile"+-- >> Posix.takeBaseName (Posix.asRelFile "myfile.txt") == "myfile"+takeBaseName :: FilePath ar -> RelFile+takeBaseName = takeFileName . dropExtension -takeDirectory :: Path ar fd -> DirPath ar+takeDirectory :: FilePath ar -> 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"+-- >> Posix.takeExtension x == snd (Posix.splitExtension x)+-- >> Posix.takeExtension (Posix.addExtension x "ext") == ".ext"+-- >> Posix.takeExtension (Posix.replaceExtension x "ext") == ".ext" takeExtension :: FilePath ar -> String takeExtension = snd . splitExtension -- | Get all extensions ----- >> takeExtensions "file.tar.gz" == ".tar.gz"+-- >> Posix.takeExtensions (Posix.asRelFile "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+-- >> Posix.takeFileName (Posix.asAbsFile "/tmp/somedir/myfile.txt") == "myfile.txt"+-- >> Posix.takeFileName (Posix.asRelFile "./myfile.txt") == "myfile.txt"+-- >> Posix.takeFileName (Posix.asRelFile "myfile.txt") == "myfile.txt"+takeFileName :: FilePath ar -> RelFile+takeFileName (Path _ _ fd) = Path Rel [] fd prop_takeFileName_end :: AbsFile -> Property prop_takeFileName_end p = property $ show (takeFileName p) `isSuffixOf` show p@@ -625,51 +798,65 @@ -- | Check whether two strings are equal as file paths. ----- >> equalFilePath "/tmp/" "/tmp" == True--- >> equalFilePath "/tmp" "tmp" == False+-- >> Posix.equalFilePath "/tmp/" "/tmp"+-- >> not $ Posix.equalFilePath "/tmp" "tmp"+-- >> Windows.equalFilePath "file" "File"+-- >> not $ Windows.equalFilePath "file" "dir" equalFilePath :: String -> String -> Bool equalFilePath s1 s2 =- isAbsoluteString s1 == isAbsoluteString s2 && asPath s1 == asPath s2+ let abs1 = isAbsoluteString s1+ abs2 = isAbsoluteString s2+ in abs1 == abs2 &&+ if abs1+ then asAbsDir s1 == asAbsDir s2+ else asRelDir s1 == asRelDir s2 --- | Constructs a 'Path' from a list of components.+-- | 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. ----- >> 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]+-- >> Posix.joinPath ["tmp","someDir","dir"] == Posix.asRelDir "tmp/someDir/dir"+-- >> Posix.joinPath ["tmp","someDir","file.txt"] == Posix.asRelFile "tmp/someDir/file.txt"+joinPath :: (FileDirClass fd) => [String] -> RelPath fd+joinPath = mkPathFromComponents Rel . map PathComponent -- | Currently just transforms: ----- >> normalise "/tmp/fred/./jim/./file" == "/tmp/fred/jim/file"+-- >> Posix.normalise "/tmp/fred/./jim/./file" == Posix.asAbsFile "/tmp/fred/jim/file" normalise :: Path ar fd -> Path ar fd-normalise =- mkPathFromComponents .- filter (/= PathComponent currentDirComponent) .- pathComponents+normalise (Path ar pcs fd) =+ Path ar (filter (PathComponent currentDirComponent /=) pcs) fd -- | 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+-- >> Posix.splitPath (Posix.asAbsDir "/tmp/someDir/mydir.dir") == (True, ["tmp","someDir","mydir.dir"], Nothing)+-- >> Posix.splitPath (Posix.asAbsFile "/tmp/someDir/myfile.txt") == (True, ["tmp","someDir"], Just "myfile.txt")+splitPath ::+ (AbsRelClass ar, FileDirClass fd) =>+ Path ar fd -> (Bool, [RelDir], Maybe RelFile)+splitPath (Path ar pcs fd) =+ (isAbsolutePlain ar,+ map (\pc -> Path Rel [pc] Dir) pcs,+ maybeFileDir fd) +isAbsolutePlain :: (AbsRelClass ar) => ar -> Bool+isAbsolutePlain = absRelPlain (const True) (const False)++maybeFileDir :: (FileDirClass fd) => fd -> Maybe RelFile+maybeFileDir = fileDirPlain (Just . Path Rel []) (\Dir -> 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'. ----- >> 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)+-- >> Posix.makeRelative "/tmp/somedir" "/tmp/somedir/anotherdir/file.txt" == Posix.asRelFile "anotherdir/file.txt"+-- >> Posix.makeRelative "/tmp/somedir" "/tmp/somedir/anotherdir/dir" == Posix.asRelDir "anotherdir/dir"+-- >> Windows.makeRelative "c:\\tmp\\somedir" "c:\\Tmp\\SomeDir\\AnotherDir\\File.txt" == Windows.asRelFile "AnotherDir\\File.txt"+-- >> Windows.makeRelative "c:\\tmp\\somedir" "c:\\tmp\\somedir\\anotherdir\\dir" == Windows.asRelDir "anotherdir\\dir"+makeRelative :: (FileDirClass fd) => AbsDir -> AbsPath fd -> RelPath fd+makeRelative relTo@(Path relToAR relToPCs Dir) orig@(Path origAR origPCs fd) =+ maybe (error msg) (flip (Path Rel) fd) $+ guard (relToAR == origAR) >> stripPrefix relToPCs origPCs where msg = printf "System.Path can't make (%s) relative to (%s)"@@ -678,9 +865,9 @@ -- | 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"+-- >> Posix.makeAbsolute "/tmp" "file.txt" == Posix.asAbsFile "/tmp/file.txt"+-- >> Posix.makeAbsolute "/tmp" "adir/file.txt" == Posix.asAbsFile "/tmp/adir/file.txt"+-- >> Posix.makeAbsolute "/tmp" "adir/dir" == Posix.asAbsDir "/tmp/adir/dir" makeAbsolute :: AbsDir -> RelPath fd -> AbsPath fd makeAbsolute = genericMakeAbsolute @@ -692,10 +879,10 @@ -- | 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"+-- >> Posix.genericMakeAbsolute "/tmp" (Posix.asRelFile "file.txt") == "/tmp/file.txt"+-- >> Posix.genericMakeAbsolute "/tmp" (Posix.asRelFile "adir/file.txt") == "/tmp/adir/file.txt"+-- >> Posix.genericMakeAbsolute "/tmp" (Posix.asAbsFile "adir/file.txt") == "/adir/file.txt"+-- >> Posix.genericMakeAbsolute "/tmp" (Posix.asAbsFile "/adir/file.txt") == "/adir/file.txt" genericMakeAbsolute :: AbsRelClass ar => AbsDir -> Path ar fd -> AbsPath fd genericMakeAbsolute base p = absRel id (base </>) p @@ -740,10 +927,10 @@ -- | Test whether a @'Path' ar fd@ is absolute. ----- >> isAbsolute (asAbsFile "fred") == True--- >> isAbsolute (asRelFile "fred") == False--- >> isAbsolute (asAbsFile "/fred") == True--- >> isAbsolute (asRelFile "/fred") == False+-- >> Posix.isAbsolute (Posix.asAbsFile "fred")+-- >> Posix.isAbsolute (Posix.asAbsFile "/fred")+-- >> Windows.isAbsolute (Windows.asAbsFile "\\fred")+-- >> Windows.isAbsolute (Windows.asAbsFile "c:\\fred") isAbsolute :: AbsRelClass ar => Path ar fd -> Bool isAbsolute = absRel (const True) (const False) @@ -751,11 +938,17 @@ -- 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+isAbsoluteString (x:xs) =+ isPathSeparator x -- Absolute if first char is a path separator+ ||+ isWindows && isAlpha x && isPrefixOf ":" xs -- | Invariant - this should return True iff arg is of type @'Path' Rel _@ -- -- > isRelative = not . isAbsolute+-- >> Posix.isRelative (Posix.asRelFile "fred")+-- >> Posix.isRelative (Posix.asRelFile "/fred")+-- >> Windows.isRelative (Windows.asRelFile "fred") isRelative :: AbsRelClass ar => Path ar fd -> Bool isRelative = not . isAbsolute @@ -769,15 +962,15 @@ -- | Does the given filename have an extension? ----- >> null (takeExtension x) == not (hasAnExtension x)+-- >> null (Posix.takeExtension x) == not (Posix.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+-- >> Posix.hasExtension ".hs" (Posix.asRelFile "MyCode.hs")+-- >> Posix.hasExtension ".hs" (Posix.asRelFile "MyCode.bak.hs")+-- >> not $ Posix.hasExtension ".hs" (Posix.asRelFile "MyCode.hs.bak") hasExtension :: String -> FilePath ar -> Bool hasExtension ext = (==ext) . snd . splitExtension @@ -795,7 +988,7 @@ -- | File extension character ----- >> extSeparator == '.'+-- >> Posix.extSeparator == '.' extSeparator :: Char extSeparator = '.' @@ -806,14 +999,14 @@ -- | The character that separates directories. In the case where more than -- one character is possible, 'pathSeparator' is the \'ideal\' one. ----- >> isPathSeparator pathSeparator+-- >> Posix.isPathSeparator Posix.pathSeparator pathSeparator :: Char pathSeparator | isWindows = '\\' | otherwise = '/' -- | The list of all possible separators. ----- >> pathSeparator `elem` pathSeparators+-- >> Posix.pathSeparator `elem` Posix.pathSeparators pathSeparators :: [Char] pathSeparators = return pathSeparator @@ -824,20 +1017,20 @@ -- | Is the character an extension character? ----- >> isExtSeparator a == (a == extSeparator)+-- >> Posix.isExtSeparator a == (a == Posix.extSeparator) isExtSeparator :: Char -> Bool isExtSeparator = (== extSeparator) -- | Rather than using @(== 'pathSeparator')@, use this. Test if something -- is a path separator. ----- >> isPathSeparator a == (a `elem` pathSeparators)+-- >> Posix.isPathSeparator a == (a `elem` Posix.pathSeparators) isPathSeparator :: Char -> Bool isPathSeparator = flip elem pathSeparators -- | Is the character a file separator? ----- >> isSearchPathSeparator a == (a == searchPathSeparator)+-- >> Posix.isSearchPathSeparator a == (a == Posix.searchPathSeparator) isSearchPathSeparator :: Char -> Bool isSearchPathSeparator = (== searchPathSeparator) @@ -853,50 +1046,107 @@ -- | 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+-- >> Posix.genericAddExtension "/" "x" == Posix.asAbsDir "/.x"+-- >> Posix.genericAddExtension "/a" "x" == Posix.asAbsDir "/a.x"+-- >> Posix.genericAddExtension "" "x" == Posix.asRelFile ".x"+-- >> Posix.genericAddExtension "" "" == Posix.asRelFile ""+genericAddExtension :: (FileDirClass fd) => 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)+ runAddExtension+ (switchFileDir+ (AddExtension $+ \(Path ar pcs (File pc)) ->+ Path ar pcs $ File $ addExtensionPC pc ext)+ (AddExtension $+ \(Path ar pcs0 Dir) ->+ let pcs = if null pcs0 then [PathComponent ""] else pcs0+ in Path ar (mapLast (flip addExtensionPC ext) pcs) Dir))+ path -genericDropExtension :: Path ar fd -> Path ar fd+newtype+ AddExtension ar fd =+ AddExtension {runAddExtension :: Path ar fd -> Path ar fd}++genericDropExtension :: (FileDirClass fd) => Path ar fd -> Path ar fd genericDropExtension = fst . genericSplitExtension -genericDropExtensions :: Path ar fd -> Path ar fd+genericDropExtensions :: (FileDirClass fd) => 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)+genericSplitExtension ::+ (FileDirClass fd) => Path ar fd -> (Path ar fd, String)+genericSplitExtension =+ runSplitExtension $+ switchFileDir+ (SplitExtension $+ \(Path ar pcs (File pc)) ->+ first (Path ar pcs . File) $ splitExtensionPC pc)+ (SplitExtension $+ \(Path ar pcs Dir) ->+ first (flip (Path ar) Dir) $+ mapLastPair+ (error "genericSplitExtension: empty path")+ splitExtensionPC pcs)++genericSplitExtensions ::+ (FileDirClass fd) => Path ar fd -> (Path ar fd, String)+genericSplitExtensions =+ runSplitExtension $+ switchFileDir+ (SplitExtension $+ \(Path ar pcs (File pc)) ->+ first (Path ar pcs . File) $ splitExtensionsPC pc)+ (SplitExtension $+ \(Path ar pcs Dir) ->+ first (flip (Path ar) Dir) $+ mapLastPair+ (error "genericSplitExtensions: empty path")+ splitExtensionsPC pcs)++genericTakeExtension :: (FileDirClass fd) => Path ar fd -> String+genericTakeExtension = snd . genericSplitExtension++genericTakeExtensions :: (FileDirClass fd) => Path ar fd -> String+genericTakeExtensions = snd . genericSplitExtension++newtype+ SplitExtension ar fd =+ SplitExtension {runSplitExtension :: Path ar fd -> (Path ar fd, 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 b0 f xs =+ case reverse xs of+ [] -> (xs, b0)+ y:ys ->+ let (a, b) = f y+ in (reverse ys ++ [a], b)++addExtensionPC :: PathComponent -> String -> PathComponent+addExtensionPC p "" = p+addExtensionPC (PathComponent pc) ext =+ PathComponent $ pc +++ if [extSeparator] `isPrefixOf` ext+ then ext+ else extSeparator : ext++splitExtensionPC :: PathComponent -> (PathComponent, String)+splitExtensionPC (PathComponent s) = (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-+splitExtensionsPC :: PathComponent -> (PathComponent, String)+splitExtensionsPC (PathComponent s) =+ first PathComponent $ break isExtSeparator s ------------------------------------------------------------------------ -- QuickCheck@@ -937,22 +1187,25 @@ arbitrary = oneof [qcFileComponent, qcDirComponent] -qcGenPath :: Gen PathComponent -> Gen (Path ar fd)+qcGenPath ::+ (AbsRelClass ar, FileDirClass fd) =>+ Gen PathComponent -> Gen (Path ar fd) qcGenPath qcLastComponent = do+ ar <- switchAbsRel (fmap (Abs . (:":")) $ QC.choose ('a', 'z')) (return Rel) pcs <- QC.listOf qcDirComponent pc <- qcLastComponent- return $ mkPathFromComponents (pcs ++ [pc])+ return $ mkPathFromComponents ar (pcs ++ [pc]) -qcFilePath :: Gen (FilePath ar)+qcFilePath :: (AbsRelClass ar) => Gen (FilePath ar) qcFilePath = qcGenPath qcFileComponent -qcDirPath :: Gen (DirPath ar)+qcDirPath :: (AbsRelClass ar) => 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)+qcPath =+ getFunctorPath $+ switchFileDir (FunctorPath qcFilePath) (FunctorPath qcDirPath) instance (AbsRelClass ar, FileDirClass fd) => Arbitrary (Path ar fd) where arbitrary = qcPath
src/System/Path/Posix.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE CPP #-} #define MODULE_NAME Posix #define IS_WINDOWS False
src/System/Path/Windows.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE CPP #-} #define MODULE_NAME Windows #define IS_WINDOWS True
test/TestResult.hs view
@@ -2,214 +2,390 @@ {-# LANGUAGE OverloadedStrings #-} module TestResult (results) where -import System.Path.Posix as Path+import qualified System.Path.Posix as Posix+import qualified System.Path.Windows as Windows+import System.Path ((</>), (<.>)) import Data.Char (toLower) -results :: Char -> Path.FilePath ar -> [(String, Bool)]+results :: (Posix.AbsRelClass ar) => Char -> Posix.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 "") :+ {-# LINE 255 "src/System/Path/Internal.hs" #-}+ ("Posix.pathMap (map toLower) \"/tmp/Reports/SpreadSheets\" == Posix.asAbsDir \"/tmp/reports/spreadsheets\"",+ Posix.pathMap (map toLower) "/tmp/Reports/SpreadSheets" == Posix.asAbsDir "/tmp/reports/spreadsheets") :+ {-# LINE 322 "src/System/Path/Internal.hs" #-}+ ("show (Posix.rootDir </> \"bla\" </> Posix.asRelFile \"blub\") == \"rootDir </> \\\"bla\\\" </> \\\"blub\\\"\"",+ show (Posix.rootDir </> "bla" </> Posix.asRelFile "blub") == "rootDir </> \"bla\" </> \"blub\"") :+ {-# LINE 323 "src/System/Path/Internal.hs" #-}+ ("show (Just (Posix.rootDir </> \"bla\" </> Posix.asRelFile \"blub\")) == \"Just (rootDir </> \\\"bla\\\" </> \\\"blub\\\")\"",+ show (Just (Posix.rootDir </> "bla" </> Posix.asRelFile "blub")) == "Just (rootDir </> \"bla\" </> \"blub\")") :+ {-# LINE 324 "src/System/Path/Internal.hs" #-}+ ("show (Posix.currentDir </> \"bla\" </> Posix.asRelFile \"blub\") == \"currentDir </> \\\"bla\\\" </> \\\"blub\\\"\"",+ show (Posix.currentDir </> "bla" </> Posix.asRelFile "blub") == "currentDir </> \"bla\" </> \"blub\"") :+ {-# LINE 325 "src/System/Path/Internal.hs" #-}+ ("show (Just (Posix.currentDir </> \"bla\" </> Posix.asRelFile \"blub\")) == \"Just (currentDir </> \\\"bla\\\" </> \\\"blub\\\")\"",+ show (Just (Posix.currentDir </> "bla" </> Posix.asRelFile "blub")) == "Just (currentDir </> \"bla\" </> \"blub\")") :+ {-# LINE 326 "src/System/Path/Internal.hs" #-}+ ("show (Windows.asAbsDir \"c:\" Windows.</> \"bla\" Windows.</> Windows.asRelFile \"blub\") == \"asAbsDir \\\"c:\\\" </> \\\"bla\\\" </> \\\"blub\\\"\"",+ show (Windows.asAbsDir "c:" Windows.</> "bla" Windows.</> Windows.asRelFile "blub") == "asAbsDir \"c:\" </> \"bla\" </> \"blub\"") :+ {-# LINE 327 "src/System/Path/Internal.hs" #-}+ ("show (Just (Windows.asAbsDir \"c:\\\\\" Windows.</> \"bla\" Windows.</> Windows.asRelFile \"blub\")) == \"Just (asAbsDir \\\"c:\\\" </> \\\"bla\\\" </> \\\"blub\\\")\"",+ show (Just (Windows.asAbsDir "c:\\" Windows.</> "bla" Windows.</> Windows.asRelFile "blub")) == "Just (asAbsDir \"c:\" </> \"bla\" </> \"blub\")") :+ {-# LINE 348 "src/System/Path/Internal.hs" #-}+ ("let path = Posix.rootDir </> \"bla\" </> Posix.asRelFile \"blub\" in read (show path) == path",+ let path = Posix.rootDir </> "bla" </> Posix.asRelFile "blub" in read (show path) == path) :+ {-# LINE 349 "src/System/Path/Internal.hs" #-}+ ("let path = Just (Posix.rootDir </> \"bla\" </> Posix.asRelFile \"blub\") in read (show path) == path",+ let path = Just (Posix.rootDir </> "bla" </> Posix.asRelFile "blub") in read (show path) == path) :+ {-# LINE 350 "src/System/Path/Internal.hs" #-}+ ("let path = Posix.currentDir </> \"bla\" </> Posix.asRelFile \"blub\" in read (show path) == path",+ let path = Posix.currentDir </> "bla" </> Posix.asRelFile "blub" in read (show path) == path) :+ {-# LINE 351 "src/System/Path/Internal.hs" #-}+ ("let path = Just (Posix.currentDir </> \"bla\" </> Posix.asRelFile \"blub\") in read (show path) == path",+ let path = Just (Posix.currentDir </> "bla" </> Posix.asRelFile "blub") in read (show path) == path) :+ {-# LINE 352 "src/System/Path/Internal.hs" #-}+ ("let path = Windows.rootDir Windows.</> \"bla\" Windows.</> Windows.asRelFile \"blub\" in read (show path) == path",+ let path = Windows.rootDir Windows.</> "bla" Windows.</> Windows.asRelFile "blub" in read (show path) == path) :+ {-# LINE 353 "src/System/Path/Internal.hs" #-}+ ("let path = Just (Windows.rootDir Windows.</> \"bla\" Windows.</> Windows.asRelFile \"blub\") in read (show path) == path",+ let path = Just (Windows.rootDir Windows.</> "bla" Windows.</> Windows.asRelFile "blub") in read (show path) == path) :+ {-# LINE 444 "src/System/Path/Internal.hs" #-}+ ("Posix.asPath \"/tmp\" == Posix.asAbsDir \"/tmp\"",+ Posix.asPath "/tmp" == Posix.asAbsDir "/tmp") :+ {-# LINE 445 "src/System/Path/Internal.hs" #-}+ ("Posix.asPath \"file.txt\" == Posix.asRelFile \"file.txt\"",+ Posix.asPath "file.txt" == Posix.asRelFile "file.txt") :+ {-# LINE 446 "src/System/Path/Internal.hs" #-}+ ("Posix.isAbsolute (Posix.asAbsDir \"/tmp\")",+ Posix.isAbsolute (Posix.asAbsDir "/tmp")) :+ {-# LINE 447 "src/System/Path/Internal.hs" #-}+ ("Posix.isRelative (Posix.asRelDir \"/tmp\")",+ Posix.isRelative (Posix.asRelDir "/tmp")) :+ {-# LINE 448 "src/System/Path/Internal.hs" #-}+ ("Posix.getPathString (Posix.asPath \"/tmp\" :: Posix.AbsDir) == \"/tmp\"",+ Posix.getPathString (Posix.asPath "/tmp" :: Posix.AbsDir) == "/tmp") :+ {-# LINE 449 "src/System/Path/Internal.hs" #-}+ ("Posix.getPathString (Posix.asPath \"/tmp\" :: Posix.RelDir) == \"tmp\"",+ Posix.getPathString (Posix.asPath "/tmp" :: Posix.RelDir) == "tmp") :+ {-# LINE 450 "src/System/Path/Internal.hs" #-}+ ("Windows.getPathString (Windows.asPath \"\\\\tmp\" :: Windows.AbsDir) == \"\\\\tmp\"",+ Windows.getPathString (Windows.asPath "\\tmp" :: Windows.AbsDir) == "\\tmp") :+ {-# LINE 451 "src/System/Path/Internal.hs" #-}+ ("Windows.getPathString (Windows.asPath \"a:\\\\tmp\" :: Windows.AbsDir) == \"a:\\\\tmp\"",+ Windows.getPathString (Windows.asPath "a:\\tmp" :: Windows.AbsDir) == "a:\\tmp") :+ {-# LINE 452 "src/System/Path/Internal.hs" #-}+ ("Windows.getPathString (Windows.asPath \"tmp\" :: Windows.RelDir) == \"tmp\"",+ Windows.getPathString (Windows.asPath "tmp" :: Windows.RelDir) == "tmp") :+ {-# LINE 465 "src/System/Path/Internal.hs" #-}+ ("Posix.getPathString (Posix.asRelFile \"file.txt\") == \"file.txt\"",+ Posix.getPathString (Posix.asRelFile "file.txt") == "file.txt") :+ {-# LINE 466 "src/System/Path/Internal.hs" #-}+ ("Posix.getPathString (Posix.asRelFile \"/file.txt\") == \"file.txt\"",+ Posix.getPathString (Posix.asRelFile "/file.txt") == "file.txt") :+ {-# LINE 467 "src/System/Path/Internal.hs" #-}+ ("Posix.getPathString (Posix.asRelFile \"tmp\") == \"tmp\"",+ Posix.getPathString (Posix.asRelFile "tmp") == "tmp") :+ {-# LINE 468 "src/System/Path/Internal.hs" #-}+ ("Posix.getPathString (Posix.asRelFile \"/tmp\") == \"tmp\"",+ Posix.getPathString (Posix.asRelFile "/tmp") == "tmp") :+ {-# LINE 474 "src/System/Path/Internal.hs" #-}+ ("Posix.getPathString (Posix.asRelDir \".\") == \".\"",+ Posix.getPathString (Posix.asRelDir ".") == ".") :+ {-# LINE 475 "src/System/Path/Internal.hs" #-}+ ("Posix.getPathString (Posix.asRelDir \"file.txt\") == \"file.txt\"",+ Posix.getPathString (Posix.asRelDir "file.txt") == "file.txt") :+ {-# LINE 476 "src/System/Path/Internal.hs" #-}+ ("Posix.getPathString (Posix.asRelDir \"/file.txt\") == \"file.txt\"",+ Posix.getPathString (Posix.asRelDir "/file.txt") == "file.txt") :+ {-# LINE 477 "src/System/Path/Internal.hs" #-}+ ("Posix.getPathString (Posix.asRelDir \"tmp\") == \"tmp\"",+ Posix.getPathString (Posix.asRelDir "tmp") == "tmp") :+ {-# LINE 478 "src/System/Path/Internal.hs" #-}+ ("Posix.getPathString (Posix.asRelDir \"/tmp\") == \"tmp\"",+ Posix.getPathString (Posix.asRelDir "/tmp") == "tmp") :+ {-# LINE 484 "src/System/Path/Internal.hs" #-}+ ("Posix.getPathString (Posix.asAbsFile \"file.txt\") == \"/file.txt\"",+ Posix.getPathString (Posix.asAbsFile "file.txt") == "/file.txt") :+ {-# LINE 485 "src/System/Path/Internal.hs" #-}+ ("Posix.getPathString (Posix.asAbsFile \"/file.txt\") == \"/file.txt\"",+ Posix.getPathString (Posix.asAbsFile "/file.txt") == "/file.txt") :+ {-# LINE 486 "src/System/Path/Internal.hs" #-}+ ("Posix.getPathString (Posix.asAbsFile \"tmp\") == \"/tmp\"",+ Posix.getPathString (Posix.asAbsFile "tmp") == "/tmp") :+ {-# LINE 487 "src/System/Path/Internal.hs" #-}+ ("Posix.getPathString (Posix.asAbsFile \"/tmp\") == \"/tmp\"",+ Posix.getPathString (Posix.asAbsFile "/tmp") == "/tmp") :+ {-# LINE 493 "src/System/Path/Internal.hs" #-}+ ("Posix.getPathString (Posix.asAbsDir \"file.txt\") == \"/file.txt\"",+ Posix.getPathString (Posix.asAbsDir "file.txt") == "/file.txt") :+ {-# LINE 494 "src/System/Path/Internal.hs" #-}+ ("Posix.getPathString (Posix.asAbsDir \"/file.txt\") == \"/file.txt\"",+ Posix.getPathString (Posix.asAbsDir "/file.txt") == "/file.txt") :+ {-# LINE 495 "src/System/Path/Internal.hs" #-}+ ("Posix.getPathString (Posix.asAbsDir \"tmp\") == \"/tmp\"",+ Posix.getPathString (Posix.asAbsDir "tmp") == "/tmp") :+ {-# LINE 496 "src/System/Path/Internal.hs" #-}+ ("Posix.getPathString (Posix.asAbsDir \"/tmp\") == \"/tmp\"",+ Posix.getPathString (Posix.asAbsDir "/tmp") == "/tmp") :+ {-# LINE 527 "src/System/Path/Internal.hs" #-}+ ("Posix.mkPathAbsOrRel \"/tmp\" == Left (Posix.asAbsDir \"/tmp\")",+ Posix.mkPathAbsOrRel "/tmp" == Left (Posix.asAbsDir "/tmp")) :+ {-# LINE 528 "src/System/Path/Internal.hs" #-}+ ("Posix.mkPathAbsOrRel \"tmp\" == Right (Posix.asRelDir \"tmp\")",+ Posix.mkPathAbsOrRel "tmp" == Right (Posix.asRelDir "tmp")) :+ {-# LINE 529 "src/System/Path/Internal.hs" #-}+ ("Windows.mkPathAbsOrRel \"\\\\tmp\" == Left (Windows.asAbsDir \"\\\\tmp\")",+ Windows.mkPathAbsOrRel "\\tmp" == Left (Windows.asAbsDir "\\tmp")) :+ {-# LINE 530 "src/System/Path/Internal.hs" #-}+ ("Windows.mkPathAbsOrRel \"d:\\\\tmp\" == Left (Windows.asAbsDir \"d:\\\\tmp\")",+ Windows.mkPathAbsOrRel "d:\\tmp" == Left (Windows.asAbsDir "d:\\tmp")) :+ {-# LINE 531 "src/System/Path/Internal.hs" #-}+ ("Windows.mkPathAbsOrRel \"tmp\" == Right (Windows.asRelDir \"tmp\")",+ Windows.mkPathAbsOrRel "tmp" == Right (Windows.asRelDir "tmp")) :+ {-# LINE 556 "src/System/Path/Internal.hs" #-}+ ("Posix.mkAbsPath \"/tmp\" \"foo.txt\" == Posix.asAbsFile \"/tmp/foo.txt\"",+ Posix.mkAbsPath "/tmp" "foo.txt" == Posix.asAbsFile "/tmp/foo.txt") :+ {-# LINE 557 "src/System/Path/Internal.hs" #-}+ ("Posix.mkAbsPath \"/tmp\" \"/etc/foo.txt\" == Posix.asAbsFile \"/etc/foo.txt\"",+ Posix.mkAbsPath "/tmp" "/etc/foo.txt" == Posix.asAbsFile "/etc/foo.txt") :+ {-# LINE 649 "src/System/Path/Internal.hs" #-}+ ("Posix.getPathString (Posix.asAbsDir \"/tmp\" </> Posix.asRelFile \"file.txt\") == \"/tmp/file.txt\"",+ Posix.getPathString (Posix.asAbsDir "/tmp" </> Posix.asRelFile "file.txt") == "/tmp/file.txt") :+ {-# LINE 650 "src/System/Path/Internal.hs" #-}+ ("Posix.getPathString (Posix.asAbsDir \"/tmp\" </> Posix.asRelDir \"dir\" </> Posix.asRelFile \"file.txt\") == \"/tmp/dir/file.txt\"",+ Posix.getPathString (Posix.asAbsDir "/tmp" </> Posix.asRelDir "dir" </> Posix.asRelFile "file.txt") == "/tmp/dir/file.txt") :+ {-# LINE 651 "src/System/Path/Internal.hs" #-}+ ("Posix.getPathString (Posix.asRelDir \"dir\" </> Posix.asRelFile \"file.txt\") == \"dir/file.txt\"",+ Posix.getPathString (Posix.asRelDir "dir" </> Posix.asRelFile "file.txt") == "dir/file.txt") :+ {-# LINE 652 "src/System/Path/Internal.hs" #-}+ ("Windows.getPathString (Windows.asAbsDir \"\\\\tmp\" Windows.</> Windows.asRelFile \"file.txt\") == \"\\\\tmp\\\\file.txt\"",+ Windows.getPathString (Windows.asAbsDir "\\tmp" Windows.</> Windows.asRelFile "file.txt") == "\\tmp\\file.txt") :+ {-# LINE 653 "src/System/Path/Internal.hs" #-}+ ("Windows.getPathString (Windows.asAbsDir \"c:\\\\tmp\" Windows.</> Windows.asRelFile \"file.txt\") == \"c:\\\\tmp\\\\file.txt\"",+ Windows.getPathString (Windows.asAbsDir "c:\\tmp" Windows.</> Windows.asRelFile "file.txt") == "c:\\tmp\\file.txt") :+ {-# LINE 654 "src/System/Path/Internal.hs" #-}+ ("Windows.getPathString (Windows.asAbsDir \"c:\" Windows.</> Windows.asRelDir \"tmp\" Windows.</> Windows.asRelFile \"file.txt\") == \"c:\\\\tmp\\\\file.txt\"",+ Windows.getPathString (Windows.asAbsDir "c:" Windows.</> Windows.asRelDir "tmp" Windows.</> Windows.asRelFile "file.txt") == "c:\\tmp\\file.txt") :+ {-# LINE 655 "src/System/Path/Internal.hs" #-}+ ("Windows.getPathString (Windows.asRelDir \"dir\" Windows.</> Windows.asRelFile \"file.txt\") == \"dir\\\\file.txt\"",+ Windows.getPathString (Windows.asRelDir "dir" Windows.</> Windows.asRelFile "file.txt") == "dir\\file.txt") :+ {-# LINE 673 "src/System/Path/Internal.hs" #-}+ ("Posix.addExtension (Posix.asRelFile \"file.txt\") \"bib\" == \"file.txt.bib\"",+ Posix.addExtension (Posix.asRelFile "file.txt") "bib" == "file.txt.bib") :+ {-# LINE 674 "src/System/Path/Internal.hs" #-}+ ("Posix.addExtension (Posix.asRelFile \"file.\") \".bib\" == \"file..bib\"",+ Posix.addExtension (Posix.asRelFile "file.") ".bib" == "file..bib") :+ {-# LINE 675 "src/System/Path/Internal.hs" #-}+ ("Posix.addExtension (Posix.asRelFile \"file\") \".bib\" == \"file.bib\"",+ Posix.addExtension (Posix.asRelFile "file") ".bib" == "file.bib") :+ {-# LINE 676 "src/System/Path/Internal.hs" #-}+ ("Posix.addExtension (Posix.asRelFile \"\") \"bib\" == \".bib\"",+ Posix.addExtension (Posix.asRelFile "") "bib" == ".bib") :+ {-# LINE 677 "src/System/Path/Internal.hs" #-}+ ("Posix.addExtension (Posix.asRelFile \"\") \".bib\" == \".bib\"",+ Posix.addExtension (Posix.asRelFile "") ".bib" == ".bib") :+ {-# LINE 678 "src/System/Path/Internal.hs" #-}+ ("Posix.takeFileName (Posix.addExtension (Posix.asRelFile \"\") \"ext\") == \".ext\"",+ Posix.takeFileName (Posix.addExtension (Posix.asRelFile "") "ext") == ".ext") :+ {-# LINE 690 "src/System/Path/Internal.hs" #-}+ ("Posix.dropExtension x == fst (Posix.splitExtension x)",+ Posix.dropExtension x == fst (Posix.splitExtension x)) :+ {-# LINE 696 "src/System/Path/Internal.hs" #-}+ ("not $ Posix.hasAnExtension (Posix.dropExtensions x)",+ not $ Posix.hasAnExtension (Posix.dropExtensions x)) :+ {-# LINE 707 "src/System/Path/Internal.hs" #-}+ ("Posix.replaceExtension (Posix.asRelFile \"file.txt\") \".bob\" == \"file.bob\"",+ Posix.replaceExtension (Posix.asRelFile "file.txt") ".bob" == "file.bob") :+ {-# LINE 708 "src/System/Path/Internal.hs" #-}+ ("Posix.replaceExtension (Posix.asRelFile \"file.txt\") \"bob\" == \"file.bob\"",+ Posix.replaceExtension (Posix.asRelFile "file.txt") "bob" == "file.bob") :+ {-# LINE 709 "src/System/Path/Internal.hs" #-}+ ("Posix.replaceExtension (Posix.asRelFile \"file\") \".bob\" == \"file.bob\"",+ Posix.replaceExtension (Posix.asRelFile "file") ".bob" == "file.bob") :+ {-# LINE 710 "src/System/Path/Internal.hs" #-}+ ("Posix.replaceExtension (Posix.asRelFile \"file.txt\") \"\" == \"file\"",+ Posix.replaceExtension (Posix.asRelFile "file.txt") "" == "file") :+ {-# LINE 711 "src/System/Path/Internal.hs" #-}+ ("Posix.replaceExtension (Posix.asRelFile \"file.fred.bob\") \"txt\" == \"file.fred.txt\"",+ Posix.replaceExtension (Posix.asRelFile "file.fred.bob") "txt" == "file.fred.txt") :+ {-# LINE 729 "src/System/Path/Internal.hs" #-}+ ("uncurry (<.>) (Posix.splitExtension x) == x",+ uncurry (<.>) (Posix.splitExtension x) == x) :+ {-# LINE 730 "src/System/Path/Internal.hs" #-}+ ("uncurry Posix.addExtension (Posix.splitExtension x) == x",+ uncurry Posix.addExtension (Posix.splitExtension x) == x) :+ {-# LINE 731 "src/System/Path/Internal.hs" #-}+ ("Posix.splitExtension (Posix.asRelFile \"file.txt\") == (\"file\",\".txt\")",+ Posix.splitExtension (Posix.asRelFile "file.txt") == ("file",".txt")) :+ {-# LINE 732 "src/System/Path/Internal.hs" #-}+ ("Posix.splitExtension (Posix.asRelFile \"file\") == (\"file\",\"\")",+ Posix.splitExtension (Posix.asRelFile "file") == ("file","")) :+ {-# LINE 733 "src/System/Path/Internal.hs" #-}+ ("Posix.splitExtension (Posix.asRelFile \"file/file.txt\") == (\"file/file\",\".txt\")",+ Posix.splitExtension (Posix.asRelFile "file/file.txt") == ("file/file",".txt")) :+ {-# LINE 734 "src/System/Path/Internal.hs" #-}+ ("Posix.splitExtension (Posix.asRelFile \"file.txt/boris\") == (\"file.txt/boris\",\"\")",+ Posix.splitExtension (Posix.asRelFile "file.txt/boris") == ("file.txt/boris","")) :+ {-# LINE 735 "src/System/Path/Internal.hs" #-}+ ("Posix.splitExtension (Posix.asRelFile \"file.txt/boris.ext\") == (\"file.txt/boris\",\".ext\")",+ Posix.splitExtension (Posix.asRelFile "file.txt/boris.ext") == ("file.txt/boris",".ext")) :+ {-# LINE 736 "src/System/Path/Internal.hs" #-}+ ("Posix.splitExtension (Posix.asRelFile \"file/path.txt.bob.fred\") == (\"file/path.txt.bob\",\".fred\")",+ Posix.splitExtension (Posix.asRelFile "file/path.txt.bob.fred") == ("file/path.txt.bob",".fred")) :+ {-# LINE 743 "src/System/Path/Internal.hs" #-}+ ("Posix.splitExtensions (Posix.asRelFile \"file.tar.gz\") == (\"file\",\".tar.gz\")",+ Posix.splitExtensions (Posix.asRelFile "file.tar.gz") == ("file",".tar.gz")) :+ {-# LINE 760 "src/System/Path/Internal.hs" #-}+ ("Posix.takeBaseName (Posix.asAbsFile \"/tmp/somedir/myfile.txt\") == \"myfile\"",+ Posix.takeBaseName (Posix.asAbsFile "/tmp/somedir/myfile.txt") == "myfile") :+ {-# LINE 761 "src/System/Path/Internal.hs" #-}+ ("Posix.takeBaseName (Posix.asRelFile \"./myfile.txt\") == \"myfile\"",+ Posix.takeBaseName (Posix.asRelFile "./myfile.txt") == "myfile") :+ {-# LINE 762 "src/System/Path/Internal.hs" #-}+ ("Posix.takeBaseName (Posix.asRelFile \"myfile.txt\") == \"myfile\"",+ Posix.takeBaseName (Posix.asRelFile "myfile.txt") == "myfile") :+ {-# LINE 771 "src/System/Path/Internal.hs" #-}+ ("Posix.takeExtension x == snd (Posix.splitExtension x)",+ Posix.takeExtension x == snd (Posix.splitExtension x)) :+ {-# LINE 772 "src/System/Path/Internal.hs" #-}+ ("Posix.takeExtension (Posix.addExtension x \"ext\") == \".ext\"",+ Posix.takeExtension (Posix.addExtension x "ext") == ".ext") :+ {-# LINE 773 "src/System/Path/Internal.hs" #-}+ ("Posix.takeExtension (Posix.replaceExtension x \"ext\") == \".ext\"",+ Posix.takeExtension (Posix.replaceExtension x "ext") == ".ext") :+ {-# LINE 779 "src/System/Path/Internal.hs" #-}+ ("Posix.takeExtensions (Posix.asRelFile \"file.tar.gz\") == \".tar.gz\"",+ Posix.takeExtensions (Posix.asRelFile "file.tar.gz") == ".tar.gz") :+ {-# LINE 785 "src/System/Path/Internal.hs" #-}+ ("Posix.takeFileName (Posix.asAbsFile \"/tmp/somedir/myfile.txt\") == \"myfile.txt\"",+ Posix.takeFileName (Posix.asAbsFile "/tmp/somedir/myfile.txt") == "myfile.txt") :+ {-# LINE 786 "src/System/Path/Internal.hs" #-}+ ("Posix.takeFileName (Posix.asRelFile \"./myfile.txt\") == \"myfile.txt\"",+ Posix.takeFileName (Posix.asRelFile "./myfile.txt") == "myfile.txt") :+ {-# LINE 787 "src/System/Path/Internal.hs" #-}+ ("Posix.takeFileName (Posix.asRelFile \"myfile.txt\") == \"myfile.txt\"",+ Posix.takeFileName (Posix.asRelFile "myfile.txt") == "myfile.txt") :+ {-# LINE 800 "src/System/Path/Internal.hs" #-}+ (" Posix.equalFilePath \"/tmp/\" \"/tmp\"",+ Posix.equalFilePath "/tmp/" "/tmp") :+ {-# LINE 801 "src/System/Path/Internal.hs" #-}+ ("not $ Posix.equalFilePath \"/tmp\" \"tmp\"",+ not $ Posix.equalFilePath "/tmp" "tmp") :+ {-# LINE 802 "src/System/Path/Internal.hs" #-}+ (" Windows.equalFilePath \"file\" \"File\"",+ Windows.equalFilePath "file" "File") :+ {-# LINE 803 "src/System/Path/Internal.hs" #-}+ ("not $ Windows.equalFilePath \"file\" \"dir\"",+ not $ Windows.equalFilePath "file" "dir") :+ {-# LINE 817 "src/System/Path/Internal.hs" #-}+ ("Posix.joinPath [\"tmp\",\"someDir\",\"dir\"] == Posix.asRelDir \"tmp/someDir/dir\"",+ Posix.joinPath ["tmp","someDir","dir"] == Posix.asRelDir "tmp/someDir/dir") :+ {-# LINE 818 "src/System/Path/Internal.hs" #-}+ ("Posix.joinPath [\"tmp\",\"someDir\",\"file.txt\"] == Posix.asRelFile \"tmp/someDir/file.txt\"",+ Posix.joinPath ["tmp","someDir","file.txt"] == Posix.asRelFile "tmp/someDir/file.txt") :+ {-# LINE 824 "src/System/Path/Internal.hs" #-}+ ("Posix.normalise \"/tmp/fred/./jim/./file\" == Posix.asAbsFile \"/tmp/fred/jim/file\"",+ Posix.normalise "/tmp/fred/./jim/./file" == Posix.asAbsFile "/tmp/fred/jim/file") :+ {-# LINE 831 "src/System/Path/Internal.hs" #-}+ ("Posix.splitPath (Posix.asAbsDir \"/tmp/someDir/mydir.dir\") == (True, [\"tmp\",\"someDir\",\"mydir.dir\"], Nothing)",+ Posix.splitPath (Posix.asAbsDir "/tmp/someDir/mydir.dir") == (True, ["tmp","someDir","mydir.dir"], Nothing)) :+ {-# LINE 832 "src/System/Path/Internal.hs" #-}+ ("Posix.splitPath (Posix.asAbsFile \"/tmp/someDir/myfile.txt\") == (True, [\"tmp\",\"someDir\"], Just \"myfile.txt\")",+ Posix.splitPath (Posix.asAbsFile "/tmp/someDir/myfile.txt") == (True, ["tmp","someDir"], Just "myfile.txt")) :+ {-# LINE 851 "src/System/Path/Internal.hs" #-}+ ("Posix.makeRelative \"/tmp/somedir\" \"/tmp/somedir/anotherdir/file.txt\" == Posix.asRelFile \"anotherdir/file.txt\"",+ Posix.makeRelative "/tmp/somedir" "/tmp/somedir/anotherdir/file.txt" == Posix.asRelFile "anotherdir/file.txt") :+ {-# LINE 852 "src/System/Path/Internal.hs" #-}+ ("Posix.makeRelative \"/tmp/somedir\" \"/tmp/somedir/anotherdir/dir\" == Posix.asRelDir \"anotherdir/dir\"",+ Posix.makeRelative "/tmp/somedir" "/tmp/somedir/anotherdir/dir" == Posix.asRelDir "anotherdir/dir") :+ {-# LINE 853 "src/System/Path/Internal.hs" #-}+ ("Windows.makeRelative \"c:\\\\tmp\\\\somedir\" \"c:\\\\Tmp\\\\SomeDir\\\\AnotherDir\\\\File.txt\" == Windows.asRelFile \"AnotherDir\\\\File.txt\"",+ Windows.makeRelative "c:\\tmp\\somedir" "c:\\Tmp\\SomeDir\\AnotherDir\\File.txt" == Windows.asRelFile "AnotherDir\\File.txt") :+ {-# LINE 854 "src/System/Path/Internal.hs" #-}+ ("Windows.makeRelative \"c:\\\\tmp\\\\somedir\" \"c:\\\\tmp\\\\somedir\\\\anotherdir\\\\dir\" == Windows.asRelDir \"anotherdir\\\\dir\"",+ Windows.makeRelative "c:\\tmp\\somedir" "c:\\tmp\\somedir\\anotherdir\\dir" == Windows.asRelDir "anotherdir\\dir") :+ {-# LINE 867 "src/System/Path/Internal.hs" #-}+ ("Posix.makeAbsolute \"/tmp\" \"file.txt\" == Posix.asAbsFile \"/tmp/file.txt\"",+ Posix.makeAbsolute "/tmp" "file.txt" == Posix.asAbsFile "/tmp/file.txt") :+ {-# LINE 868 "src/System/Path/Internal.hs" #-}+ ("Posix.makeAbsolute \"/tmp\" \"adir/file.txt\" == Posix.asAbsFile \"/tmp/adir/file.txt\"",+ Posix.makeAbsolute "/tmp" "adir/file.txt" == Posix.asAbsFile "/tmp/adir/file.txt") :+ {-# LINE 869 "src/System/Path/Internal.hs" #-}+ ("Posix.makeAbsolute \"/tmp\" \"adir/dir\" == Posix.asAbsDir \"/tmp/adir/dir\"",+ Posix.makeAbsolute "/tmp" "adir/dir" == Posix.asAbsDir "/tmp/adir/dir") :+ {-# LINE 881 "src/System/Path/Internal.hs" #-}+ ("Posix.genericMakeAbsolute \"/tmp\" (Posix.asRelFile \"file.txt\") == \"/tmp/file.txt\"",+ Posix.genericMakeAbsolute "/tmp" (Posix.asRelFile "file.txt") == "/tmp/file.txt") :+ {-# LINE 882 "src/System/Path/Internal.hs" #-}+ ("Posix.genericMakeAbsolute \"/tmp\" (Posix.asRelFile \"adir/file.txt\") == \"/tmp/adir/file.txt\"",+ Posix.genericMakeAbsolute "/tmp" (Posix.asRelFile "adir/file.txt") == "/tmp/adir/file.txt") :+ {-# LINE 883 "src/System/Path/Internal.hs" #-}+ ("Posix.genericMakeAbsolute \"/tmp\" (Posix.asAbsFile \"adir/file.txt\") == \"/adir/file.txt\"",+ Posix.genericMakeAbsolute "/tmp" (Posix.asAbsFile "adir/file.txt") == "/adir/file.txt") :+ {-# LINE 884 "src/System/Path/Internal.hs" #-}+ ("Posix.genericMakeAbsolute \"/tmp\" (Posix.asAbsFile \"/adir/file.txt\") == \"/adir/file.txt\"",+ Posix.genericMakeAbsolute "/tmp" (Posix.asAbsFile "/adir/file.txt") == "/adir/file.txt") :+ {-# LINE 929 "src/System/Path/Internal.hs" #-}+ ("Posix.isAbsolute (Posix.asAbsFile \"fred\")",+ Posix.isAbsolute (Posix.asAbsFile "fred")) :+ {-# LINE 930 "src/System/Path/Internal.hs" #-}+ ("Posix.isAbsolute (Posix.asAbsFile \"/fred\")",+ Posix.isAbsolute (Posix.asAbsFile "/fred")) :+ {-# LINE 931 "src/System/Path/Internal.hs" #-}+ ("Windows.isAbsolute (Windows.asAbsFile \"\\\\fred\")",+ Windows.isAbsolute (Windows.asAbsFile "\\fred")) :+ {-# LINE 932 "src/System/Path/Internal.hs" #-}+ ("Windows.isAbsolute (Windows.asAbsFile \"c:\\\\fred\")",+ Windows.isAbsolute (Windows.asAbsFile "c:\\fred")) :+ {-# LINE 948 "src/System/Path/Internal.hs" #-}+ ("Posix.isRelative (Posix.asRelFile \"fred\")",+ Posix.isRelative (Posix.asRelFile "fred")) :+ {-# LINE 949 "src/System/Path/Internal.hs" #-}+ ("Posix.isRelative (Posix.asRelFile \"/fred\")",+ Posix.isRelative (Posix.asRelFile "/fred")) :+ {-# LINE 950 "src/System/Path/Internal.hs" #-}+ ("Windows.isRelative (Windows.asRelFile \"fred\")",+ Windows.isRelative (Windows.asRelFile "fred")) :+ {-# LINE 964 "src/System/Path/Internal.hs" #-}+ ("null (Posix.takeExtension x) == not (Posix.hasAnExtension x)",+ null (Posix.takeExtension x) == not (Posix.hasAnExtension x)) :+ {-# LINE 970 "src/System/Path/Internal.hs" #-}+ ("Posix.hasExtension \".hs\" (Posix.asRelFile \"MyCode.hs\")",+ Posix.hasExtension ".hs" (Posix.asRelFile "MyCode.hs")) :+ {-# LINE 971 "src/System/Path/Internal.hs" #-}+ ("Posix.hasExtension \".hs\" (Posix.asRelFile \"MyCode.bak.hs\")",+ Posix.hasExtension ".hs" (Posix.asRelFile "MyCode.bak.hs")) :+ {-# LINE 972 "src/System/Path/Internal.hs" #-}+ ("not $ Posix.hasExtension \".hs\" (Posix.asRelFile \"MyCode.hs.bak\")",+ not $ Posix.hasExtension ".hs" (Posix.asRelFile "MyCode.hs.bak")) :+ {-# LINE 990 "src/System/Path/Internal.hs" #-}+ ("Posix.extSeparator == '.'",+ Posix.extSeparator == '.') :+ {-# LINE 1001 "src/System/Path/Internal.hs" #-}+ ("Posix.isPathSeparator Posix.pathSeparator",+ Posix.isPathSeparator Posix.pathSeparator) :+ {-# LINE 1008 "src/System/Path/Internal.hs" #-}+ ("Posix.pathSeparator `elem` Posix.pathSeparators",+ Posix.pathSeparator `elem` Posix.pathSeparators) :+ {-# LINE 1019 "src/System/Path/Internal.hs" #-}+ ("Posix.isExtSeparator a == (a == Posix.extSeparator)",+ Posix.isExtSeparator a == (a == Posix.extSeparator)) :+ {-# LINE 1026 "src/System/Path/Internal.hs" #-}+ ("Posix.isPathSeparator a == (a `elem` Posix.pathSeparators)",+ Posix.isPathSeparator a == (a `elem` Posix.pathSeparators)) :+ {-# LINE 1032 "src/System/Path/Internal.hs" #-}+ ("Posix.isSearchPathSeparator a == (a == Posix.searchPathSeparator)",+ Posix.isSearchPathSeparator a == (a == Posix.searchPathSeparator)) :+ {-# LINE 1048 "src/System/Path/Internal.hs" #-}+ ("Posix.genericAddExtension \"/\" \"x\" == Posix.asAbsDir \"/.x\"",+ Posix.genericAddExtension "/" "x" == Posix.asAbsDir "/.x") :+ {-# LINE 1049 "src/System/Path/Internal.hs" #-}+ ("Posix.genericAddExtension \"/a\" \"x\" == Posix.asAbsDir \"/a.x\"",+ Posix.genericAddExtension "/a" "x" == Posix.asAbsDir "/a.x") :+ {-# LINE 1050 "src/System/Path/Internal.hs" #-}+ ("Posix.genericAddExtension \"\" \"x\" == Posix.asRelFile \".x\"",+ Posix.genericAddExtension "" "x" == Posix.asRelFile ".x") :+ {-# LINE 1051 "src/System/Path/Internal.hs" #-}+ ("Posix.genericAddExtension \"\" \"\" == Posix.asRelFile \"\"",+ Posix.genericAddExtension "" "" == Posix.asRelFile "") : []
test/TestTemplate.hs view
@@ -1,11 +1,13 @@ {-# LANGUAGE OverloadedStrings #-} module TestResult (results) where -import System.Path.Posix as Path+import qualified System.Path.Posix as Posix+import qualified System.Path.Windows as Windows+import System.Path ((</>), (<.>)) import Data.Char (toLower) -results :: Char -> Path.FilePath ar -> [(String, Bool)]+results :: (Posix.AbsRelClass ar) => Char -> Posix.FilePath ar -> [(String, Bool)] results a x = <TESTS_GO_HERE> []
tool/CreateTest.hs view
@@ -20,11 +20,23 @@ main :: IO () main = do+ let mapSndF f (a,b) = (,) a <$> f b+ let readFileNumbered path =+ zipWith (\n row -> ((path,n), row)) [(0::Int)..] . lines <$>+ readFile path testLines <-- mapMaybe (stripPrefix testPrefix) . concatMap lines <$> mapM readFile srcfiles+ mapMaybe (mapSndF $ stripPrefix testPrefix) . concat <$>+ mapM readFileNumbered srcfiles (templateHead,_:templateTail) <- break (tok `isInfixOf`) . lines <$> readFile template- let outLines = (\t -> printf " (%s,\n %s) :" (show t) t) <$> testLines+ {-+ Choose the same indentation depth as in the source file,+ such that GHC reports precise source file locations.+ -}+ let outLines =+ (\((src,n),t) ->+ printf " {-# LINE %d \"%s\" #-}\n (%s,\n %s) :"+ n src (show t) t) <$> testLines writeFile testModule $ unlines $ ("{- Do not edit! Created from " ++ template ++ " -}") :