module System.FilePath.Glob.Utils where
import Data.List ((\\), tails)
import qualified Data.Set as Set
import System.Directory (doesDirectoryExist, getDirectoryContents)
import System.FilePath ((</>), joinPath, splitPath)
import System.IO.Unsafe (unsafeInterleaveIO)
inRange :: Ord a => (a,a) -> a -> Bool
inRange (a,b) c = c >= a && c <= b
overlap :: Ord a => (a,a) -> (a,a) -> Maybe (a,a)
overlap (a,b) (c,d) =
if b >= c
then if b >= d
then if a <= c
then Just (a,b)
else Just (c,b)
else if a <= c
then Just (a,d)
else Just (c,d)
else Nothing
addToRange :: (Ord a, Enum a) => (a,a) -> a -> Maybe (a,a)
addToRange (a,b) c
| inRange (a,b) c = Just (a,b)
| c == pred a = Just (c,b)
| c == succ b = Just (a,c)
| otherwise = Nothing
increasingSeq :: (Eq a, Enum a) => [a] -> ([a],[a])
increasingSeq [] = ([],[])
increasingSeq (x:xs) = go [x] xs
where
go is [] = (is,[])
go is@(i:_) (y:ys) =
if y == succ i
then go (y:is) ys
else (is, y:ys)
go _ _ = error "Glob.increasingSeq :: internal error"
isLeft :: Either a b -> Bool
isLeft (Left _) = True
isLeft _ = False
fromLeft :: Either a b -> a
fromLeft (Left x) = x
fromLeft _ = error "fromLeft :: Right"
dropLeadingZeroes :: String -> String
dropLeadingZeroes s =
let x = dropWhile (=='0') s
in if null x then "0" else x
pathParts :: FilePath -> [FilePath]
pathParts = map joinPath . tails . splitPath
getRecursiveContents :: FilePath -> IO [FilePath]
getRecursiveContents dir = flip catch (const $ return []) $ do
raw <- getDirectoryContents dir
let entries = raw \\ [".",".."]
absEntries =
if dir == "."
then entries
else map (dir </>) entries
(dirs,files) <- partitionM doesDirectoryExist absEntries
subs <- unsafeInterleaveIO . mapM getRecursiveContents $ dirs
return$ dir : files ++ concat subs
partitionM :: (Monad m) => (a -> m Bool) -> [a] -> m ([a], [a])
partitionM _ [] = return ([],[])
partitionM p (x:xs) = do
~(ts,fs) <- partitionM p xs
b <- p x
return $ if b
then (x:ts, fs)
else (ts, x:fs)
nubOrd :: Ord a => [a] -> [a]
nubOrd = go Set.empty
where
go _ [] = []
go set (x:xs) =
if Set.member x set
then go set xs
else x : go (Set.insert x set) xs