{-# LANGUAGE CPP #-}
{-|
Module      : Portage.PackageId
License     : GPL-3+
Maintainer  : haskell@gentoo.org

Portage package identifiers, which unlike Cabal ones include a category.
-}
module Portage.PackageId (
    Category(..),
    PackageName(..),
    PackageId(..),
    Portage.Version(..),
    mkPackageName,
    fromCabalPackageId,
    toCabalPackageId,
    parseFriendlyPackage,
    normalizeCabalPackageName,
    normalizeCabalPackageId,
    filePathToPackageId,
    packageIdToFilePath,
    cabal_pn_to_PN
  ) where

import qualified Distribution.Compat.CharParsing as P
import qualified Distribution.Package as Cabal
import           Distribution.Parsec (CabalParsing(..), Parsec(..), explicitEitherParsec)
import           Distribution.Pretty (Pretty(..), prettyShow)

import qualified Portage.Version as Portage

import           Control.DeepSeq (NFData(..))
import qualified Data.Char as Char
import qualified Text.PrettyPrint as Disp
import           Text.PrettyPrint ((<>))
import           System.FilePath ((</>))

#if MIN_VERSION_base(4,11,0)
import Prelude hiding ((<>))
#endif

newtype Category = Category { Category -> String
unCategory :: String }
  deriving (Category -> Category -> Bool
(Category -> Category -> Bool)
-> (Category -> Category -> Bool) -> Eq Category
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Category -> Category -> Bool
$c/= :: Category -> Category -> Bool
== :: Category -> Category -> Bool
$c== :: Category -> Category -> Bool
Eq, Eq Category
Eq Category
-> (Category -> Category -> Ordering)
-> (Category -> Category -> Bool)
-> (Category -> Category -> Bool)
-> (Category -> Category -> Bool)
-> (Category -> Category -> Bool)
-> (Category -> Category -> Category)
-> (Category -> Category -> Category)
-> Ord Category
Category -> Category -> Bool
Category -> Category -> Ordering
Category -> Category -> Category
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Category -> Category -> Category
$cmin :: Category -> Category -> Category
max :: Category -> Category -> Category
$cmax :: Category -> Category -> Category
>= :: Category -> Category -> Bool
$c>= :: Category -> Category -> Bool
> :: Category -> Category -> Bool
$c> :: Category -> Category -> Bool
<= :: Category -> Category -> Bool
$c<= :: Category -> Category -> Bool
< :: Category -> Category -> Bool
$c< :: Category -> Category -> Bool
compare :: Category -> Category -> Ordering
$ccompare :: Category -> Category -> Ordering
$cp1Ord :: Eq Category
Ord, Int -> Category -> ShowS
[Category] -> ShowS
Category -> String
(Int -> Category -> ShowS)
-> (Category -> String) -> ([Category] -> ShowS) -> Show Category
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Category] -> ShowS
$cshowList :: [Category] -> ShowS
show :: Category -> String
$cshow :: Category -> String
showsPrec :: Int -> Category -> ShowS
$cshowsPrec :: Int -> Category -> ShowS
Show, ReadPrec [Category]
ReadPrec Category
Int -> ReadS Category
ReadS [Category]
(Int -> ReadS Category)
-> ReadS [Category]
-> ReadPrec Category
-> ReadPrec [Category]
-> Read Category
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Category]
$creadListPrec :: ReadPrec [Category]
readPrec :: ReadPrec Category
$creadPrec :: ReadPrec Category
readList :: ReadS [Category]
$creadList :: ReadS [Category]
readsPrec :: Int -> ReadS Category
$creadsPrec :: Int -> ReadS Category
Read)

