Rearrange, prettify and improve haddock
This also matches the documentation order from the filepath package more.
This commit is contained in:
parent
eb72fce33f
commit
9c199c6da2
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
module System.Posix.FilePath (
|
module System.Posix.FilePath (
|
||||||
|
|
||||||
-- * Separators
|
-- * Separator predicates
|
||||||
pathSeparator
|
pathSeparator
|
||||||
, isPathSeparator
|
, isPathSeparator
|
||||||
, searchPathSeparator
|
, searchPathSeparator
|
||||||
@ -32,20 +32,20 @@ module System.Posix.FilePath (
|
|||||||
, splitSearchPath
|
, splitSearchPath
|
||||||
, getSearchPath
|
, getSearchPath
|
||||||
|
|
||||||
-- * File extensions
|
-- * Extension functions
|
||||||
, splitExtension
|
, splitExtension
|
||||||
, takeExtension
|
, takeExtension
|
||||||
, replaceExtension
|
, replaceExtension
|
||||||
, dropExtension
|
, dropExtension
|
||||||
, addExtension
|
, addExtension
|
||||||
, hasExtension
|
, hasExtension
|
||||||
, stripExtension
|
|
||||||
, (<.>)
|
, (<.>)
|
||||||
, splitExtensions
|
, splitExtensions
|
||||||
, dropExtensions
|
, dropExtensions
|
||||||
, takeExtensions
|
, takeExtensions
|
||||||
|
, stripExtension
|
||||||
|
|
||||||
-- * Filenames/Directory names
|
-- * Filename\/directory functions
|
||||||
, splitFileName
|
, splitFileName
|
||||||
, takeFileName
|
, takeFileName
|
||||||
, replaceFileName
|
, replaceFileName
|
||||||
@ -54,29 +54,25 @@ module System.Posix.FilePath (
|
|||||||
, replaceBaseName
|
, replaceBaseName
|
||||||
, takeDirectory
|
, takeDirectory
|
||||||
, replaceDirectory
|
, replaceDirectory
|
||||||
|
|
||||||
-- * Path combinators and splitters
|
|
||||||
, combine
|
, combine
|
||||||
, (</>)
|
, (</>)
|
||||||
, splitPath
|
, splitPath
|
||||||
, joinPath
|
, joinPath
|
||||||
, splitDirectories
|
, splitDirectories
|
||||||
|
|
||||||
-- * Path conversions
|
-- * Trailing slash functions
|
||||||
, normalise
|
|
||||||
|
|
||||||
-- * Trailing path separator
|
|
||||||
, hasTrailingPathSeparator
|
, hasTrailingPathSeparator
|
||||||
, addTrailingPathSeparator
|
, addTrailingPathSeparator
|
||||||
, dropTrailingPathSeparator
|
, dropTrailingPathSeparator
|
||||||
|
|
||||||
-- * Queries
|
-- * File name manipulations
|
||||||
|
, normalise
|
||||||
|
, equalFilePath
|
||||||
, isRelative
|
, isRelative
|
||||||
, isAbsolute
|
, isAbsolute
|
||||||
, isValid
|
, isValid
|
||||||
, isFileName
|
, isFileName
|
||||||
, hasParentDir
|
, hasParentDir
|
||||||
, equalFilePath
|
|
||||||
, hiddenFile
|
, hiddenFile
|
||||||
|
|
||||||
, module System.Posix.ByteString.FilePath
|
, module System.Posix.ByteString.FilePath
|
||||||
@ -105,39 +101,52 @@ import Control.Arrow (second)
|
|||||||
-- >>> let _chr :: Word8 -> Char; _chr = chr . fromIntegral
|
-- >>> let _chr :: Word8 -> Char; _chr = chr . fromIntegral
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
-- Separator predicates
|
||||||
|
|
||||||
|
|
||||||
-- | Path separator character
|
-- | Path separator character
|
||||||
pathSeparator :: Word8
|
pathSeparator :: Word8
|
||||||
pathSeparator = _slash
|
pathSeparator = _slash
|
||||||
|
|
||||||
|
|
||||||
-- | Check if a character is the path separator
|
-- | Check if a character is the path separator
|
||||||
--
|
--
|
||||||
-- prop> \n -> (_chr n == '/') == isPathSeparator n
|
-- prop> \n -> (_chr n == '/') == isPathSeparator n
|
||||||
isPathSeparator :: Word8 -> Bool
|
isPathSeparator :: Word8 -> Bool
|
||||||
isPathSeparator = (== pathSeparator)
|
isPathSeparator = (== pathSeparator)
|
||||||
|
|
||||||
|
|
||||||
-- | Search path separator
|
-- | Search path separator
|
||||||
searchPathSeparator :: Word8
|
searchPathSeparator :: Word8
|
||||||
searchPathSeparator = _colon
|
searchPathSeparator = _colon
|
||||||
|
|
||||||
|
|
||||||
-- | Check if a character is the search path separator
|
-- | Check if a character is the search path separator
|
||||||
--
|
--
|
||||||
-- prop> \n -> (_chr n == ':') == isSearchPathSeparator n
|
-- prop> \n -> (_chr n == ':') == isSearchPathSeparator n
|
||||||
isSearchPathSeparator :: Word8 -> Bool
|
isSearchPathSeparator :: Word8 -> Bool
|
||||||
isSearchPathSeparator = (== searchPathSeparator)
|
isSearchPathSeparator = (== searchPathSeparator)
|
||||||
|
|
||||||
|
|
||||||
-- | File extension separator
|
-- | File extension separator
|
||||||
extSeparator :: Word8
|
extSeparator :: Word8
|
||||||
extSeparator = _period
|
extSeparator = _period
|
||||||
|
|
||||||
|
|
||||||
-- | Check if a character is the file extension separator
|
-- | Check if a character is the file extension separator
|
||||||
--
|
--
|
||||||
-- prop> \n -> (_chr n == '.') == isExtSeparator n
|
-- prop> \n -> (_chr n == '.') == isExtSeparator n
|
||||||
isExtSeparator :: Word8 -> Bool
|
isExtSeparator :: Word8 -> Bool
|
||||||
isExtSeparator = (== extSeparator)
|
isExtSeparator = (== extSeparator)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
------------------------
|
------------------------
|
||||||
-- $PATH methods
|
-- $PATH methods
|
||||||
|
|
||||||
|
|
||||||
-- | Take a ByteString, split it on the 'searchPathSeparator'.
|
-- | Take a ByteString, split it on the 'searchPathSeparator'.
|
||||||
-- Blank items are converted to @.@.
|
-- Blank items are converted to @.@.
|
||||||
--
|
--
|
||||||
@ -161,12 +170,15 @@ splitSearchPath = f
|
|||||||
| BS.null x = [BS.singleton _period]
|
| BS.null x = [BS.singleton _period]
|
||||||
| otherwise = [x]
|
| otherwise = [x]
|
||||||
|
|
||||||
|
|
||||||
-- | Get a list of 'RawFilePath's in the $PATH variable.
|
-- | Get a list of 'RawFilePath's in the $PATH variable.
|
||||||
getSearchPath :: IO [RawFilePath]
|
getSearchPath :: IO [RawFilePath]
|
||||||
getSearchPath = fmap (maybe [] splitSearchPath) (PE.getEnv $ fromString "PATH")
|
getSearchPath = fmap (maybe [] splitSearchPath) (PE.getEnv $ fromString "PATH")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
------------------------
|
------------------------
|
||||||
-- extension stuff
|
-- Extension functions
|
||||||
|
|
||||||
-- | Split a 'RawFilePath' into a path+filename and extension
|
-- | Split a 'RawFilePath' into a path+filename and extension
|
||||||
--
|
--
|
||||||
@ -186,6 +198,7 @@ splitExtension x = if BS.null basename
|
|||||||
(path,file) = splitFileNameRaw x
|
(path,file) = splitFileNameRaw x
|
||||||
(basename,fileExt) = BS.breakEnd isExtSeparator file
|
(basename,fileExt) = BS.breakEnd isExtSeparator file
|
||||||
|
|
||||||
|
|
||||||
-- | Get the final extension from a 'RawFilePath'
|
-- | Get the final extension from a 'RawFilePath'
|
||||||
--
|
--
|
||||||
-- >>> takeExtension "file.exe"
|
-- >>> takeExtension "file.exe"
|
||||||
@ -197,12 +210,14 @@ splitExtension x = if BS.null basename
|
|||||||
takeExtension :: RawFilePath -> ByteString
|
takeExtension :: RawFilePath -> ByteString
|
||||||
takeExtension = snd . splitExtension
|
takeExtension = snd . splitExtension
|
||||||
|
|
||||||
|
|
||||||
-- | Change a file's extension
|
-- | Change a file's extension
|
||||||
--
|
--
|
||||||
-- prop> \path -> let ext = takeExtension path in replaceExtension path ext == path
|
-- prop> \path -> let ext = takeExtension path in replaceExtension path ext == path
|
||||||
replaceExtension :: RawFilePath -> ByteString -> RawFilePath
|
replaceExtension :: RawFilePath -> ByteString -> RawFilePath
|
||||||
replaceExtension path ext = dropExtension path <.> ext
|
replaceExtension path ext = dropExtension path <.> ext
|
||||||
|
|
||||||
|
|
||||||
-- | Drop the final extension from a 'RawFilePath'
|
-- | Drop the final extension from a 'RawFilePath'
|
||||||
--
|
--
|
||||||
-- >>> dropExtension "file.exe"
|
-- >>> dropExtension "file.exe"
|
||||||
@ -214,6 +229,7 @@ replaceExtension path ext = dropExtension path <.> ext
|
|||||||
dropExtension :: RawFilePath -> RawFilePath
|
dropExtension :: RawFilePath -> RawFilePath
|
||||||
dropExtension = fst . splitExtension
|
dropExtension = fst . splitExtension
|
||||||
|
|
||||||
|
|
||||||
-- | Add an extension to a 'RawFilePath'
|
-- | Add an extension to a 'RawFilePath'
|
||||||
--
|
--
|
||||||
-- >>> addExtension "file" ".exe"
|
-- >>> addExtension "file" ".exe"
|
||||||
@ -229,10 +245,6 @@ addExtension file ext
|
|||||||
| otherwise = BS.intercalate (BS.singleton extSeparator) [file, ext]
|
| otherwise = BS.intercalate (BS.singleton extSeparator) [file, ext]
|
||||||
|
|
||||||
|
|
||||||
-- | Operator version of 'addExtension'
|
|
||||||
(<.>) :: RawFilePath -> ByteString -> RawFilePath
|
|
||||||
(<.>) = addExtension
|
|
||||||
|
|
||||||
-- | Check if a 'RawFilePath' has an extension
|
-- | Check if a 'RawFilePath' has an extension
|
||||||
--
|
--
|
||||||
-- >>> hasExtension "file"
|
-- >>> hasExtension "file"
|
||||||
@ -244,6 +256,43 @@ addExtension file ext
|
|||||||
hasExtension :: RawFilePath -> Bool
|
hasExtension :: RawFilePath -> Bool
|
||||||
hasExtension = isJust . BS.elemIndex extSeparator . takeFileName
|
hasExtension = isJust . BS.elemIndex extSeparator . takeFileName
|
||||||
|
|
||||||
|
|
||||||
|
-- | Operator version of 'addExtension'
|
||||||
|
(<.>) :: RawFilePath -> ByteString -> RawFilePath
|
||||||
|
(<.>) = addExtension
|
||||||
|
|
||||||
|
|
||||||
|
-- | Split a 'RawFilePath' on the first extension.
|
||||||
|
--
|
||||||
|
-- >>> splitExtensions "/path/file.tar.gz"
|
||||||
|
-- ("/path/file",".tar.gz")
|
||||||
|
--
|
||||||
|
-- prop> \path -> uncurry addExtension (splitExtensions path) == path
|
||||||
|
splitExtensions :: RawFilePath -> (RawFilePath, ByteString)
|
||||||
|
splitExtensions x = if BS.null basename
|
||||||
|
then (path,fileExt)
|
||||||
|
else (BS.append path basename,fileExt)
|
||||||
|
where
|
||||||
|
(path,file) = splitFileNameRaw x
|
||||||
|
(basename,fileExt) = BS.break isExtSeparator file
|
||||||
|
|
||||||
|
|
||||||
|
-- | Remove all extensions from a 'RawFilePath'
|
||||||
|
--
|
||||||
|
-- >>> dropExtensions "/path/file.tar.gz"
|
||||||
|
-- "/path/file"
|
||||||
|
dropExtensions :: RawFilePath -> RawFilePath
|
||||||
|
dropExtensions = fst . splitExtensions
|
||||||
|
|
||||||
|
|
||||||
|
-- | Take all extensions from a 'RawFilePath'
|
||||||
|
--
|
||||||
|
-- >>> takeExtensions "/path/file.tar.gz"
|
||||||
|
-- ".tar.gz"
|
||||||
|
takeExtensions :: RawFilePath -> ByteString
|
||||||
|
takeExtensions = snd . splitExtensions
|
||||||
|
|
||||||
|
|
||||||
-- | Drop the given extension from a FilePath, and the @\".\"@ preceding it.
|
-- | Drop the given extension from a FilePath, and the @\".\"@ preceding it.
|
||||||
-- Returns 'Nothing' if the FilePath does not have the given extension, or
|
-- Returns 'Nothing' if the FilePath does not have the given extension, or
|
||||||
-- 'Just' and the part before the extension if it does.
|
-- 'Just' and the part before the extension if it does.
|
||||||
@ -276,36 +325,11 @@ stripExtension bs path
|
|||||||
then bs
|
then bs
|
||||||
else extSeparator `BS.cons` bs
|
else extSeparator `BS.cons` bs
|
||||||
|
|
||||||
-- | Split a 'RawFilePath' on the first extension.
|
|
||||||
--
|
|
||||||
-- >>> splitExtensions "/path/file.tar.gz"
|
|
||||||
-- ("/path/file",".tar.gz")
|
|
||||||
--
|
|
||||||
-- prop> \path -> uncurry addExtension (splitExtensions path) == path
|
|
||||||
splitExtensions :: RawFilePath -> (RawFilePath, ByteString)
|
|
||||||
splitExtensions x = if BS.null basename
|
|
||||||
then (path,fileExt)
|
|
||||||
else (BS.append path basename,fileExt)
|
|
||||||
where
|
|
||||||
(path,file) = splitFileNameRaw x
|
|
||||||
(basename,fileExt) = BS.break isExtSeparator file
|
|
||||||
|
|
||||||
-- | Remove all extensions from a 'RawFilePath'
|
|
||||||
--
|
|
||||||
-- >>> dropExtensions "/path/file.tar.gz"
|
|
||||||
-- "/path/file"
|
|
||||||
dropExtensions :: RawFilePath -> RawFilePath
|
|
||||||
dropExtensions = fst . splitExtensions
|
|
||||||
|
|
||||||
-- | Take all extensions from a 'RawFilePath'
|
|
||||||
--
|
|
||||||
-- >>> takeExtensions "/path/file.tar.gz"
|
|
||||||
-- ".tar.gz"
|
|
||||||
takeExtensions :: RawFilePath -> ByteString
|
|
||||||
takeExtensions = snd . splitExtensions
|
|
||||||
|
|
||||||
------------------------
|
------------------------
|
||||||
-- more stuff
|
-- Filename/directory functions
|
||||||
|
|
||||||
|
|
||||||
-- | Split a 'RawFilePath' into (path,file). 'combine' is the inverse
|
-- | Split a 'RawFilePath' into (path,file). 'combine' is the inverse
|
||||||
--
|
--
|
||||||
@ -335,12 +359,14 @@ splitFileName x = if BS.null path
|
|||||||
takeFileName :: RawFilePath -> RawFilePath
|
takeFileName :: RawFilePath -> RawFilePath
|
||||||
takeFileName = snd . splitFileName
|
takeFileName = snd . splitFileName
|
||||||
|
|
||||||
|
|
||||||
-- | Change the file name
|
-- | Change the file name
|
||||||
--
|
--
|
||||||
-- prop> \path -> replaceFileName path (takeFileName path) == path
|
-- prop> \path -> replaceFileName path (takeFileName path) == path
|
||||||
replaceFileName :: RawFilePath -> ByteString -> RawFilePath
|
replaceFileName :: RawFilePath -> ByteString -> RawFilePath
|
||||||
replaceFileName x y = fst (splitFileNameRaw x) </> y
|
replaceFileName x y = fst (splitFileNameRaw x) </> y
|
||||||
|
|
||||||
|
|
||||||
-- | Drop the file name
|
-- | Drop the file name
|
||||||
--
|
--
|
||||||
-- >>> dropFileName "path/file.txt"
|
-- >>> dropFileName "path/file.txt"
|
||||||
@ -350,6 +376,7 @@ replaceFileName x y = fst (splitFileNameRaw x) </> y
|
|||||||
dropFileName :: RawFilePath -> RawFilePath
|
dropFileName :: RawFilePath -> RawFilePath
|
||||||
dropFileName = fst . splitFileName
|
dropFileName = fst . splitFileName
|
||||||
|
|
||||||
|
|
||||||
-- | Get the file name, without a trailing extension
|
-- | Get the file name, without a trailing extension
|
||||||
--
|
--
|
||||||
-- >>> takeBaseName "path/file.tar.gz"
|
-- >>> takeBaseName "path/file.tar.gz"
|
||||||
@ -359,6 +386,7 @@ dropFileName = fst . splitFileName
|
|||||||
takeBaseName :: RawFilePath -> ByteString
|
takeBaseName :: RawFilePath -> ByteString
|
||||||
takeBaseName = dropExtension . takeFileName
|
takeBaseName = dropExtension . takeFileName
|
||||||
|
|
||||||
|
|
||||||
-- | Change the base name
|
-- | Change the base name
|
||||||
--
|
--
|
||||||
-- >>> replaceBaseName "path/file.tar.gz" "bob"
|
-- >>> replaceBaseName "path/file.tar.gz" "bob"
|
||||||
@ -371,6 +399,7 @@ replaceBaseName path name = combineRaw dir (name <.> ext)
|
|||||||
(dir,file) = splitFileNameRaw path
|
(dir,file) = splitFileNameRaw path
|
||||||
ext = takeExtension file
|
ext = takeExtension file
|
||||||
|
|
||||||
|
|
||||||
-- | Get the directory, moving up one level if it's already a directory
|
-- | Get the directory, moving up one level if it's already a directory
|
||||||
--
|
--
|
||||||
-- >>> takeDirectory "path/file.txt"
|
-- >>> takeDirectory "path/file.txt"
|
||||||
@ -390,12 +419,14 @@ takeDirectory x = case () of
|
|||||||
res = fst $ BS.spanEnd isPathSeparator file
|
res = fst $ BS.spanEnd isPathSeparator file
|
||||||
file = dropFileName x
|
file = dropFileName x
|
||||||
|
|
||||||
|
|
||||||
-- | Change the directory component of a 'RawFilePath'
|
-- | Change the directory component of a 'RawFilePath'
|
||||||
--
|
--
|
||||||
-- prop> \path -> replaceDirectory path (takeDirectory path) `equalFilePath` path || takeDirectory path == "."
|
-- prop> \path -> replaceDirectory path (takeDirectory path) `equalFilePath` path || takeDirectory path == "."
|
||||||
replaceDirectory :: RawFilePath -> ByteString -> RawFilePath
|
replaceDirectory :: RawFilePath -> ByteString -> RawFilePath
|
||||||
replaceDirectory file dir = combineRaw dir (takeFileName file)
|
replaceDirectory file dir = combineRaw dir (takeFileName file)
|
||||||
|
|
||||||
|
|
||||||
-- | Join two paths together
|
-- | Join two paths together
|
||||||
--
|
--
|
||||||
-- >>> combine "/" "file"
|
-- >>> combine "/" "file"
|
||||||
@ -408,6 +439,7 @@ combine :: RawFilePath -> RawFilePath -> RawFilePath
|
|||||||
combine a b | not (BS.null b) && isPathSeparator (BS.head b) = b
|
combine a b | not (BS.null b) && isPathSeparator (BS.head b) = b
|
||||||
| otherwise = combineRaw a b
|
| otherwise = combineRaw a b
|
||||||
|
|
||||||
|
|
||||||
-- | Operator version of combine
|
-- | Operator version of combine
|
||||||
(</>) :: RawFilePath -> RawFilePath -> RawFilePath
|
(</>) :: RawFilePath -> RawFilePath -> RawFilePath
|
||||||
(</>) = combine
|
(</>) = combine
|
||||||
@ -429,6 +461,17 @@ splitPath = splitter
|
|||||||
Nothing -> [x]
|
Nothing -> [x]
|
||||||
Just runlen -> uncurry (:) . second splitter $ BS.splitAt (ix+1+runlen) x
|
Just runlen -> uncurry (:) . second splitter $ BS.splitAt (ix+1+runlen) x
|
||||||
|
|
||||||
|
|
||||||
|
-- | Join a split path back together
|
||||||
|
--
|
||||||
|
-- prop> \path -> joinPath (splitPath path) == path
|
||||||
|
--
|
||||||
|
-- >>> joinPath ["path","to","file.txt"]
|
||||||
|
-- "path/to/file.txt"
|
||||||
|
joinPath :: [RawFilePath] -> RawFilePath
|
||||||
|
joinPath = foldr (</>) BS.empty
|
||||||
|
|
||||||
|
|
||||||
-- | Like 'splitPath', but without trailing slashes
|
-- | Like 'splitPath', but without trailing slashes
|
||||||
--
|
--
|
||||||
-- >>> splitDirectories "/path/to/file.txt"
|
-- >>> splitDirectories "/path/to/file.txt"
|
||||||
@ -444,14 +487,60 @@ splitDirectories x
|
|||||||
where
|
where
|
||||||
splitter = filter (not . BS.null) . BS.split pathSeparator
|
splitter = filter (not . BS.null) . BS.split pathSeparator
|
||||||
|
|
||||||
-- | Join a split path back together
|
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
-- Trailing slash functions
|
||||||
|
|
||||||
|
-- | Check if the last character of a 'RawFilePath' is '/'.
|
||||||
--
|
--
|
||||||
-- prop> \path -> joinPath (splitPath path) == path
|
-- >>> hasTrailingPathSeparator "/path/"
|
||||||
|
-- True
|
||||||
|
-- >>> hasTrailingPathSeparator "/"
|
||||||
|
-- True
|
||||||
|
-- >>> hasTrailingPathSeparator "/path"
|
||||||
|
-- False
|
||||||
|
hasTrailingPathSeparator :: RawFilePath -> Bool
|
||||||
|
hasTrailingPathSeparator x
|
||||||
|
| BS.null x = False
|
||||||
|
| otherwise = isPathSeparator $ BS.last x
|
||||||
|
|
||||||
|
|
||||||
|
-- | Add a trailing path separator.
|
||||||
--
|
--
|
||||||
-- >>> joinPath ["path","to","file.txt"]
|
-- >>> addTrailingPathSeparator "/path"
|
||||||
-- "path/to/file.txt"
|
-- "/path/"
|
||||||
joinPath :: [RawFilePath] -> RawFilePath
|
-- >>> addTrailingPathSeparator "/path/"
|
||||||
joinPath = foldr (</>) BS.empty
|
-- "/path/"
|
||||||
|
-- >>> addTrailingPathSeparator "/"
|
||||||
|
-- "/"
|
||||||
|
addTrailingPathSeparator :: RawFilePath -> RawFilePath
|
||||||
|
addTrailingPathSeparator x = if hasTrailingPathSeparator x
|
||||||
|
then x
|
||||||
|
else x `BS.snoc` pathSeparator
|
||||||
|
|
||||||
|
|
||||||
|
-- | Remove a trailing path separator
|
||||||
|
--
|
||||||
|
-- >>> dropTrailingPathSeparator "/path/"
|
||||||
|
-- "/path"
|
||||||
|
-- >>> dropTrailingPathSeparator "/path////"
|
||||||
|
-- "/path"
|
||||||
|
-- >>> dropTrailingPathSeparator "/"
|
||||||
|
-- "/"
|
||||||
|
-- >>> dropTrailingPathSeparator "//"
|
||||||
|
-- "/"
|
||||||
|
dropTrailingPathSeparator :: RawFilePath -> RawFilePath
|
||||||
|
dropTrailingPathSeparator x
|
||||||
|
| x == BS.singleton pathSeparator = x
|
||||||
|
| otherwise = if hasTrailingPathSeparator x
|
||||||
|
then dropTrailingPathSeparator $ BS.init x
|
||||||
|
else x
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
-- File name manipulations
|
||||||
|
|
||||||
|
|
||||||
-- |Normalise a file.
|
-- |Normalise a file.
|
||||||
@ -507,54 +596,36 @@ normalise filepath =
|
|||||||
dropDots :: [ByteString] -> [ByteString]
|
dropDots :: [ByteString] -> [ByteString]
|
||||||
dropDots = filter (BS.singleton _period /=)
|
dropDots = filter (BS.singleton _period /=)
|
||||||
|
|
||||||
------------------------
|
|
||||||
-- trailing path separators
|
|
||||||
|
|
||||||
-- | Check if the last character of a 'RawFilePath' is '/'.
|
-- |Equality of two filepaths. The filepaths are normalised
|
||||||
|
-- and trailing path separators are dropped.
|
||||||
--
|
--
|
||||||
-- >>> hasTrailingPathSeparator "/path/"
|
-- >>> equalFilePath "foo" "foo"
|
||||||
-- True
|
-- True
|
||||||
-- >>> hasTrailingPathSeparator "/"
|
-- >>> equalFilePath "foo" "foo/"
|
||||||
-- True
|
-- True
|
||||||
-- >>> hasTrailingPathSeparator "/path"
|
-- >>> equalFilePath "foo" "./foo"
|
||||||
|
-- True
|
||||||
|
-- >>> equalFilePath "foo" "/foo"
|
||||||
|
-- False
|
||||||
|
-- >>> equalFilePath "foo" "FOO"
|
||||||
|
-- False
|
||||||
|
-- >>> equalFilePath "foo" "../foo"
|
||||||
-- False
|
-- False
|
||||||
hasTrailingPathSeparator :: RawFilePath -> Bool
|
|
||||||
hasTrailingPathSeparator x
|
|
||||||
| BS.null x = False
|
|
||||||
| otherwise = isPathSeparator $ BS.last x
|
|
||||||
|
|
||||||
-- | Add a trailing path separator.
|
|
||||||
--
|
--
|
||||||
-- >>> addTrailingPathSeparator "/path"
|
-- prop> \p -> equalFilePath p p
|
||||||
-- "/path/"
|
equalFilePath :: RawFilePath -> RawFilePath -> Bool
|
||||||
-- >>> addTrailingPathSeparator "/path/"
|
equalFilePath p1 p2 = f p1 == f p2
|
||||||
-- "/path/"
|
where
|
||||||
-- >>> addTrailingPathSeparator "/"
|
f x = dropTrailingPathSeparator $ normalise x
|
||||||
-- "/"
|
|
||||||
addTrailingPathSeparator :: RawFilePath -> RawFilePath
|
|
||||||
addTrailingPathSeparator x = if hasTrailingPathSeparator x
|
|
||||||
then x
|
|
||||||
else x `BS.snoc` pathSeparator
|
|
||||||
|
|
||||||
-- | Remove a trailing path separator
|
|
||||||
|
-- | Check if a path is relative
|
||||||
--
|
--
|
||||||
-- >>> dropTrailingPathSeparator "/path/"
|
-- prop> \path -> isRelative path /= isAbsolute path
|
||||||
-- "/path"
|
isRelative :: RawFilePath -> Bool
|
||||||
-- >>> dropTrailingPathSeparator "/path////"
|
isRelative = not . isAbsolute
|
||||||
-- "/path"
|
|
||||||
-- >>> dropTrailingPathSeparator "/"
|
|
||||||
-- "/"
|
|
||||||
-- >>> dropTrailingPathSeparator "//"
|
|
||||||
-- "/"
|
|
||||||
dropTrailingPathSeparator :: RawFilePath -> RawFilePath
|
|
||||||
dropTrailingPathSeparator x
|
|
||||||
| x == BS.singleton pathSeparator = x
|
|
||||||
| otherwise = if hasTrailingPathSeparator x
|
|
||||||
then dropTrailingPathSeparator $ BS.init x
|
|
||||||
else x
|
|
||||||
|
|
||||||
------------------------
|
|
||||||
-- Filename/system stuff
|
|
||||||
|
|
||||||
-- | Check if a path is absolute
|
-- | Check if a path is absolute
|
||||||
--
|
--
|
||||||
@ -569,11 +640,6 @@ isAbsolute x
|
|||||||
| BS.length x > 0 = isPathSeparator (BS.head x)
|
| BS.length x > 0 = isPathSeparator (BS.head x)
|
||||||
| otherwise = False
|
| otherwise = False
|
||||||
|
|
||||||
-- | Check if a path is relative
|
|
||||||
--
|
|
||||||
-- prop> \path -> isRelative path /= isAbsolute path
|
|
||||||
isRelative :: RawFilePath -> Bool
|
|
||||||
isRelative = not . isAbsolute
|
|
||||||
|
|
||||||
-- | Is a FilePath valid, i.e. could you create a file like it?
|
-- | Is a FilePath valid, i.e. could you create a file like it?
|
||||||
--
|
--
|
||||||
@ -589,6 +655,7 @@ isValid filepath
|
|||||||
| _nul `BS.elem` filepath = False
|
| _nul `BS.elem` filepath = False
|
||||||
| otherwise = True
|
| otherwise = True
|
||||||
|
|
||||||
|
|
||||||
-- | Is the given path a valid filename? This includes
|
-- | Is the given path a valid filename? This includes
|
||||||
-- "." and "..".
|
-- "." and "..".
|
||||||
--
|
--
|
||||||
@ -610,6 +677,7 @@ isFileName filepath =
|
|||||||
not (BS.null filepath) &&
|
not (BS.null filepath) &&
|
||||||
not (_nul `BS.elem` filepath)
|
not (_nul `BS.elem` filepath)
|
||||||
|
|
||||||
|
|
||||||
-- | Check if the filepath has any parent directories in it.
|
-- | Check if the filepath has any parent directories in it.
|
||||||
--
|
--
|
||||||
-- >>> hasParentDir "/.."
|
-- >>> hasParentDir "/.."
|
||||||
@ -641,28 +709,6 @@ hasParentDir filepath =
|
|||||||
where
|
where
|
||||||
pathDoubleDot = BS.pack [_period, _period]
|
pathDoubleDot = BS.pack [_period, _period]
|
||||||
|
|
||||||
-- |Equality of two filepaths. The filepaths are normalised
|
|
||||||
-- and trailing path separators are dropped.
|
|
||||||
--
|
|
||||||
-- >>> equalFilePath "foo" "foo"
|
|
||||||
-- True
|
|
||||||
-- >>> equalFilePath "foo" "foo/"
|
|
||||||
-- True
|
|
||||||
-- >>> equalFilePath "foo" "./foo"
|
|
||||||
-- True
|
|
||||||
-- >>> equalFilePath "foo" "/foo"
|
|
||||||
-- False
|
|
||||||
-- >>> equalFilePath "foo" "FOO"
|
|
||||||
-- False
|
|
||||||
-- >>> equalFilePath "foo" "../foo"
|
|
||||||
-- False
|
|
||||||
--
|
|
||||||
-- prop> \p -> equalFilePath p p
|
|
||||||
equalFilePath :: RawFilePath -> RawFilePath -> Bool
|
|
||||||
equalFilePath p1 p2 = f p1 == f p2
|
|
||||||
where
|
|
||||||
f x = dropTrailingPathSeparator $ normalise x
|
|
||||||
|
|
||||||
|
|
||||||
-- | Whether the file is a hidden file.
|
-- | Whether the file is a hidden file.
|
||||||
--
|
--
|
||||||
@ -691,6 +737,8 @@ hiddenFile fp
|
|||||||
where
|
where
|
||||||
fn = takeFileName fp
|
fn = takeFileName fp
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
------------------------
|
------------------------
|
||||||
-- internal stuff
|
-- internal stuff
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user