module Data.ConfigManager.Reader ( readConfig ) where import Control.Monad (foldM) import System.FilePath.Posix (dropFileName, ()) import qualified Data.HashMap.Strict as M import Data.Text (Text) import qualified Data.Text.IO as T import Data.ConfigManager.Parser (parseConfig) import Data.ConfigManager.Expr import Data.ConfigManager.Config readConfig :: FilePath -> IO (Either Text Config) readConfig path = do input <- T.readFile path case parseConfig input of Left errorMessage -> return . Left $ errorMessage Right exprs -> foldM (go fileDir) (Right emptyConfig) exprs where fileDir = dropFileName path emptyConfig = Config $ M.fromList [] go :: String -> Either Text Config -> Expr -> IO (Either Text Config) go _ errorMessage@(Left _) _ = return errorMessage go fileDir (Right config) expr = case expr of Binding name value -> return . Right . Config $ M.insert name value (hashMap config) Import path -> do eitherConfig <- readConfig (fileDir path) case eitherConfig of Left errorMessage -> return . Left $ errorMessage Right importedConfig -> let unionConfig = (hashMap importedConfig) `M.union` (hashMap config) in return . Right . Config $ unionConfig