@@ -122,7 +122,7 @@ import qualified Data.List as L
122
122
#ifndef OS_PATH
123
123
import Data.String (fromString )
124
124
import System.Environment (getEnv )
125
- import Prelude (String , map , FilePath , Eq , IO , id , last , init , reverse , dropWhile , null , break , take , all , elem , any , span )
125
+ import Prelude (String , map , FilePath , Eq , IO , id , reverse , dropWhile , null , break , take , all , elem , any , span )
126
126
import Data.Char (toLower , toUpper , isAsciiLower , isAsciiUpper )
127
127
import Data.List (stripPrefix , isSuffixOf , uncons , dropWhileEnd )
128
128
#define CHAR Char
@@ -299,14 +299,15 @@ getSearchPath = fmap splitSearchPath (getEnv "PATH")
299
299
-- Instead we speculatively split on the extension separator first, then check
300
300
-- whether results are well-formed.
301
301
splitExtension :: FILEPATH -> (STRING , STRING )
302
- splitExtension x
302
+ splitExtension x = case unsnoc nameDot of
303
303
-- Imagine x = "no-dots", then nameDot = ""
304
- | null nameDot = (x, mempty )
305
- -- Imagine x = "\\shared.with.dots\no-dots"
306
- | isWindows && null (dropDrive nameDot) = (x, mempty )
307
- -- Imagine x = "dir.with.dots/no-dots"
308
- | any isPathSeparator ext = (x, mempty )
309
- | otherwise = (init nameDot, extSeparator `cons` ext)
304
+ Nothing -> (x, mempty )
305
+ Just (initNameDot, _)
306
+ -- Imagine x = "\\shared.with.dots\no-dots"
307
+ | isWindows && null (dropDrive nameDot) -> (x, mempty )
308
+ -- Imagine x = "dir.with.dots/no-dots"
309
+ | any isPathSeparator ext -> (x, mempty )
310
+ | otherwise -> (initNameDot, extSeparator `cons` ext)
310
311
where
311
312
(nameDot, ext) = breakEnd isExtSeparator x
312
313
@@ -668,9 +669,9 @@ splitFileName_ fp
668
669
where
669
670
(dirSlash, file) = breakEnd isPathSeparator fp
670
671
dropExcessTrailingPathSeparators x
671
- | hasTrailingPathSeparator x
672
+ | Just lastX <- getTrailingPathSeparator x
672
673
, let x' = dropWhileEnd isPathSeparator x
673
- , otherwise = if | null x' -> singleton ( last x)
674
+ , otherwise = if | null x' -> singleton lastX
674
675
| otherwise -> addTrailingPathSeparator x'
675
676
| otherwise = x
676
677
@@ -742,10 +743,13 @@ replaceBaseName pth nam = combineAlways a (nam <.> ext)
742
743
-- > hasTrailingPathSeparator "test" == False
743
744
-- > hasTrailingPathSeparator "test/" == True
744
745
hasTrailingPathSeparator :: FILEPATH -> Bool
745
- hasTrailingPathSeparator x
746
- | null x = False
747
- | otherwise = isPathSeparator $ last x
746
+ hasTrailingPathSeparator = isJust . getTrailingPathSeparator
748
747
748
+ getTrailingPathSeparator :: FILEPATH -> Maybe CHAR
749
+ getTrailingPathSeparator x = case unsnoc x of
750
+ Just (_, lastX)
751
+ | isPathSeparator lastX -> Just lastX
752
+ _ -> Nothing
749
753
750
754
hasLeadingPathSeparator :: FILEPATH -> Bool
751
755
hasLeadingPathSeparator = maybe False (isPathSeparator . fst ) . uncons
@@ -767,11 +771,12 @@ addTrailingPathSeparator x = if hasTrailingPathSeparator x then x else x <> sing
767
771
-- > Windows: dropTrailingPathSeparator "\\" == "\\"
768
772
-- > Posix: not (hasTrailingPathSeparator (dropTrailingPathSeparator x)) || isDrive x
769
773
dropTrailingPathSeparator :: FILEPATH -> FILEPATH
770
- dropTrailingPathSeparator x =
771
- if hasTrailingPathSeparator x && not (isDrive x)
772
- then let x' = dropWhileEnd isPathSeparator x
773
- in if null x' then singleton (last x) else x'
774
- else x
774
+ dropTrailingPathSeparator x = case getTrailingPathSeparator x of
775
+ Just lastX
776
+ | not (isDrive x)
777
+ -> let x' = dropWhileEnd isPathSeparator x
778
+ in if null x' then singleton lastX else x'
779
+ _ -> x
775
780
776
781
777
782
-- | Get the directory name, move up one level.
@@ -1044,9 +1049,9 @@ normalise filepath =
1044
1049
&& not (hasTrailingPathSeparator result)
1045
1050
&& not (isRelativeDrive drv)
1046
1051
1047
- isDirPath xs = hasTrailingPathSeparator xs
1048
- || not ( null xs) && last xs == _period
1049
- && hasTrailingPathSeparator ( init xs)
1052
+ isDirPath xs = hasTrailingPathSeparator xs || case unsnoc xs of
1053
+ Nothing -> False
1054
+ Just (initXs, lastXs) -> lastXs == _period && hasTrailingPathSeparator initXs
1050
1055
1051
1056
f = joinPath . dropDots . propSep . splitDirectories
1052
1057
0 commit comments