uni-util-2.2.0.0: Util/FileNames.hs
{-# LANGUAGE CPP #-}
-- | FileNames contain facilities for manipulating filenames
-- in a hopefully OS-independent manner.
module Util.FileNames(
fileSep, -- :: Char
-- file separator
topDir, -- :: String
-- what we call the top directory.
thisDir, -- :: String
-- what we call the current directory.
trimDir, -- :: String -> String
-- trim file separator from end of name if there.
-- (intended for directories)
splitName,
-- :: String -> (String,String)
-- Returns the directory and file part of a name.
combineNames,
-- :: String -> String -> String
-- combines a directory and file name.
breakName,
-- :: String -> [String]
-- breakName splits local file name completely into
-- a sequence of file names, with the top directory
-- first. (If the first character is the file separator
-- the first list element is the empty string.)
unbreakName,
-- :: [String] -> String
-- unbreakName inverts breakName
splitExtension,
-- :: String -> Maybe (String,String)
-- Remove the (last) extension part from a file name, returning
-- the two parts. For example "foo.bar" should go to (foo,bar).
unsplitExtension,
-- :: String -> String -> String
-- reverse unsplitExtension.
recordSep,
-- :: String
-- separator for between records.
) where
#ifdef WINDOWS
fileSep = '\\'
recordSep = "\r\n"
#else
fileSep = '/'
recordSep = "\n"
#endif
fileSep :: Char
recordSep :: String
topDir :: String
topDir = [fileSep]
thisDir :: String
thisDir = "."
trimDir :: String -> String
trimDir [] = []
trimDir (name@[c])
| c==fileSep = []
| True = name
trimDir (first:rest) = first:trimDir rest
splitName :: String -> (String,String)
splitName filePath0 =
let
filePath1 = trimDir filePath0
in
case splitName1 filePath1 of
Nothing -> (thisDir,filePath1)
Just ("",filePath2) -> (topDir,filePath2)
Just simple -> simple
splitName1 :: String -> Maybe(String,String)
splitName1 [] = Nothing
splitName1 (first:remainder) =
case splitName1 remainder of
Nothing
| first == fileSep -> Just([],remainder)
| True -> Nothing
Just (dir,name) -> Just (first:dir,name)
combineNames :: String -> String -> String
combineNames dir file = dir ++ (fileSep:file)
breakName :: String -> [String]
breakName [] = [[]]
breakName (first : rest)
| (first == fileSep) = "":breakName rest
| True =
case breakName rest of
firstName : restNames -> (first:firstName) : restNames
[] -> error "breakName"
unbreakName :: [String] -> String
unbreakName [] = ""
unbreakName parts = foldr1 combineNames parts
splitExtension :: String -> Maybe (String,String)
splitExtension str = case splitExtension0 str of
Just (ne @ (name,ext)) | not (null name) && not (null ext) -> Just ne
_ -> Nothing
where
splitExtension0 [] = Nothing
splitExtension0 (c:cs) = case splitExtension0 cs of
Just (name0,ext) -> Just (c:name0,ext)
Nothing -> if c == '.' then Just ("",cs) else Nothing
unsplitExtension :: String -> String -> String
unsplitExtension name ext = name ++ "." ++ ext