{- | Support library for users of the installation script in hsinstall. When your project has data files in a @resources@ directory, this library can be used to locate those files at runtime. -} module HSInstall ( getRsrcDir ) where import Control.Monad ( liftM2, mplus ) import System.Directory ( doesDirectoryExist ) import System.Environment ( getExecutablePath ) import System.FilePath ( (), takeDirectory, takeFileName ) {- | Get the path to the resources, relative to where the binary was installed and executed from. The argument passed here is expected to be the @getDataDir@ generated by Cabal at compile time in the @Paths_YOUR_PROJECT@ module. Usage: @ import HSInstall ( getRsrcDir ) import Paths_YOUR_PROJECT ( getDataDir ) resourcesDir <- getRsrcDir getDataDir @ -} getRsrcDir :: IO FilePath -> IO FilePath getRsrcDir cabalDataDir = maybe (fail "Unable to find resources directory") return =<< searchResult where searchResult :: IO (Maybe FilePath) searchResult = foldl (liftM2 mplus) (return Nothing) $ map (>>= mbExists) [ mkRsrcPathFHS cabalDataDir , mkRsrcPathFHSNoVer cabalDataDir , mkRsrcPathBundle ] mbExists :: FilePath -> IO (Maybe FilePath) mbExists p = do exists <- doesDirectoryExist p return $ if exists then Just p else Nothing mkRsrcPathFHS :: IO FilePath -> IO FilePath mkRsrcPathFHS cabalDataDir = do appDir <- takeFileName <$> cabalDataDir ( "share" appDir "resources" ) . takeDirectory . takeDirectory <$> getExecutablePath mkRsrcPathFHSNoVer :: IO FilePath -> IO FilePath mkRsrcPathFHSNoVer cabalDataDir = do appDir <- takeFileName <$> cabalDataDir ( "share" (removeVersion appDir) "resources" ) . takeDirectory . takeDirectory <$> getExecutablePath where removeVersion = init . reverse . dropWhile (/= '-') . reverse mkRsrcPathBundle :: IO FilePath mkRsrcPathBundle = ( "resources" ) . takeDirectory . takeDirectory <$> getExecutablePath