kit-0.6.6: Kit/Spec.hs
{-# LANGUAGE PackageImports #-}
module Kit.Spec (
-- | The Core Kit types
KitSpec(..),
Kit(..),
updateVersion,
-- | Duck typing the name/version of a Kit/Spec
Packageable(..),
packageFileName,
-- | Utils
defaultSpec,
-- | Serialisation
decodeSpec,
encodeSpec,
writeSpec
) where
import Control.Applicative
import "mtl" Control.Monad.Trans
import Data.Object
import Kit.Util.IsObject
import qualified Data.ByteString as BS
import qualified Data.Object.Yaml as Y
data KitSpec = KitSpec {
specKit :: Kit,
specDependencies :: [Kit],
specSourceDirectory :: FilePath,
specTestDirectory :: FilePath,
specLibDirectory :: FilePath,
specResourcesDirectory :: FilePath,
specPrefixFile :: FilePath,
specConfigFile :: FilePath,
specKitDepsXcodeFlags :: Maybe String
} deriving (Show, Read, Eq)
updateVersion :: KitSpec -> (String -> String) -> KitSpec
updateVersion spec f = spec { specKit = (specKit spec) { kitVersion = f . kitVersion . specKit $ spec } }
data Kit = Kit {
kitName :: String,
kitVersion :: String
} deriving (Eq, Show, Ord, Read)
class Packageable a where
packageName :: a -> String
packageVersion :: a -> String
packageFileName :: Packageable a => a -> String
packageFileName a = packageName a ++ "-" ++ packageVersion a
instance Packageable Kit where
packageName = kitName
packageVersion = kitVersion
instance Packageable KitSpec where
packageName = kitName . specKit
packageVersion = kitVersion . specKit
defaultSpec :: String -> String -> KitSpec
defaultSpec name version = KitSpec (Kit name version) [] "src" "test" "lib" "resources" "Prefix.pch" "Config.xcconfig" Nothing
-- TODO make this and the json reading use the same defaults
-- I suspect that to do this I'll need update functions for each of
-- fields in the KitSpec record.
-- Look at the 'lenses' package on hackage.
decodeSpec :: BS.ByteString -> Maybe KitSpec
decodeSpec s = Y.decode s >>= readObject
encodeSpec :: KitSpec -> BS.ByteString
encodeSpec = Y.encode . showObject
writeSpec :: MonadIO m => FilePath -> KitSpec -> m ()
writeSpec fp spec = liftIO $ BS.writeFile fp $ encodeSpec spec
instance ShowObject Kit where
showObject kit = Mapping [("name", w kitName), ("version", w kitVersion)] where w f = showObject . f $ kit
instance ReadObject Kit where
readObject x = fromMapping x >>= \obj -> (Kit <$> obj #> "name" <*> obj #> "version") <|> case obj of
[(key, Scalar value)] -> Just $ Kit key value
_ -> Nothing
instance ShowObject KitSpec where
showObject spec = Mapping [
"name" ~> (val $ kitName . specKit),
"version" ~> (val $ kitVersion . specKit),
"dependencies" ~> showObject (specDependencies spec),
"source-directory" ~> val specSourceDirectory
] where a ~> b = (a, b)
val f = Scalar . f $ spec
instance ReadObject KitSpec where
readObject x = fromMapping x >>= parser
where or' a b = a <|> pure b
parser obj = KitSpec <$> readObject x
<*> (obj #> "dependencies" `or'` [])
<*> (obj #> "source-directory" `or'` "src")
<*> (obj #> "test-directory" `or'` "test")
<*> (obj #> "lib-directory" `or'` "lib")
<*> (obj #> "resources-directory" `or'` "resources")
<*> (obj #> "prefix-header" `or'` "Prefix.pch")
<*> (obj #> "xcconfig" `or'` "Config.xcconfig")
<*> (Just <$> obj #> "kitdeps-xcode-flags") `or'` Nothing