{-# 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 :: Char
fileSep = Char
'/'
recordSep :: String
recordSep = String
"\n"
#endif

fileSep :: Char
recordSep :: String

topDir :: String
topDir :: String
topDir = [Char
fileSep]

thisDir :: String
thisDir :: String
thisDir = String
"."

trimDir :: String -> String
trimDir :: String -> String
trimDir [] = []
trimDir (name :: String
name@[Char
c])
   | Char
cChar -> Char -> Bool
forall a. Eq a => a -> a -> Bool
==Char
fileSep = []
   | Bool
True = String
name
trimDir (Char
first:String
rest) = Char
firstChar -> String -> String
forall a. a -> [a] -> [a]
:String -> String
trimDir String
rest

splitName :: String -> (String,String)
splitName :: String -> (String, String)
splitName String
filePath0 =
   let
      filePath1 :: String
filePath1 = String -> String
trimDir String
filePath0
   in
      case String -> Maybe (String, String)
splitName1 String
filePath1 of
         Maybe (String, String)
Nothing -> (String
thisDir,String
filePath1)
         Just (String
"",String
filePath2) -> (String
topDir,String
filePath2)
         Just (String, String)
simple -> (String, String)
simple

splitName1 :: String -> Maybe(String,String)
splitName1 :: String -> Maybe (String, String)
splitName1 [] = Maybe (String, String)
forall a. Maybe a
Nothing
splitName1 (Char
first:String
remainder) =
   case String -> Maybe (String, String)
splitName1 String
remainder of
      Maybe (String, String)
Nothing
         | Char
first Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
fileSep -> (String, String) -> Maybe (String, String)
forall a. a -> Maybe a
Just([],String
remainder)
         | Bool
True -> Maybe (String, String)
forall a. Maybe a
Nothing
      Just (String
dir,String
name) -> (String, String) -> Maybe (String, String)
forall a. a -> Maybe a
Just (Char
firstChar -> String -> String
forall a. a -> [a] -> [a]
:String
dir,String
name)

combineNames :: String -> String -> String
combineNames :: String -> String -> String
combineNames String
dir String
file = String
dir String -> String -> String
forall a. [a] -> [a] -> [a]
++ (Char
fileSepChar -> String -> String
forall a. a -> [a] -> [a]
:String
file)

breakName :: String -> [String]
breakName :: String -> [String]
breakName [] = [[]]
breakName (Char
first : String
rest)
   | (Char
first Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
fileSep) = String
""String -> [String] -> [String]
forall a. a -> [a] -> [a]
:String -> [String]
breakName String
rest
   | Bool
True =
      case String -> [String]
breakName String
rest of
         String
firstName : [String]
restNames -> (Char
firstChar -> String -> String
forall a. a -> [a] -> [a]
:String
firstName) String -> [String] -> [String]
forall a. a -> [a] -> [a]
: [String]
restNames
         [] -> String -> [String]
forall a. HasCallStack => String -> a
error String
"breakName"

unbreakName :: [String] -> String
unbreakName :: [String] -> String
unbreakName [] = String
""
unbreakName [String]
parts = (String -> String -> String) -> [String] -> String
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 String -> String -> String
combineNames [String]
parts


splitExtension :: String -> Maybe (String,String)
splitExtension :: String -> Maybe (String, String)
splitExtension String
str = case String -> Maybe (String, String)
splitExtension0 String
str of
      Just (ne :: (String, String)
ne @ (String
name,String
ext)) | Bool -> Bool
not (String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
name) Bool -> Bool -> Bool
&& Bool -> Bool
not (String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
ext) -> (String, String) -> Maybe (String, String)
forall a. a -> Maybe a
Just (String, String)
ne
      Maybe (String, String)
_ -> Maybe (String, String)
forall a. Maybe a
Nothing
   where
      splitExtension0 :: String -> Maybe (String, String)
splitExtension0 [] = Maybe (String, String)
forall a. Maybe a
Nothing
      splitExtension0 (Char
c:String
cs) = case String -> Maybe (String, String)
splitExtension0 String
cs of
         Just (String
name0,String
ext) -> (String, String) -> Maybe (String, String)
forall a. a -> Maybe a
Just (Char
cChar -> String -> String
forall a. a -> [a] -> [a]
:String
name0,String
ext)
         Maybe (String, String)
Nothing -> if Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'.' then (String, String) -> Maybe (String, String)
forall a. a -> Maybe a
Just (String
"",String
cs) else Maybe (String, String)
forall a. Maybe a
Nothing

unsplitExtension :: String -> String -> String
unsplitExtension :: String -> String -> String
unsplitExtension String
name String
ext = String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"." String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
ext