{-# LANGUAGE OverloadedStrings #-} module HIE.Bios.Config( readConfig, Config(..), CradleConfig(..), CradleType(..) ) where import qualified Data.Text as T import qualified Data.Vector as V import qualified Data.HashMap.Strict as Map import Data.Yaml data CradleConfig = CradleConfig { cradleDependencies :: [FilePath] -- ^ Dependencies of a cradle. -- Dependencies are expected to be relative to the root directory. -- The given files are not required to exist. , cradleType :: CradleType -- ^ Type of the cradle to use. Actions to obtain -- compiler flags from are dependant on this field. } deriving (Show) data CradleType = Cabal { component :: Maybe String } | Stack | Bazel | Obelisk | Bios { prog :: FilePath -- ^ Path to program that retrieves options to compile a file , depsProg :: Maybe FilePath -- ^ Optional Path to program to obtain cradle dependencies. -- Each cradle dependency is to be expected to be on a separate line -- and relative to the root dir of the cradle, not relative -- to the location of this program. } | Direct { arguments :: [String] } | Default deriving (Show) instance FromJSON CradleType where parseJSON (Object o) = parseCradleType o parseJSON _ = fail "Not a known cradle type. Possible are: cabal, stack, bazel, obelisk, bios, direct, default" parseCradleType :: Object -> Parser CradleType parseCradleType o | Just val <- Map.lookup "cabal" o = parseCabal val | Just _val <- Map.lookup "stack" o = return Stack | Just _val <- Map.lookup "bazel" o = return Bazel | Just _val <- Map.lookup "obelisk" o = return Obelisk | Just val <- Map.lookup "bios" o = parseBios val | Just val <- Map.lookup "direct" o = parseDirect val | Just _val <- Map.lookup "default" o = return Default parseCradleType o = fail $ "Unknown cradle type: " ++ show o parseCabal :: Value -> Parser CradleType parseCabal (Object x) | Map.size x == 1 , Just (String cabalComponent) <- Map.lookup "component" x = return $ Cabal $ Just $ T.unpack cabalComponent | Map.null x = return $ Cabal Nothing | otherwise = fail "Not a valid Cabal Configuration type, following keys are allowed: component" parseCabal _ = fail "Cabal Configuration is expected to be an object." parseBios :: Value -> Parser CradleType parseBios (Object x) | 2 == Map.size x , Just (String biosProgram) <- Map.lookup "program" x , Just (String biosDepsProgram) <- Map.lookup "dependency-program" x = return $ Bios (T.unpack biosProgram) (Just (T.unpack biosDepsProgram)) | 1 == Map.size x , Just (String biosProgram) <- Map.lookup "program" x = return $ Bios (T.unpack biosProgram) Nothing | otherwise = fail "Not a valid Bios Configuration type, following keys are allowed: program, dependency-program" parseBios _ = fail "Bios Configuration is expected to be an object." parseDirect :: Value -> Parser CradleType parseDirect (Object x) | Map.size x == 1 , Just (Array v) <- Map.lookup "arguments" x = return $ Direct [T.unpack s | String s <- V.toList v] | otherwise = fail "Not a valid Direct Configuration type, following keys are allowed: arguments" parseDirect _ = fail "Direct Configuration is expected to be an object." data Config = Config { cradle :: CradleConfig } deriving (Show) instance FromJSON Config where parseJSON (Object val) = do crd <- val .: "cradle" crdDeps <- case Map.size val of 1 -> return [] 2 -> val .: "dependencies" _ -> fail "Unknown key, following keys are allowed: cradle, dependencies" return Config { cradle = CradleConfig { cradleType = crd , cradleDependencies = crdDeps } } parseJSON _ = fail "Expected a cradle: key containing the preferences, possible values: cradle, dependencies" readConfig :: FilePath -> IO Config readConfig = decodeFileThrow