-- | Portage-style 'PackageName', containing a 'Category' and a 'Cabal.PackageName'.
data PackageName = PackageName { PackageName -> Category
category :: Category, PackageName -> PackageName
cabalPkgName :: Cabal.PackageName }
  deriving (PackageName -> PackageName -> Bool
(PackageName -> PackageName -> Bool)
-> (PackageName -> PackageName -> Bool) -> Eq PackageName
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PackageName -> PackageName -> Bool
$c/= :: PackageName -> PackageName -> Bool
== :: PackageName -> PackageName -> Bool
$c== :: PackageName -> PackageName -> Bool
Eq, Eq PackageName
Eq PackageName
-> (PackageName -> PackageName -> Ordering)
-> (PackageName -> PackageName -> Bool)
-> (PackageName -> PackageName -> Bool)
-> (PackageName -> PackageName -> Bool)
-> (PackageName -> PackageName -> Bool)
-> (PackageName -> PackageName -> PackageName)
-> (PackageName -> PackageName -> PackageName)
-> Ord PackageName
PackageName -> PackageName -> Bool
PackageName -> PackageName -> Ordering
PackageName -> PackageName -> PackageName
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: PackageName -> PackageName -> PackageName
$cmin :: PackageName -> PackageName -> PackageName
max :: PackageName -> PackageName -> PackageName
$cmax :: PackageName -> PackageName -> PackageName
>= :: PackageName -> PackageName -> Bool
$c>= :: PackageName -> PackageName -> Bool
> :: PackageName -> PackageName -> Bool
$c> :: PackageName -> PackageName -> Bool
<= :: PackageName -> PackageName -> Bool
$c<= :: PackageName -> PackageName -> Bool
< :: PackageName -> PackageName -> Bool
$c< :: PackageName -> PackageName -> Bool
compare :: PackageName -> PackageName -> Ordering
$ccompare :: PackageName -> PackageName -> Ordering
$cp1Ord :: Eq PackageName
Ord, Int -> PackageName -> ShowS
[PackageName] -> ShowS
PackageName -> String
(Int -> PackageName -> ShowS)
-> (PackageName -> String)
-> ([PackageName] -> ShowS)
-> Show PackageName
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PackageName] -> ShowS
$cshowList :: [PackageName] -> ShowS
show :: PackageName -> String
$cshow :: PackageName -> String
showsPrec :: Int -> PackageName -> ShowS
$cshowsPrec :: Int -> PackageName -> ShowS
Show, ReadPrec [PackageName]
ReadPrec PackageName
Int -> ReadS PackageName
ReadS [PackageName]
(Int -> ReadS PackageName)
-> ReadS [PackageName]
-> ReadPrec PackageName
-> ReadPrec [PackageName]
-> Read PackageName
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [PackageName]
$creadListPrec :: ReadPrec [PackageName]
readPrec :: ReadPrec PackageName
$creadPrec :: ReadPrec PackageName
readList :: ReadS [PackageName]
$creadList :: ReadS [PackageName]
readsPrec :: Int -> ReadS PackageName
$creadsPrec :: Int -> ReadS PackageName
Read)

-- | Portage-style 'PackageId', containing a 'PackageName' and a 'Portage.Version'.
data PackageId = PackageId { PackageId -> PackageName
packageId :: PackageName, PackageId -> Version
pkgVersion :: Portage.Version }
  deriving (PackageId -> PackageId -> Bool
(PackageId -> PackageId -> Bool)
-> (PackageId -> PackageId -> Bool) -> Eq PackageId
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PackageId -> PackageId -> Bool
$c/= :: PackageId -> PackageId -> Bool
== :: PackageId -> PackageId -> Bool
$c== :: PackageId -> PackageId -> Bool
Eq, Eq PackageId
Eq PackageId
-> (PackageId -> PackageId -> Ordering)
-> (PackageId -> PackageId -> Bool)
-> (PackageId -> PackageId -> Bool)
-> (PackageId -> PackageId -> Bool)
-> (PackageId -> PackageId -> Bool)
-> (PackageId -> PackageId -> PackageId)
-> (PackageId -> PackageId -> PackageId)
-> Ord PackageId
PackageId -> PackageId -> Bool
PackageId -> PackageId -> Ordering
PackageId -> PackageId -> PackageId
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: PackageId -> PackageId -> PackageId
$cmin :: PackageId -> PackageId -> PackageId
max :: PackageId -> PackageId -> PackageId
$cmax :: PackageId -> PackageId -> PackageId
>= :: PackageId -> PackageId -> Bool
$c>= :: PackageId -> PackageId -> Bool
> :: PackageId -> PackageId -> Bool
$c> :: PackageId -> PackageId -> Bool
<= :: PackageId -> PackageId -> Bool
$c<= :: PackageId -> PackageId -> Bool
< :: PackageId -> PackageId -> Bool
$c< :: PackageId -> PackageId -> Bool
compare :: PackageId -> PackageId -> Ordering
$ccompare :: PackageId -> PackageId -> Ordering
$cp1Ord :: Eq PackageId
Ord, Int -> PackageId -> ShowS
[PackageId] -> ShowS
PackageId -> String
(Int -> PackageId -> ShowS)
-> (PackageId -> String)
-> ([PackageId] -> ShowS)
-> Show PackageId
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PackageId] -> ShowS
$cshowList :: [PackageId] -> ShowS
show :: PackageId -> String
$cshow :: PackageId -> String
showsPrec :: Int -> PackageId -> ShowS
$cshowsPrec :: Int -> PackageId -> ShowS
Show, ReadPrec [PackageId]
ReadPrec PackageId
Int -> ReadS PackageId
ReadS [PackageId]
(Int -> ReadS PackageId)
-> ReadS [PackageId]
-> ReadPrec PackageId
-> ReadPrec [PackageId]
-> Read PackageId
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [PackageId]
$creadListPrec :: ReadPrec [PackageId]
readPrec :: ReadPrec PackageId
$creadPrec :: ReadPrec PackageId
readList :: ReadS [PackageId]
$creadList :: ReadS [PackageId]
readsPrec :: Int -> ReadS PackageId
$creadsPrec :: Int -> ReadS PackageId
Read)

