Add splitSearchPath, getSearchPath and stripExtension

This commit is contained in:
Julian Ospald 2016-05-24 02:07:04 +02:00
parent 65bb09d133
commit eb72fce33f
No known key found for this signature in database
GPG Key ID: 511B62C09D50CD28
2 changed files with 73 additions and 2 deletions

View File

@ -32,7 +32,7 @@ library
System.Posix.FD, System.Posix.FD,
System.Posix.FilePath System.Posix.FilePath
build-depends: base >= 4.2 && <5 build-depends: base >= 4.2 && <5
, bytestring >= 0.9.2.0 , bytestring >= 0.10.8.0
, deepseq , deepseq
, exceptions , exceptions
, hspec , hspec

View File

@ -16,6 +16,7 @@
{-# OPTIONS_GHC -Wall #-} {-# OPTIONS_GHC -Wall #-}
-- TODO: makeValid, makeRelative
module System.Posix.FilePath ( module System.Posix.FilePath (
@ -27,6 +28,10 @@ module System.Posix.FilePath (
, extSeparator , extSeparator
, isExtSeparator , isExtSeparator
-- * $PATH methods
, splitSearchPath
, getSearchPath
-- * File extensions -- * File extensions
, splitExtension , splitExtension
, takeExtension , takeExtension
@ -34,6 +39,7 @@ module System.Posix.FilePath (
, dropExtension , dropExtension
, addExtension , addExtension
, hasExtension , hasExtension
, stripExtension
, (<.>) , (<.>)
, splitExtensions , splitExtensions
, dropExtensions , dropExtensions
@ -78,7 +84,9 @@ module System.Posix.FilePath (
import Data.ByteString (ByteString) import Data.ByteString (ByteString)
import qualified Data.ByteString as BS import qualified Data.ByteString as BS
import Data.String (fromString)
import System.Posix.ByteString.FilePath import System.Posix.ByteString.FilePath
import qualified System.Posix.Env.ByteString as PE
import Data.Maybe (isJust) import Data.Maybe (isJust)
import Data.Word8 import Data.Word8
@ -87,6 +95,7 @@ import Control.Arrow (second)
-- $setup -- $setup
-- >>> import Data.Char -- >>> import Data.Char
-- >>> import Data.Maybe
-- >>> import Test.QuickCheck -- >>> import Test.QuickCheck
-- >>> import Control.Applicative -- >>> import Control.Applicative
-- >>> import qualified Data.ByteString as BS -- >>> import qualified Data.ByteString as BS
@ -126,6 +135,36 @@ extSeparator = _period
isExtSeparator :: Word8 -> Bool isExtSeparator :: Word8 -> Bool
isExtSeparator = (== extSeparator) isExtSeparator = (== extSeparator)
------------------------
-- $PATH methods
-- | Take a ByteString, split it on the 'searchPathSeparator'.
-- Blank items are converted to @.@.
--
-- Follows the recommendations in
-- <http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html>
--
-- >>> splitSearchPath "File1:File2:File3"
-- ["File1","File2","File3"]
-- >>> splitSearchPath "File1::File2:File3"
-- ["File1",".","File2","File3"]
-- >>> splitSearchPath ""
-- ["."]
splitSearchPath :: ByteString -> [RawFilePath]
splitSearchPath = f
where
f bs = let (pre, post) = BS.break isSearchPathSeparator bs
in if BS.null post
then g pre
else g pre ++ f (BS.tail post)
g x
| BS.null x = [BS.singleton _period]
| otherwise = [x]
-- | Get a list of 'RawFilePath's in the $PATH variable.
getSearchPath :: IO [RawFilePath]
getSearchPath = fmap (maybe [] splitSearchPath) (PE.getEnv $ fromString "PATH")
------------------------ ------------------------
-- extension stuff -- extension stuff
@ -205,7 +244,39 @@ addExtension file ext
hasExtension :: RawFilePath -> Bool hasExtension :: RawFilePath -> Bool
hasExtension = isJust . BS.elemIndex extSeparator . takeFileName hasExtension = isJust . BS.elemIndex extSeparator . takeFileName
-- | Split a 'RawFilePath' on the first extension -- | Drop the given extension from a FilePath, and the @\".\"@ preceding it.
-- Returns 'Nothing' if the FilePath does not have the given extension, or
-- 'Just' and the part before the extension if it does.
--
-- This function can be more predictable than 'dropExtensions',
-- especially if the filename might itself contain @.@ characters.
--
-- >>> stripExtension "hs.o" "foo.x.hs.o"
-- Just "foo.x"
-- >>> stripExtension "hi.o" "foo.x.hs.o"
-- Nothing
-- >>> stripExtension ".c.d" "a.b.c.d"
-- Just "a.b"
-- >>> stripExtension ".c.d" "a.b..c.d"
-- Just "a.b."
-- >>> stripExtension "baz" "foo.bar"
-- Nothing
-- >>> stripExtension "bar" "foobar"
-- Nothing
--
-- prop> \path -> stripExtension "" path == Just path
-- prop> \path -> dropExtension path == fromJust (stripExtension (takeExtension path) path)
-- prop> \path -> dropExtensions path == fromJust (stripExtension (takeExtensions path) path)
stripExtension :: ByteString -> RawFilePath -> Maybe RawFilePath
stripExtension bs path
| BS.null bs = Just path
| otherwise = BS.stripSuffix dotExt path
where
dotExt = if isExtSeparator $ BS.head bs
then bs
else extSeparator `BS.cons` bs
-- | Split a 'RawFilePath' on the first extension.
-- --
-- >>> splitExtensions "/path/file.tar.gz" -- >>> splitExtensions "/path/file.tar.gz"
-- ("/path/file",".tar.gz") -- ("/path/file",".tar.gz")