{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Cabal.Internal.Newtypes where
import Control.Applicative (Alternative (..), liftA2)
import Data.Char (isSpace)
import Data.Function (on)
import Data.Functor.Identity (Identity (..))
import Data.Proxy (Proxy (..))
import Network.URI (URI, parseURI, uriToString)
import qualified Data.Set as S
import qualified Distribution.Compat.CharParsing as C
import qualified Distribution.Compat.Newtype as C
import qualified Distribution.Parsec as C
import qualified Distribution.Parsec.Newtypes as C
import qualified Distribution.Pretty as C
import qualified Distribution.Version as C
import qualified Text.PrettyPrint as PP
newtype PackageLocation = PackageLocation String
deriving anyclass (C.Newtype String)
instance C.Parsec PackageLocation where
parsec = PackageLocation <$> outerTerm
where
outerTerm = ($ "") <$> outerChars
outerChars, outerChar, innerChars, innerChar :: C.CabalParsing m => m ShowS
outerChars = foldr (.) id <$> C.some outerChar
innerChars = foldr (.) id <$> C.many innerChar
outerChar = do
c <- C.satisfy $ \c -> not (isSpace c || c == '}' || c == ',')
kont c
innerChar = do
c <- C.satisfy $ \c -> not (isSpace c || c == '}')
kont c
kont :: C.CabalParsing m => Char -> m ShowS
kont c = case c of
'{' -> do
cs <- innerChars
c' <- C.char '}'
return (showChar c . cs . showChar c')
_ -> return $ showChar c
instance C.Pretty PackageLocation where
pretty (PackageLocation p) = PP.text p
newtype NoCommas = NoCommas String
deriving anyclass (C.Newtype String)
instance C.Parsec NoCommas where
parsec = NoCommas <$> liftA2 (:) (C.satisfy (not . isSpace)) (C.munch (/= ','))
instance C.Pretty NoCommas where
pretty (NoCommas p) = PP.text p
newtype HeadVersion = HeadVersion { getHeadVersion :: Maybe C.Version }
deriving anyclass (C.Newtype (Maybe C.Version))
instance C.Parsec HeadVersion where
parsec = HeadVersion Nothing <$ C.string "head" <|>
HeadVersion . Just <$> C.parsec
instance C.Pretty HeadVersion where
pretty (HeadVersion Nothing) = PP.text "head"
pretty (HeadVersion (Just v)) = C.pretty v
newtype Int' = Int' Int
deriving anyclass (C.Newtype Int)
instance C.Parsec Int' where
parsec = Int' <$> C.integral
instance C.Pretty Int' where
pretty (Int' i) = PP.int i
newtype Range = Range C.VersionRange
deriving anyclass (C.Newtype C.VersionRange)
instance C.Parsec Range where
parsec = fmap Range $ C.parsec <|> fromBool <$> C.parsec where
fromBool True = C.anyVersion
fromBool False = C.noVersion
instance C.Pretty Range where
pretty (Range r)
| equivVersionRanges r C.anyVersion = C.pretty True
| equivVersionRanges r C.noVersion = C.pretty False
| otherwise = C.pretty r
newtype AlaSet sep b a = AlaSet { getAlaSet :: S.Set a }
deriving anyclass (C.Newtype (S.Set a))
alaSet :: sep -> S.Set a -> AlaSet sep (Identity a) a
alaSet _ = AlaSet
alaSet' :: sep -> (a -> b) -> S.Set a -> AlaSet sep b a
alaSet' _ _ = AlaSet
instance (C.Newtype a b, Ord a, C.Sep sep, C.Parsec b) => C.Parsec (AlaSet sep b a) where
parsec = C.pack . S.fromList . map (C.unpack :: b -> a) <$> C.parseSep (hack (Proxy :: Proxy sep)) C.parsec
instance (C.Newtype a b, C.Sep sep, C.Pretty b) => C.Pretty (AlaSet sep b a) where
pretty = C.prettySep (hack (Proxy :: Proxy sep)) . map (C.pretty . (C.pack :: a -> b)) . S.toList . C.unpack
hack :: Proxy a -> proxy a
hack _ = undefined
newtype WrappedURI = WrapURI URI
deriving anyclass (C.Newtype URI)
instance C.Parsec WrappedURI where
parsec = do
t <- C.parsecToken
case parseURI t of
Just x -> return (WrapURI x)
Nothing -> C.unexpected $ "Not an URI: " ++ t
instance C.Pretty WrappedURI where
pretty (WrapURI uri) = PP.text (uriToString id uri "")
equivVersionRanges :: C.VersionRange -> C.VersionRange -> Bool
equivVersionRanges = on (==) C.asVersionIntervals