module Portager.DSL
( Arch(..)
, amd64
, x86
, ShowText(..)
, Name
, Atom(..)
, Use(..)
, Keyword(..)
, License(..)
, PackageConfiguration(..)
, keywordsL
, keywords
, unstable
, licencesL
, license
, Package(..)
, SetConfiguration(..)
, setPackagesL
, pkgs
, PackageSet(..)
, WithUseflags(..)
, WithDependencies(..)
, With(..)
, PortagerConfiguration(..)
) where
import Control.Monad.Identity (Identity)
import Control.Monad.State (MonadState, StateT, execStateT)
import Control.Monad.Trans.Class (lift)
import Control.Monad.Trans.Reader (ReaderT, asks)
import Control.Lens (Lens', (<>=), lens, set)
import Data.List (isPrefixOf)
import Data.Monoid ((<>))
import Data.String (IsString(..))
import Data.Text (Text)
import qualified Data.Text as Text (unwords)
newtype Arch = Arch { arch :: Text } deriving (Eq, Show)
instance IsString Arch where
fromString = Arch . fromString
amd64 :: Arch
amd64 = Arch "amd64"
x86 :: Arch
x86 = Arch "x86"
data PortagerConfiguration = PortagerConfiguration { _arch :: Arch } deriving (Eq, Show)
type PortageT c a = StateT c (ReaderT PortagerConfiguration Identity) a
class ShowText a where
showText :: a -> Text
instance ShowText Text where
showText = id
instance ShowText a => ShowText [a] where
showText = Text.unwords . map showText
type Name = Text
newtype Atom = Atom Name deriving (Eq, Ord, Show)
instance ShowText Atom where
showText (Atom n) = n
instance IsString Atom where
fromString = Atom . fromString
data Use = Use Bool Text deriving (Eq, Show)
instance Ord Use where
Use _ t `compare` Use _ t' = t `compare` t'
instance IsString Use where
fromString s
| "-" `isPrefixOf` s = Use False (fromString $ tail s)
| otherwise = Use True (fromString s)
instance ShowText Use where
showText (Use True t) = t
showText (Use False t) = "-" <> t
newtype Keyword = Keyword Text deriving (Eq, Ord, Show)
instance IsString Keyword where
fromString = Keyword . fromString
instance ShowText Keyword where
showText (Keyword k) = k
newtype License = License Text deriving (Eq, Ord, Show)
instance IsString License where
fromString = License . fromString
instance ShowText License where
showText (License l) = l
data PackageConfiguration = PackageConfiguration
{ _useflags :: [Use]
, _keywords :: [Keyword]
, _licenses :: [License]
, _dependencies :: [Package]
} deriving (Eq, Show)
instance Monoid PackageConfiguration where
mempty = PackageConfiguration mempty mempty mempty mempty
PackageConfiguration u k d l `mappend` PackageConfiguration u' k' d' l' =
PackageConfiguration (u <> u') (k <> k') (d <> d') (l <> l')
keywordsL :: Lens' PackageConfiguration [Keyword]
keywordsL = lens _keywords (\cfg nks -> cfg { _keywords = nks })
keywords :: MonadState PackageConfiguration m => [Keyword] -> m ()
keywords ks = keywordsL <>= ks
unstable :: PortageT PackageConfiguration ()
unstable = do
a <- lift $ asks _arch
keywords [ Keyword ("~" <> arch a) ]
licencesL :: Lens' PackageConfiguration [License]
licencesL = lens _licenses (\cfg nls -> cfg { _licenses = nls })
license :: MonadState PackageConfiguration m => License -> m ()
license l = licencesL <>= [l]
data Package = Package
{ _atom :: Atom
, _configuration :: PackageConfiguration
} deriving (Eq, Show)
instance Ord Package where
a `compare` b = _atom a `compare` _atom b
instance IsString Package where
fromString s = Package (fromString s) mempty
class WithUseflags a where
useL :: Lens' a [Use]
use :: [Use] -> PortageT a ()
uses :: [Use] -> PortageT a ()
uses = use
use us = useL <>= us
instance WithUseflags PackageConfiguration where
useL = lens _useflags (\cfg nus -> cfg { _useflags = nus })
instance WithUseflags SetConfiguration where
useL = lens _setUseflags (\cfg nus -> cfg { _setUseflags = nus })
class WithDependencies a where
depL :: Lens' a [Package]
dep :: [ReaderT PortagerConfiguration Identity Package] -> PortageT a ()
deps :: [ReaderT PortagerConfiguration Identity Package] -> PortageT a ()
deps = dep
dep ds = do
ds' <- lift $ sequence ds
depL <>= ds'
instance WithDependencies PackageConfiguration where
depL = lens _dependencies (\cfg nds -> cfg { _dependencies = nds })
instance WithDependencies SetConfiguration where
depL = lens _setDependencies (\cfg nds -> cfg { _setDependencies = nds })
data SetConfiguration = SetConfiguration
{ _setUseflags :: [Use]
, _setPackages :: [Package]
, _setDependencies :: [Package]
} deriving (Eq, Show)
instance Monoid SetConfiguration where
mempty = SetConfiguration mempty mempty mempty
SetConfiguration u p d `mappend` SetConfiguration u' p' d' =
SetConfiguration (u <> u') (p <> p') (d <> d')
setPackagesL :: Lens' SetConfiguration [Package]
setPackagesL = lens _setPackages (\cfg nps -> cfg { _setPackages = nps })
pkgs :: [ReaderT PortagerConfiguration Identity Package] -> PortageT SetConfiguration ()
pkgs ps = do
ps' <- lift $ sequence ps
setPackagesL <>= ps'
data PackageSet = PackageSet
{ _setName :: Name
, _setConfiguration :: SetConfiguration
} deriving (Eq, Show)
instance IsString PackageSet where
fromString s = PackageSet (fromString s) mempty
class (Monoid (Configuration w)) => With w where
type Configuration w
configurationL :: Lens' w (Configuration w)
with :: w -> PortageT (Configuration w) () -> ReaderT PortagerConfiguration Identity w
with w s = do
cfg <- execStateT s mempty
pure $ set configurationL cfg w
instance With Package where
type Configuration Package = PackageConfiguration
configurationL = lens _configuration (\p nc -> p { _configuration = nc })
instance With PackageSet where
type Configuration PackageSet = SetConfiguration
configurationL = lens _setConfiguration (\s nc -> s { _setConfiguration = nc })