{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving, TypeFamilies #-}
module Development.Shake.Config(
readConfigFile, readConfigFileWithEnv,
usingConfigFile, usingConfig,
getConfig, getConfigKeys
) where
import Development.Shake
import Development.Shake.Classes
import qualified Development.Ninja.Parse as Ninja
import qualified Development.Ninja.Env as Ninja
import qualified Data.HashMap.Strict as Map
import qualified Data.ByteString.UTF8 as UTF8
import Data.Tuple.Extra
import Data.List
readConfigFile :: FilePath -> IO (Map.HashMap String String)
readConfigFile :: String -> IO (HashMap String String)
readConfigFile = [(String, String)] -> String -> IO (HashMap String String)
readConfigFileWithEnv []
readConfigFileWithEnv :: [(String, String)] -> FilePath -> IO (Map.HashMap String String)
readConfigFileWithEnv :: [(String, String)] -> String -> IO (HashMap String String)
readConfigFileWithEnv [(String, String)]
vars String
file = do
Env ByteString ByteString
env <- IO (Env ByteString ByteString)
forall k v. IO (Env k v)
Ninja.newEnv
((String, String) -> IO ()) -> [(String, String)] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ ((ByteString -> ByteString -> IO ())
-> (ByteString, ByteString) -> IO ()
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry (Env ByteString ByteString -> ByteString -> ByteString -> IO ()
forall k v. (Eq k, Hashable k) => Env k v -> k -> v -> IO ()
Ninja.addEnv Env ByteString ByteString
env) ((ByteString, ByteString) -> IO ())
-> ((String, String) -> (ByteString, ByteString))
-> (String, String)
-> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> ByteString
UTF8.fromString (String -> ByteString)
-> (String -> ByteString)
-> (String, String)
-> (ByteString, ByteString)
forall a a' b b'. (a -> a') -> (b -> b') -> (a, b) -> (a', b')
*** String -> ByteString
UTF8.fromString)) [(String, String)]
vars
String -> Env ByteString ByteString -> IO Ninja
Ninja.parse String
file Env ByteString ByteString
env
HashMap ByteString ByteString
mp <- Env ByteString ByteString -> IO (HashMap ByteString ByteString)
forall k v. Env k v -> IO (HashMap k v)
Ninja.fromEnv Env ByteString ByteString
env
HashMap String String -> IO (HashMap String String)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (HashMap String String -> IO (HashMap String String))
-> HashMap String String -> IO (HashMap String String)
forall a b. (a -> b) -> a -> b
$ [(String, String)] -> HashMap String String
forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
Map.fromList ([(String, String)] -> HashMap String String)
-> [(String, String)] -> HashMap String String
forall a b. (a -> b) -> a -> b
$ ((ByteString, ByteString) -> (String, String))
-> [(ByteString, ByteString)] -> [(String, String)]
forall a b. (a -> b) -> [a] -> [b]
map (ByteString -> String
UTF8.toString (ByteString -> String)
-> (ByteString -> String)
-> (ByteString, ByteString)
-> (String, String)
forall a a' b b'. (a -> a') -> (b -> b') -> (a, b) -> (a', b')
*** ByteString -> String
UTF8.toString) ([(ByteString, ByteString)] -> [(String, String)])
-> [(ByteString, ByteString)] -> [(String, String)]
forall a b. (a -> b) -> a -> b
$ HashMap ByteString ByteString -> [(ByteString, ByteString)]
forall k v. HashMap k v -> [(k, v)]
Map.toList HashMap ByteString ByteString
mp
newtype Config = Config String deriving (Int -> Config -> ShowS
[Config] -> ShowS
Config -> String
(Int -> Config -> ShowS)
-> (Config -> String) -> ([Config] -> ShowS) -> Show Config
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Config -> ShowS
showsPrec :: Int -> Config -> ShowS
$cshow :: Config -> String
show :: Config -> String
$cshowList :: [Config] -> ShowS
showList :: [Config] -> ShowS
Show,Typeable,Config -> Config -> Bool
(Config -> Config -> Bool)
-> (Config -> Config -> Bool) -> Eq Config
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Config -> Config -> Bool
== :: Config -> Config -> Bool
$c/= :: Config -> Config -> Bool
/= :: Config -> Config -> Bool
Eq,Eq Config
Eq Config =>
(Int -> Config -> Int) -> (Config -> Int) -> Hashable Config
Int -> Config -> Int
Config -> Int
forall a. Eq a => (Int -> a -> Int) -> (a -> Int) -> Hashable a
$chashWithSalt :: Int -> Config -> Int
hashWithSalt :: Int -> Config -> Int
$chash :: Config -> Int
hash :: Config -> Int
Hashable,Get Config
[Config] -> Put
Config -> Put
(Config -> Put) -> Get Config -> ([Config] -> Put) -> Binary Config
forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
$cput :: Config -> Put
put :: Config -> Put
$cget :: Get Config
get :: Get Config
$cputList :: [Config] -> Put
putList :: [Config] -> Put
Binary,Config -> ()
(Config -> ()) -> NFData Config
forall a. (a -> ()) -> NFData a
$crnf :: Config -> ()
rnf :: Config -> ()
NFData)
newtype ConfigKeys = ConfigKeys () deriving (Int -> ConfigKeys -> ShowS
[ConfigKeys] -> ShowS
ConfigKeys -> String
(Int -> ConfigKeys -> ShowS)
-> (ConfigKeys -> String)
-> ([ConfigKeys] -> ShowS)
-> Show ConfigKeys
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ConfigKeys -> ShowS
showsPrec :: Int -> ConfigKeys -> ShowS
$cshow :: ConfigKeys -> String
show :: ConfigKeys -> String
$cshowList :: [ConfigKeys] -> ShowS
showList :: [ConfigKeys] -> ShowS
Show,Typeable,ConfigKeys -> ConfigKeys -> Bool
(ConfigKeys -> ConfigKeys -> Bool)
-> (ConfigKeys -> ConfigKeys -> Bool) -> Eq ConfigKeys
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ConfigKeys -> ConfigKeys -> Bool
== :: ConfigKeys -> ConfigKeys -> Bool
$c/= :: ConfigKeys -> ConfigKeys -> Bool
/= :: ConfigKeys -> ConfigKeys -> Bool
Eq,Eq ConfigKeys
Eq ConfigKeys =>
(Int -> ConfigKeys -> Int)
-> (ConfigKeys -> Int) -> Hashable ConfigKeys
Int -> ConfigKeys -> Int
ConfigKeys -> Int
forall a. Eq a => (Int -> a -> Int) -> (a -> Int) -> Hashable a
$chashWithSalt :: Int -> ConfigKeys -> Int
hashWithSalt :: Int -> ConfigKeys -> Int
$chash :: ConfigKeys -> Int
hash :: ConfigKeys -> Int
Hashable,Get ConfigKeys
[ConfigKeys] -> Put
ConfigKeys -> Put
(ConfigKeys -> Put)
-> Get ConfigKeys -> ([ConfigKeys] -> Put) -> Binary ConfigKeys
forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
$cput :: ConfigKeys -> Put
put :: ConfigKeys -> Put
$cget :: Get ConfigKeys
get :: Get ConfigKeys
$cputList :: [ConfigKeys] -> Put
putList :: [ConfigKeys] -> Put
Binary,ConfigKeys -> ()
(ConfigKeys -> ()) -> NFData ConfigKeys
forall a. (a -> ()) -> NFData a
$crnf :: ConfigKeys -> ()
rnf :: ConfigKeys -> ()
NFData)
type instance RuleResult Config = Maybe String
type instance RuleResult ConfigKeys = [String]
usingConfigFile :: FilePath -> Rules ()
usingConfigFile :: String -> Rules ()
usingConfigFile String
file = do
() -> Action (HashMap String String)
mp <- (() -> Action (HashMap String String))
-> Rules (() -> Action (HashMap String String))
forall k v.
(Eq k, Hashable k) =>
(k -> Action v) -> Rules (k -> Action v)
newCache ((() -> Action (HashMap String String))
-> Rules (() -> Action (HashMap String String)))
-> (() -> Action (HashMap String String))
-> Rules (() -> Action (HashMap String String))
forall a b. (a -> b) -> a -> b
$ \() -> do
Partial => [String] -> Action ()
[String] -> Action ()
need [String
file]
IO (HashMap String String) -> Action (HashMap String String)
forall a. IO a -> Action a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (HashMap String String) -> Action (HashMap String String))
-> IO (HashMap String String) -> Action (HashMap String String)
forall a b. (a -> b) -> a -> b
$ String -> IO (HashMap String String)
readConfigFile String
file
(Config -> Action (Maybe String))
-> Rules (Config -> Action (Maybe String))
forall q a.
(RuleResult q ~ a, ShakeValue q, ShakeValue a, Partial) =>
(q -> Action a) -> Rules (q -> Action a)
addOracle ((Config -> Action (Maybe String))
-> Rules (Config -> Action (Maybe String)))
-> (Config -> Action (Maybe String))
-> Rules (Config -> Action (Maybe String))
forall a b. (a -> b) -> a -> b
$ \(Config String
x) -> String -> HashMap String String -> Maybe String
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
Map.lookup String
x (HashMap String String -> Maybe String)
-> Action (HashMap String String) -> Action (Maybe String)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> () -> Action (HashMap String String)
mp ()
(ConfigKeys -> Action [String])
-> Rules (ConfigKeys -> Action [String])
forall q a.
(RuleResult q ~ a, ShakeValue q, ShakeValue a, Partial) =>
(q -> Action a) -> Rules (q -> Action a)
addOracle ((ConfigKeys -> Action [String])
-> Rules (ConfigKeys -> Action [String]))
-> (ConfigKeys -> Action [String])
-> Rules (ConfigKeys -> Action [String])
forall a b. (a -> b) -> a -> b
$ \(ConfigKeys ()) -> [String] -> [String]
forall a. Ord a => [a] -> [a]
sort ([String] -> [String])
-> (HashMap String String -> [String])
-> HashMap String String
-> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HashMap String String -> [String]
forall k v. HashMap k v -> [k]
Map.keys (HashMap String String -> [String])
-> Action (HashMap String String) -> Action [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> () -> Action (HashMap String String)
mp ()
() -> Rules ()
forall a. a -> Rules a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
usingConfig :: Map.HashMap String String -> Rules ()
usingConfig :: HashMap String String -> Rules ()
usingConfig HashMap String String
mp = do
(Config -> Action (Maybe String))
-> Rules (Config -> Action (Maybe String))
forall q a.
(RuleResult q ~ a, ShakeValue q, ShakeValue a, Partial) =>
(q -> Action a) -> Rules (q -> Action a)
addOracle ((Config -> Action (Maybe String))
-> Rules (Config -> Action (Maybe String)))
-> (Config -> Action (Maybe String))
-> Rules (Config -> Action (Maybe String))
forall a b. (a -> b) -> a -> b
$ \(Config String
x) -> Maybe String -> Action (Maybe String)
forall a. a -> Action a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe String -> Action (Maybe String))
-> Maybe String -> Action (Maybe String)
forall a b. (a -> b) -> a -> b
$ String -> HashMap String String -> Maybe String
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
Map.lookup String
x HashMap String String
mp
(ConfigKeys -> Action [String])
-> Rules (ConfigKeys -> Action [String])
forall q a.
(RuleResult q ~ a, ShakeValue q, ShakeValue a, Partial) =>
(q -> Action a) -> Rules (q -> Action a)
addOracle ((ConfigKeys -> Action [String])
-> Rules (ConfigKeys -> Action [String]))
-> (ConfigKeys -> Action [String])
-> Rules (ConfigKeys -> Action [String])
forall a b. (a -> b) -> a -> b
$ \(ConfigKeys ()) -> [String] -> Action [String]
forall a. a -> Action a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([String] -> Action [String]) -> [String] -> Action [String]
forall a b. (a -> b) -> a -> b
$ [String] -> [String]
forall a. Ord a => [a] -> [a]
sort ([String] -> [String]) -> [String] -> [String]
forall a b. (a -> b) -> a -> b
$ HashMap String String -> [String]
forall k v. HashMap k v -> [k]
Map.keys HashMap String String
mp
() -> Rules ()
forall a. a -> Rules a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
getConfig :: String -> Action (Maybe String)
getConfig :: String -> Action (Maybe String)
getConfig = Config -> Action (Maybe String)
forall q a.
(RuleResult q ~ a, ShakeValue q, ShakeValue a) =>
q -> Action a
askOracle (Config -> Action (Maybe String))
-> (String -> Config) -> String -> Action (Maybe String)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Config
Config
getConfigKeys :: Action [String]
getConfigKeys :: Action [String]
getConfigKeys = ConfigKeys -> Action [String]
forall q a.
(RuleResult q ~ a, ShakeValue q, ShakeValue a) =>
q -> Action a
askOracle (ConfigKeys -> Action [String]) -> ConfigKeys -> Action [String]
forall a b. (a -> b) -> a -> b
$ () -> ConfigKeys
ConfigKeys ()