instance NFData Category where
  rnf :: Category -> ()
rnf (Category String
c) = String -> ()
forall a. NFData a => a -> ()
rnf String
c

instance Pretty Category where
  pretty :: Category -> Doc
pretty (Category String
c) = String -> Doc
Disp.text String
c

instance Parsec Category where
  parsec :: m Category
parsec = String -> Category
Category (String -> Category) -> m String -> m Category
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Char -> Bool) -> m String
forall (m :: * -> *). CharParsing m => (Char -> Bool) -> m String
P.munch1 Char -> Bool
categoryChar
    where
      categoryChar :: Char -> Bool
categoryChar Char
c = Char -> Bool
Char.isAlphaNum Char
c Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'-'

instance NFData PackageName where
  rnf :: PackageName -> ()
rnf (PackageName Category
c PackageName
pn) = Category -> ()
forall a. NFData a => a -> ()
rnf Category
c () -> () -> ()
`seq` PackageName -> ()
forall a. NFData a => a -> ()
rnf PackageName
pn

instance Pretty PackageName where
  pretty :: PackageName -> Doc
pretty (PackageName Category
cat PackageName
name) =
    Category -> Doc
forall a. Pretty a => a -> Doc
pretty Category
cat Doc -> Doc -> Doc
<> Char -> Doc
Disp.char Char
'/' Doc -> Doc -> Doc
<> PackageName -> Doc
forall a. Pretty a => a -> Doc
pretty PackageName
name

instance Parsec PackageName where
  parsec :: m PackageName
parsec = do
    Category
cat <- m Category
forall a (m :: * -> *). (Parsec a, CabalParsing m) => m a
parsec
    Char
_ <- Char -> m Char
forall (m :: * -> *). CharParsing m => Char -> m Char
P.char Char
'/'
    PackageName
name <- m PackageName
forall (m :: * -> *). CabalParsing m => m PackageName
parseCabalPackageName
    PackageName -> m PackageName
forall (m :: * -> *) a. Monad m => a -> m a
return (PackageName -> m PackageName) -> PackageName -> m PackageName
forall a b. (a -> b) -> a -> b
$ Category -> PackageName -> PackageName
PackageName Category
cat PackageName
name

instance NFData PackageId where
  rnf :: PackageId -> ()
rnf (PackageId PackageName
pId Version
pv) = PackageName -> ()
forall a. NFData a => a -> ()
rnf PackageName
pId () -> () -> ()
`seq` Version -> ()
forall a. NFData a => a -> ()
rnf Version
pv

instance Pretty PackageId where
  pretty :: PackageId -> Doc
pretty (PackageId PackageName
name Version
version) =
    PackageName -> Doc
forall a. Pretty a => a -> Doc
pretty PackageName
name Doc -> Doc -> Doc
<> Char -> Doc
Disp.char Char
'-' Doc -> Doc -> Doc
<> Version -> Doc
forall a. Pretty a => a -> Doc
pretty Version
version

instance Parsec PackageId where
  parsec :: m PackageId
parsec = do
    PackageName
name <- m PackageName
forall a (m :: * -> *). (Parsec a, CabalParsing m) => m a
parsec
    Char
