{-# LANGUAGE CPP #-}#ifndef MIN_VERSION_filepath #if __GLASGOW_HASKELL__ >= 709 #define MIN_VERSION_filepath(a,b,c) 1 #else #define MIN_VERSION_filepath(a,b,c) 0 #endif #endif -- | A module for 'FilePath' operations exposing "System.FilePath" plus some additional operations.---- /Windows note:/ The extension methods ('<.>', 'takeExtension' etc) use the Posix variants since on-- Windows @\"\/\/\*\" '<.>' \"txt\"@ produces @\"\/\/\*\\\\.txt\"@-- (which is bad for 'Development.Shake.FilePattern' values).moduleDevelopment.Shake.FilePath(moduleSystem.FilePath,moduleSystem.FilePath.Posix,dropDirectory1 ,takeDirectory1 ,replaceDirectory1 ,normaliseEx ,#if !MIN_VERSION_filepath(1,4,0) (-<.>),#endif toNative ,toStandard ,exe )whereimportSystem.Info.ExtraimportqualifiedSystem.FilePathasNativeimportSystem.FilePathhiding(splitExtension,takeExtension,replaceExtension,dropExtension,addExtension,hasExtension,(<.>),splitExtensions,takeExtensions,dropExtensions#if MIN_VERSION_filepath(1,4,0) ,(-<.>)#endif )importSystem.FilePath.Posix(splitExtension,takeExtension,replaceExtension,dropExtension,addExtension,hasExtension,(<.>),splitExtensions,takeExtensions,dropExtensions#if MIN_VERSION_filepath(1,4,0) ,(-<.>)#endif )#if !MIN_VERSION_filepath(1,4,0) infixr7-<.>-- | Remove the current extension and add another, an alias for 'replaceExtension'.(-<.>)::FilePath->String->FilePath(-<.>)=replaceExtension#endif -- | Drop the first directory from a 'FilePath'. Should only be used on-- relative paths.---- > dropDirectory1 "aaa/bbb" == "bbb"-- > dropDirectory1 "aaa/" == ""-- > dropDirectory1 "aaa" == ""-- > dropDirectory1 "" == ""dropDirectory1::FilePath->FilePathdropDirectory1 =drop1.dropWhile(not.isPathSeparator)-- | Take the first component of a 'FilePath'. Should only be used on-- relative paths.---- > takeDirectory1 "aaa/bbb" == "aaa"-- > takeDirectory1 "aaa/" == "aaa"-- > takeDirectory1 "aaa" == "aaa"takeDirectory1::FilePath->FilePathtakeDirectory1 =takeWhile(not.isPathSeparator)-- | Replace the first component of a 'FilePath'. Should only be used on-- relative paths.---- > replaceDirectory1 "root/file.ext" "directory" == "directory/file.ext"-- > replaceDirectory1 "root/foo/bar/file.ext" "directory" == "directory/foo/bar/file.ext"replaceDirectory1::FilePath->String->FilePathreplaceDirectory1 x dir =dir </>dropDirectory1 x -- | Normalise a 'FilePath', applying the rules:---- * All 'pathSeparators' become 'pathSeparator' (@\/@ on Linux, @\\@ on Windows)---- * @foo\/bar\/..\/baz@ becomes @foo\/baz@ (not universally true in the presence of symlinks)---- * @foo\/.\/bar@ becomes @foo\/bar@---- * @foo\/\/bar@ becomes @foo\/bar@---- This function is not based on the 'normalise' function from the @filepath@ library, as that function-- is quite broken.normaliseEx::FilePath->FilePathnormaliseEx xs |a :b :xs <-xs ,isWindows&&sep a &&sep b ='/':f ('/':xs )-- account for UNC paths being double //|otherwise=f xs wheresep =Native.isPathSeparatorf o =toNative $deslash o $(++"/")$concatMap('/':)$reverse$g 0$reverse$split o deslash o x |x =="/"=case(pre ,pos )of(True,True)->"/"(True,False)->"/."(False,True)->"./"(False,False)->"."|otherwise=(ifpre thenidelsetail)$(ifpos thenidelseinit)x wherepre =sep $head$o ++" "pos =sep $last$" "++o g i []=replicatei ".."gi ("..":xs )=g (i +1)xs gi (".":xs )=g i xs g0(x :xs )=x :g 0xs gi (_:xs )=g (i -1)xs -- equivalent to eliminating ../xsplit xs =ifnullys then[]elsea :split b where(a ,b )=breaksep ys ys =dropWhilesep xs -- | Convert to native path separators, namely @\\@ on Windows.toNative::FilePath->FilePathtoNative =ifisWindowsthenmap(\x ->ifx =='/'then'\\'elsex )elseid-- | Convert all path separators to @/@, even on Windows.toStandard::FilePath->FilePathtoStandard =ifisWindowsthenmap(\x ->ifx =='\\'then'/'elsex )elseid-- | The extension of executables, @\"exe\"@ on Windows and @\"\"@ otherwise.exe::Stringexe =ifisWindowsthen"exe"else""