content: 
  -- | The information from Paths_rattle cleaned up
  module General.Paths(
      rattleVersionString,
      initDataDirectory,
      readDataFileHTML
      ) where
  
  import Paths_rattle
  import Control.Exception
  import Control.Monad.Extra
  import Data.Version
  import System.Directory
  import System.FilePath
  import System.IO.Unsafe
  import System.Environment
  import General.Extra
  import qualified Data.ByteString.Lazy as LBS
  
  
  rattleVersionString :: String
  rattleVersionString = showVersion version
  
  
  -- We want getDataFileName to be relative to the current directory on program startup,
  -- even if we issue a change directory command. Therefore, first call caches, future ones read.
  {-# NOINLINE dataDirs #-}
  dataDirs :: [String]
  dataDirs = unsafePerformIO $ do
      datdir <- getDataDir
      exedir <- takeDirectory <$> getExecutablePath `catchIO` \_ -> pure ""
      curdir <- getCurrentDirectory
      pure $ [datdir] ++ [exedir | exedir /= ""] ++ [curdir]
  
  -- | The data files may be located relative to the current directory, if so cache it in advance.
  initDataDirectory :: IO ()
  initDataDirectory = void $ evaluate dataDirs
  
  
  getDataFile :: FilePath -> IO FilePath
  getDataFile file = do
      let poss = map (</> file) dataDirs
      res <- filterM doesFileExist_ poss
      case res of
          [] -> fail $ unlines $ ("Could not find data file " ++ file ++ ", looked in:") : map ("  " ++) poss
          x:_ -> pure x
  
  
  readDataFileHTML :: FilePath -> IO LBS.ByteString
  readDataFileHTML file = LBS.readFile =<< getDataFile ("html" </> file)
  