_ <- Char -> m Char
forall (m :: * -> *). CharParsing m => Char -> m Char
P.char Char
'-'
    Version
version <- m Version
forall a (m :: * -> *). (Parsec a, CabalParsing m) => m a
parsec
    PackageId -> m PackageId
forall (m :: * -> *) a. Monad m => a -> m a
return (PackageId -> m PackageId) -> PackageId -> m PackageId
forall a b. (a -> b) -> a -> b
$ PackageName -> Version -> PackageId
PackageId PackageName
name Version
version

-- | Transform a 'PackageId' into a 'FilePath'.
-- 
-- >>> packageIdToFilePath (PackageId (PackageName (Category "dev-haskell") (Cabal.mkPackageName "foo-bar2")) (Portage.Version [3,0,0] (Just 'b') [Portage.RC 2] 1 ))
-- "dev-haskell/foo-bar2/foo-bar2-3.0.0b_rc2-r1.ebuild"
packageIdToFilePath :: PackageId -> FilePath
packageIdToFilePath :: PackageId -> String
packageIdToFilePath (PackageId (PackageName Category
cat PackageName
pn) Version
version) =
  Category -> String
forall a. Pretty a => a -> String
prettyShow Category
cat String -> ShowS
</> PackageName -> String
forall a. Pretty a => a -> String
prettyShow PackageName
pn String -> ShowS
</> PackageName -> String
forall a. Pretty a => a -> String
prettyShow PackageName
pn String -> ShowS
<-> Version -> String
forall a. Pretty a => a -> String
prettyShow Version
version String -> ShowS
<.> String
"ebuild"
  where
    String
a <-> :: String -> ShowS
<-> String
b = String
a String -> ShowS
forall a. [a] -> [a] -> [a]
++ Char
'-'Char -> ShowS
forall a. a -> [a] -> [a]
:String
b
    String
a <.> :: String -> ShowS
<.> String
b = String
a String -> ShowS
forall a. [a] -> [a] -> [a]
++ Char
'.'Char -> ShowS
forall a. a -> [a] -> [a]
:String
b

-- | Maybe generate a 'PackageId' from a 'FilePath'. Note that the 'FilePath' must have its
-- file extension stripped before being passed to 'filePathToPackageId'.
-- 
-- >>> filePathToPackageId (Category "dev-haskell") "foo-bar2-3.0.0b_rc2-r1"
-- Just (PackageId {packageId = PackageName {category = Category {unCategory = "dev-haskell"}, cabalPkgName = PackageName "foo-bar2"}, pkgVersion = Version {versionNumber = [3,0,0], versionChar = Just 'b', versionSuffix = [RC 2], versionRevision = 1}})
filePathToPackageId :: Category -> FilePath -> Maybe PackageId
filePathToPackageId :: Category -> String -> Maybe PackageId
filePathToPackageId Category
cat String
fp =
  case ParsecParser PackageId -> String -> Either String PackageId
forall a. ParsecParser a -> String -> Either String a
explicitEitherParsec ParsecParser PackageId
parser String
fp of
    Right PackageId
x -> PackageId -> Maybe PackageId
forall a. a -> Maybe a
Just PackageId
x
    Either String PackageId
_ -> Maybe PackageId
forall a. Maybe a
Nothing
  where
    parser :: ParsecParser PackageId
parser = do
      PackageName
pn <- ParsecParser PackageName
forall (m :: * -> *). CabalParsing m => m PackageName
parseCabalPackageName
      Char
_ <- Char -> ParsecParser Char
forall (m :: * -> *). CharParsing m => Char -> m Char
P.char Char
'-'
      Version
v <- ParsecParser Version
forall a (m :: * -> *). (Parsec a, CabalParsing m) => m a
parsec
      PackageId -> ParsecParser PackageId
forall (m :: * -> *) a. Monad m => a -> m a
return (PackageId -> ParsecParser PackageId)
-> PackageId -> ParsecParser PackageId
forall a b. (a -> b) -> a -> b
$ PackageName -> Version -> PackageId
PackageId (Category -> PackageName -> PackageName
PackageName Category
cat PackageName
pn) Version
v

-- | Create a 'PackageName' from supplied category and package name 'String's.
mkPackageName :: String -> String -> PackageName
mkPackageName :: String -> String -> PackageName
mkPackageName String
cat String
package = Category -> PackageName -> PackageName
PackageName (String -> Category
Category String
cat) (String -> PackageName
Cabal.mkPackageName String
package)

