module HaskellCI.Config.Jobs where

import HaskellCI.Prelude

import qualified Distribution.Compat.CharParsing as C
import qualified Distribution.Parsec             as C
import qualified Distribution.Pretty             as C
import qualified Text.PrettyPrint                as PP

-- | Jobs
--
-- * @N:M@ - @N@ ghcs (cabal -j), @M@ threads (ghc -j)
--
-- >>> let parseJobs = C.simpleParsec :: String -> Maybe Jobs
-- >>> parseJobs "2:2"
-- Just (BothJobs 2 2)
--
-- >>> parseJobs ":2"
-- Just (GhcJobs 2)
--
-- >>> parseJobs "2"
-- Just (CabalJobs 2)
--
-- >>> parseJobs "garbage"
-- Nothing
--
data Jobs
    = CabalJobs Int
    | GhcJobs Int
    | BothJobs Int Int
  deriving (Int -> Jobs -> ShowS
[Jobs] -> ShowS
Jobs -> String
(Int -> Jobs -> ShowS)
-> (Jobs -> String) -> ([Jobs] -> ShowS) -> Show Jobs
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Jobs -> ShowS
showsPrec :: Int -> Jobs -> ShowS
$cshow :: Jobs -> String
show :: Jobs -> String
$cshowList :: [Jobs] -> ShowS
showList :: [Jobs] -> ShowS
Show)

cabalJobs :: Jobs -> Maybe Int
cabalJobs :: Jobs -> Maybe Int
cabalJobs (CabalJobs Int
n)  = Int -> Maybe Int
forall a. a -> Maybe a
Just Int
n
cabalJobs (GhcJobs Int
_)    = Maybe Int
forall a. Maybe a
Nothing
cabalJobs (BothJobs Int
n Int
_) = Int -> Maybe Int
forall a. a -> Maybe a
Just Int
n

ghcJobs :: Jobs -> Maybe Int
ghcJobs :: Jobs -> Maybe Int
ghcJobs (CabalJobs Int
_)  = Maybe Int
forall a. Maybe a
Nothing
ghcJobs (GhcJobs Int
m)    = Int -> Maybe Int
forall a. a -> Maybe a
Just Int
m
ghcJobs (BothJobs Int
_ Int
m) = Int -> Maybe Int
forall a. a -> Maybe a
Just Int
m

instance C.Parsec Jobs where
    parsec :: forall (m :: * -> *). CabalParsing m => m Jobs
parsec = m Jobs
ghc m Jobs -> m Jobs -> m Jobs
forall a. m a -> m a -> m a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> m Jobs
rest where
        ghc :: m Jobs
ghc  = Char -> m Char
forall (m :: * -> *). CharParsing m => Char -> m Char
C.char Char
':' m Char -> m Jobs -> m Jobs
forall a b. m a -> m b -> m b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> (Int -> Jobs
GhcJobs (Int -> Jobs) -> m Int -> m Jobs
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m Int
forall (m :: * -> *) a. (CharParsing m, Integral a) => m a
C.integral)
        rest :: m Jobs
rest = do
            Int
n <- m Int
forall (m :: * -> *) a. (CharParsing m, Integral a) => m a
C.integral
            Maybe Int
m' <- m Int -> m (Maybe Int)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
C.optional (Char -> m Char
forall (m :: * -> *). CharParsing m => Char -> m Char
C.char Char
':' m Char -> m Int -> m Int
forall a b. m a -> m b -> m b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> m Int
forall (m :: * -> *) a. (CharParsing m, Integral a) => m a
C.integral)
            Jobs -> m Jobs
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Jobs -> m Jobs) -> Jobs -> m Jobs
forall a b. (a -> b) -> a -> b
$ case Maybe Int
m' of
                Maybe Int
Nothing -> Int -> Jobs
CabalJobs Int
n
                Just Int
m  -> Int -> Int -> Jobs
BothJobs Int
n Int
m

instance C.Pretty Jobs where
    pretty :: Jobs -> Doc
pretty (BothJobs Int
n Int
m) = Int -> Doc
PP.int Int
n Doc -> Doc -> Doc
PP.<> Doc
PP.colon Doc -> Doc -> Doc
PP.<> Int -> Doc
PP.int Int
m
    pretty (CabalJobs Int
n)  = Int -> Doc
PP.int Int
n
    pretty (GhcJobs Int
m)    = Doc
PP.colon Doc -> Doc -> Doc
PP.<> Int -> Doc
PP.int Int
m