-- | String specification of a Repository's Pull Request
--
-- This shortened format is useful for passing a Pull Request as a command-line
-- argument, or showing it in log messages.
--
module Restyler.PullRequestSpec
    ( PullRequestSpec(..)
    , parseSpec
    )
where

import Restyler.Prelude

import GitHub.Data
import qualified Prelude as Unsafe
import Text.Megaparsec hiding (some)
import Text.Megaparsec.Char

data PullRequestSpec = PullRequestSpec
    { PullRequestSpec -> Name Owner
prsOwner :: Name Owner
    , PullRequestSpec -> Name Repo
prsRepo :: Name Repo
    , PullRequestSpec -> IssueNumber
prsPullRequest :: IssueNumber
    }
    deriving stock (PullRequestSpec -> PullRequestSpec -> Bool
(PullRequestSpec -> PullRequestSpec -> Bool)
-> (PullRequestSpec -> PullRequestSpec -> Bool)
-> Eq PullRequestSpec
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PullRequestSpec -> PullRequestSpec -> Bool
$c/= :: PullRequestSpec -> PullRequestSpec -> Bool
== :: PullRequestSpec -> PullRequestSpec -> Bool
$c== :: PullRequestSpec -> PullRequestSpec -> Bool
Eq, Int -> PullRequestSpec -> ShowS
[PullRequestSpec] -> ShowS
PullRequestSpec -> String
(Int -> PullRequestSpec -> ShowS)
-> (PullRequestSpec -> String)
-> ([PullRequestSpec] -> ShowS)
-> Show PullRequestSpec
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PullRequestSpec] -> ShowS
$cshowList :: [PullRequestSpec] -> ShowS
show :: PullRequestSpec -> String
$cshow :: PullRequestSpec -> String
showsPrec :: Int -> PullRequestSpec -> ShowS
$cshowsPrec :: Int -> PullRequestSpec -> ShowS
Show)

instance Display PullRequestSpec where
    textDisplay :: PullRequestSpec -> Text
textDisplay PullRequestSpec {..} = [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
        [ Name Owner -> Text
forall entity. Name entity -> Text
untagName Name Owner
prsOwner Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> "/"
        , Name Repo -> Text
forall entity. Name entity -> Text
untagName Name Repo
prsRepo Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> "#"
        , IssueNumber -> Text
forall a. IsPathPart a => a -> Text
toPathPart IssueNumber
prsPullRequest
        ]

-- | Parse @\<owner>\/\<name>#\<number>@ into a @'PullRequestSpec'@
parseSpec :: String -> Either String PullRequestSpec
parseSpec :: String -> Either String PullRequestSpec
parseSpec = (ParseErrorBundle String Void -> String)
-> Either (ParseErrorBundle String Void) PullRequestSpec
-> Either String PullRequestSpec
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first ParseErrorBundle String Void -> String
forall s e.
(Stream s, ShowErrorComponent e) =>
ParseErrorBundle s e -> String
errorBundlePretty (Either (ParseErrorBundle String Void) PullRequestSpec
 -> Either String PullRequestSpec)
-> (String
    -> Either (ParseErrorBundle String Void) PullRequestSpec)
-> String
-> Either String PullRequestSpec
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Parsec Void String PullRequestSpec
-> String
-> String
-> Either (ParseErrorBundle String Void) PullRequestSpec
forall e s a.
Parsec e s a -> String -> s -> Either (ParseErrorBundle s e) a
parse Parsec Void String PullRequestSpec
parser "<input>"

type Parser = Parsec Void String

parser :: Parser PullRequestSpec
parser :: Parsec Void String PullRequestSpec
parser =
    Name Owner -> Name Repo -> IssueNumber -> PullRequestSpec
PullRequestSpec
        (Name Owner -> Name Repo -> IssueNumber -> PullRequestSpec)
-> ParsecT Void String Identity (Name Owner)
-> ParsecT
     Void String Identity (Name Repo -> IssueNumber -> PullRequestSpec)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Proxy Owner -> Text -> Name Owner
forall (proxy :: * -> *) entity.
proxy entity -> Text -> Name entity
mkName Proxy Owner
forall k (t :: k). Proxy t
Proxy (Text -> Name Owner) -> (String -> Text) -> String -> Name Owner
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
pack (String -> Name Owner)
-> ParsecT Void String Identity String
-> ParsecT Void String Identity (Name Owner)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT Void String Identity Char
-> ParsecT Void String Identity Char
-> ParsecT Void String Identity String
forall (m :: * -> *) a end. MonadPlus m => m a -> m end -> m [a]
manyTill ParsecT Void String Identity Char
nonSpace (Token String -> ParsecT Void String Identity (Token String)
forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Token String
'/'))
        ParsecT
  Void String Identity (Name Repo -> IssueNumber -> PullRequestSpec)
-> ParsecT Void String Identity (Name Repo)
-> ParsecT Void String Identity (IssueNumber -> PullRequestSpec)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Proxy Repo -> Text -> Name Repo
forall (proxy :: * -> *) entity.
proxy entity -> Text -> Name entity
mkName Proxy Repo
forall k (t :: k). Proxy t
Proxy (Text -> Name Repo) -> (String -> Text) -> String -> Name Repo
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
pack (String -> Name Repo)
-> ParsecT Void String Identity String
-> ParsecT Void String Identity (Name Repo)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT Void String Identity Char
-> ParsecT Void String Identity Char
-> ParsecT Void String Identity String
forall (m :: * -> *) a end. MonadPlus m => m a -> m end -> m [a]
manyTill ParsecT Void String Identity Char
nonSpace (Token String -> ParsecT Void String Identity (Token String)
forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Token String
'#'))
        ParsecT Void String Identity (IssueNumber -> PullRequestSpec)
-> ParsecT Void String Identity IssueNumber
-> Parsec Void String PullRequestSpec
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Int -> IssueNumber
IssueNumber (Int -> IssueNumber) -> (String -> Int) -> String -> IssueNumber
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Int
forall a. Read a => String -> a
Unsafe.read (String -> IssueNumber)
-> ParsecT Void String Identity String
-> ParsecT Void String Identity IssueNumber
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT Void String Identity Char
-> ParsecT Void String Identity String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
some ParsecT Void String Identity Char
forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m (Token s)
digitChar)

nonSpace :: Parser Char
nonSpace :: ParsecT Void String Identity Char
nonSpace = (Token String -> Bool) -> ParsecT Void String Identity Char
forall e s (m :: * -> *).
MonadParsec e s m =>
(Token s -> Bool) -> m (Token s)
satisfy ((Token String -> Bool) -> ParsecT Void String Identity Char)
-> (Token String -> Bool) -> ParsecT Void String Identity Char
forall a b. (a -> b) -> a -> b
$ Bool -> Bool
not (Bool -> Bool) -> (Char -> Bool) -> Char -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Bool
isSpace