-- | Create a 'PackageId' from a 'Category' and 'Cabal.PackageIdentifier'.
fromCabalPackageId :: Category -> Cabal.PackageIdentifier -> PackageId
fromCabalPackageId :: Category -> PackageIdentifier -> PackageId
fromCabalPackageId Category
cat (Cabal.PackageIdentifier PackageName
name Version
version) =
  PackageName -> Version -> PackageId
PackageId (Category -> PackageName -> PackageName
PackageName Category
cat (PackageName -> PackageName
normalizeCabalPackageName PackageName
name))
            (Version -> Version
Portage.fromCabalVersion Version
version)

-- | Convert a 'Cabal.PackageName' into lowercase. Internally uses
-- 'cabal_pn_to_PN'.
--
-- >>> normalizeCabalPackageName (Cabal.mkPackageName "FooBar1")
-- PackageName "foobar1"
normalizeCabalPackageName :: Cabal.PackageName -> Cabal.PackageName
normalizeCabalPackageName :: PackageName -> PackageName
normalizeCabalPackageName =
  String -> PackageName
Cabal.mkPackageName (String -> PackageName)
-> (PackageName -> String) -> PackageName -> PackageName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PackageName -> String
cabal_pn_to_PN

-- | Apply 'normalizeCabalPackageName' to the 'Cabal.PackageName' of
-- a supplied 'Cabal.PackageIdentifier'.
normalizeCabalPackageId :: Cabal.PackageIdentifier -> Cabal.PackageIdentifier
normalizeCabalPackageId :: PackageIdentifier -> PackageIdentifier
normalizeCabalPackageId (Cabal.PackageIdentifier PackageName
name Version
version) =
  PackageName -> Version -> PackageIdentifier
Cabal.PackageIdentifier (PackageName -> PackageName
normalizeCabalPackageName PackageName
name) Version
version

-- | Convert a 'PackageId' into a 'Maybe' 'Cabal.PackageIdentifier'.
toCabalPackageId :: PackageId -> Maybe Cabal.PackageIdentifier
toCabalPackageId :: PackageId -> Maybe PackageIdentifier
toCabalPackageId (PackageId (PackageName Category
_cat PackageName
name) Version
version) =
  (Version -> PackageIdentifier)
-> Maybe Version -> Maybe PackageIdentifier
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (PackageName -> Version -> PackageIdentifier
Cabal.PackageIdentifier PackageName
name)
           (Version -> Maybe Version
Portage.toCabalVersion Version
version)

-- | Parse a 'String' as a package in the form of @[category\/]name[-version]@:
--
-- Note that we /cannot/ use the 'parsec' function to parse the 'Cabal.PackageName',
-- since it fails the entire parse if it tries to parse a 'Version'.
-- See 'parseCabalPackageName' below.
--
-- If parsing a valid package string:
-- 
-- >>> parseFriendlyPackage "category-name/package-name1-0.0.0.1a_beta2-r4"
-- Right (Just (Category {unCategory = "category-name"}),PackageName "package-name1",Just (Version {versionNumber = [0,0,0,1], versionChar = Just 'a', versionSuffix = [Beta 2], versionRevision = 4}))
--
-- If malformed, return an error string:
--
-- >>> parseFriendlyPackage "category-name/package-name-1-0.0.0.1a_beta2-r4"
-- Left ...
parseFriendlyPackage :: String -> Either String (Maybe Category, Cabal.PackageName, Maybe Portage.Version)
parseFriendlyPackage :: String
-> Either String (Maybe Category, PackageName, Maybe Version)
parseFriendlyPackage String
str = ParsecParser (Maybe Category, PackageName, Maybe Version)
-> String
-> Either String (Maybe Category, PackageName, Maybe Version)
forall a. ParsecParser a -> String -> Either String a
explicitEitherParsec ParsecParser (Maybe Category, PackageName, Maybe Version)
parser String
str
  where
  parser :: ParsecParser (Maybe Category, PackageName, Maybe Version)
parser = do
    Maybe Category
