{-# LANGUAGE CPP #-}

module System.Environment.XDG.BaseDir
    ( getUserDataDir
    , getUserDataFile
    , getUserConfigDir
    , getUserConfigFile
    , getUserCacheDir
    , getUserCacheFile
    , getSystemDataDirs
    , getSystemDataFiles
    , getSystemConfigDirs
    , getSystemConfigFiles
    , getAllDataDirs
    , getAllDataFiles
    , getAllConfigDirs
    , getAllConfigFiles
    ) where

import Data.Maybe         ( fromMaybe )
import System.FilePath    ( (</>), splitSearchPath )
import System.Environment ( getEnvironment, getEnv )
import Control.Exception    ( try )
import System.Directory   ( getHomeDirectory )
import Control.Monad      ( liftM2 )

#if defined(mingw32_HOST_OS) || defined(__MINGW32__)

getDefault "XDG_DATA_HOME"   = getEnv "AppData"
getDefault "XDG_CONFIG_HOME" = userRelative $ "Local Settings"
getDefault "XDG_CACHE_HOME"  = userRelative $ "Local Settings" </> "Cache"
getDefault "XDG_DATA_DIRS"   = getEnv "ProgramFiles"
getDefault "XDG_CONFIG_DIRS" = getEnv "ProgramFiles"
getDefault _                 = return ""

#else

getDefault :: String -> IO String
getDefault String
"XDG_DATA_HOME"   = String -> IO String
userRelative forall a b. (a -> b) -> a -> b
$ String
".local" String -> String -> String
</> String
"share"
getDefault String
"XDG_CONFIG_HOME" = String -> IO String
userRelative forall a b. (a -> b) -> a -> b
$ String
".config"
getDefault String
"XDG_CACHE_HOME"  = String -> IO String
userRelative forall a b. (a -> b) -> a -> b
$ String
".cache"
getDefault String
"XDG_DATA_DIRS"   = forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ String
"/usr/local/share:/usr/share"
getDefault String
"XDG_CONFIG_DIRS" = forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ String
"/etc/xdg"
getDefault String
_                 = forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ String
""

#endif

-- | Get the directory for user-specific data files.
getUserDataDir      :: String -> IO FilePath
getUserDataDir :: String -> IO String
getUserDataDir      = String -> String -> IO String
singleDir String
"XDG_DATA_HOME"
-- | Get the directory for user-specific configuration files.
getUserConfigDir    :: String -> IO FilePath
getUserConfigDir :: String -> IO String
getUserConfigDir    = String -> String -> IO String
singleDir String
"XDG_CONFIG_HOME"
-- | Get the directory for user-specific cache files.
getUserCacheDir     :: String -> IO FilePath
getUserCacheDir :: String -> IO String
getUserCacheDir     = String -> String -> IO String
singleDir String
"XDG_CACHE_HOME"
-- | Get a list of the system-wide data directories.
getSystemDataDirs   :: String -> IO [FilePath]
getSystemDataDirs :: String -> IO [String]
getSystemDataDirs   = String -> String -> IO [String]
multiDirs String
"XDG_DATA_DIRS"
-- | Get a list of the system-wide configuration directories.
getSystemConfigDirs :: String -> IO [FilePath]
getSystemConfigDirs :: String -> IO [String]
getSystemConfigDirs = String -> String -> IO [String]
multiDirs String
"XDG_CONFIG_DIRS"
-- | Get a list of all data directories.
getAllDataDirs      :: String -> IO [FilePath]
getAllDataDirs :: String -> IO [String]
getAllDataDirs String
a    = forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 (:) (String -> IO String
getUserDataDir String
a) (String -> IO [String]
getSystemDataDirs String
a)
-- | Get a list of all configuration directories.
getAllConfigDirs    :: String -> IO [FilePath]
getAllConfigDirs :: String -> IO [String]
getAllConfigDirs String
a  = forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 (:) (String -> IO String
getUserConfigDir String
a) (String -> IO [String]
getSystemConfigDirs String
a)
-- | Get the path to a specific user data file.
getUserDataFile          :: String -> String -> IO FilePath
getUserDataFile :: String -> String -> IO String
getUserDataFile String
a String
f      = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (String -> String -> String
</> String
f) forall a b. (a -> b) -> a -> b
$ String -> IO String
getUserDataDir String
a
-- | Get the path to a specific user configuration file.
getUserConfigFile        :: String -> String -> IO FilePath
getUserConfigFile :: String -> String -> IO String
getUserConfigFile String
a String
f    = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (String -> String -> String
</> String
f) forall a b. (a -> b) -> a -> b
$ String -> IO String
getUserConfigDir String
a
-- | Get the path to a specific user cache file.
getUserCacheFile         :: String -> String -> IO FilePath
getUserCacheFile :: String -> String -> IO String
getUserCacheFile String
a String
f     = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (String -> String -> String
</> String
f) forall a b. (a -> b) -> a -> b
$ String -> IO String
getUserCacheDir String
a
-- | Get a list of all paths for a specific system data file.
getSystemDataFiles       :: String -> String -> IO [FilePath]
getSystemDataFiles :: String -> String -> IO [String]
getSystemDataFiles String
a String
f   = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b. (a -> b) -> [a] -> [b]
map (String -> String -> String
</> String
f)) forall a b. (a -> b) -> a -> b
$ String -> IO [String]
getSystemDataDirs String
a
-- | Get a list of all paths for a specific system configuration file.
getSystemConfigFiles     :: String -> String -> IO [FilePath]
getSystemConfigFiles :: String -> String -> IO [String]
getSystemConfigFiles String
a String
f = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b. (a -> b) -> [a] -> [b]
map (String -> String -> String
</> String
f)) forall a b. (a -> b) -> a -> b
$ String -> IO [String]
getSystemConfigDirs String
a
-- | Get a list of all paths for a specific data file.
getAllDataFiles          :: String -> String -> IO [FilePath]
getAllDataFiles :: String -> String -> IO [String]
getAllDataFiles String
a String
f      = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b. (a -> b) -> [a] -> [b]
map (String -> String -> String
</> String
f)) forall a b. (a -> b) -> a -> b
$ String -> IO [String]
getAllDataDirs String
a
-- | Get a list of all paths for a specific configuration file.
getAllConfigFiles        :: String -> String -> IO [FilePath]
getAllConfigFiles :: String -> String -> IO [String]
getAllConfigFiles String
a String
f    = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b. (a -> b) -> [a] -> [b]
map (String -> String -> String
</> String
f)) forall a b. (a -> b) -> a -> b
$ String -> IO [String]
getAllConfigDirs String
a

singleDir :: String -> String -> IO FilePath
singleDir :: String -> String -> IO String
singleDir String
key String
app = String -> IO String
envLookup String
key forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> String -> String
</> String
app)

multiDirs :: String -> String -> IO [FilePath]
multiDirs :: String -> String -> IO [String]
multiDirs String
key String
app = String -> IO String
envLookup String
key forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map (String -> String -> String
</> String
app) forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
splitSearchPath

envLookup :: String -> IO String
envLookup :: String -> IO String
envLookup String
key = do [(String, String)]
env <- IO [(String, String)]
getEnvironment
                   case forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup String
key [(String, String)]
env of
                        Just String
val -> forall (m :: * -> *) a. Monad m => a -> m a
return String
val
                        Maybe String
Nothing  -> String -> IO String
getDefault String
key

userRelative :: FilePath -> IO FilePath
userRelative :: String -> IO String
userRelative String
p = IO String
getHomeDirectory forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> String -> String
</> String
p)