mc <- ParsecParser Category -> ParsecParser (Maybe Category)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
P.optional (ParsecParser Category -> ParsecParser (Maybe Category))
-> (ParsecParser Category -> ParsecParser Category)
-> ParsecParser Category
-> ParsecParser (Maybe Category)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ParsecParser Category -> ParsecParser Category
forall (m :: * -> *) a. Parsing m => m a -> m a
P.try (ParsecParser Category -> ParsecParser (Maybe Category))
-> ParsecParser Category -> ParsecParser (Maybe Category)
forall a b. (a -> b) -> a -> b
$ do
      Category
c <- ParsecParser Category
forall a (m :: * -> *). (Parsec a, CabalParsing m) => m a
parsec
      Char
_ <- Char -> ParsecParser Char
forall (m :: * -> *). CharParsing m => Char -> m Char
P.char Char
'/'
      Category -> ParsecParser Category
forall (m :: * -> *) a. Monad m => a -> m a
return Category
c
    PackageName
p <- ParsecParser PackageName
forall (m :: * -> *). CabalParsing m => m PackageName
parseCabalPackageName
    Maybe Version
mv <- ParsecParser Version -> ParsecParser (Maybe Version)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
P.optional (ParsecParser Version -> ParsecParser (Maybe Version))
-> ParsecParser Version -> ParsecParser (Maybe Version)
forall a b. (a -> b) -> a -> b
$ do
      Char
_ <- Char -> ParsecParser Char
forall (m :: * -> *). CharParsing m => Char -> m Char
P.char Char
'-'
      Version
v <- ParsecParser Version
forall a (m :: * -> *). (Parsec a, CabalParsing m) => m a
parsec
      Version -> ParsecParser Version
forall (m :: * -> *) a. Monad m => a -> m a
return Version
v
    (Maybe Category, PackageName, Maybe Version)
-> ParsecParser (Maybe Category, PackageName, Maybe Version)
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe Category
mc, PackageName
p, Maybe Version
mv)

-- | Parse a 'Cabal.PackageName'.
--
-- This parser is a replacement for 'parsecUnqualComponentName' which fails when
-- trying to parse a 'Version'.
parseCabalPackageName :: CabalParsing m => m Cabal.PackageName
parseCabalPackageName :: m PackageName
parseCabalPackageName = do
  String
pn <- m Char -> m String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
P.some (m Char -> m String) -> (m Char -> m Char) -> m Char -> m String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. m Char -> m Char
forall (m :: * -> *) a. Parsing m => m a -> m a
P.try (m Char -> m String) -> m Char -> m String
forall a b. (a -> b) -> a -> b
$
    [m Char] -> m Char
forall (m :: * -> *) a. Alternative m => [m a] -> m a
P.choice
    [ m Char
forall (m :: * -> *). CharParsing m => m Char
P.alphaNum
    , Char -> m Char
forall (m :: * -> *). CharParsing m => Char -> m Char
P.char Char
'+'
    , Char -> m Char
forall (m :: * -> *). CharParsing m => Char -> m Char
P.char Char
'-' m Char -> m () -> m Char
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* m String -> m ()
forall (m :: * -> *) a. (Parsing m, Show a) => m a -> m ()
P.notFollowedBy (m Char -> m String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
P.some m Char
forall (m :: * -> *). CharParsing m => m Char
P.digit m String -> m () -> m String
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* m Char -> m ()
forall (m :: * -> *) a. (Parsing m, Show a) => m a -> m ()
P.notFollowedBy m Char
forall (m :: * -> *). CharParsing m => m Char
P.letter)
    ]
  PackageName -> m PackageName
forall (m :: * -> *) a. Monad m => a -> m a
return (PackageName -> m PackageName) -> PackageName -> m PackageName
forall a b. (a -> b) -> a -> b
$ String -> PackageName
Cabal.mkPackageName String
pn

-- | Pretty-print a lowercase 'Cabal.PackageName'.
--
-- Note the difference between this function and 'normalizeCabalPackageName':
-- this function returns a 'String', the other a 'Cabal.PackageName'.
--
-- >>> cabal_pn_to_PN (Cabal.mkPackageName "FooBar1")
-- "foobar1"
cabal_pn_to_PN :: Cabal.PackageName -> String
cabal_pn_to_PN :: PackageName -> String
cabal_pn_to_PN = (Char -> Char) -> ShowS
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
Char.toLower ShowS -> (PackageName -> String) -> PackageName -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PackageName -> String
forall a. Pretty a => a -> String
prettyShow