module HMGit.Commands.Porcelain.Diff.Cmd (
    diffCmd
) where

import           HMGit.Commands                     (Cmd (..))
import           HMGit.Commands.Porcelain.Diff.Core (Diff (..), DiffCfg (..),
                                                     diffDefault, showDiff)

import           Control.Exception.Safe             (MonadCatch)
import           Control.Monad                      (MonadPlus)
import           Control.Monad.IO.Class             (MonadIO)
import           Data.Foldable                      (asum)
import qualified Options.Applicative                as OA

diffMode :: (MonadCatch m, MonadIO m, MonadPlus m) => OA.Parser (Diff m)
diffMode :: Parser (Diff m)
diffMode = [Parser (Diff m)] -> Parser (Diff m)
forall (t :: * -> *) (f :: * -> *) a.
(Foldable t, Alternative f) =>
t (f a) -> f a
asum [
    Diff m -> Mod FlagFields (Diff m) -> Parser (Diff m)
forall a. a -> Mod FlagFields a -> Parser a
OA.flag' ((DiffCfg -> HMGitT m ()) -> Diff m
forall (m :: * -> *). (DiffCfg -> HMGitT m ()) -> Diff m
Diff ((DiffCfg -> HMGitT m ()) -> Diff m)
-> (DiffCfg -> HMGitT m ()) -> Diff m
forall a b. (a -> b) -> a -> b
$ HMGitT m () -> DiffCfg -> HMGitT m ()
forall a b. a -> b -> a
const (HMGitT m () -> DiffCfg -> HMGitT m ())
-> HMGitT m () -> DiffCfg -> HMGitT m ()
forall a b. (a -> b) -> a -> b
$ () -> HMGitT m ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()) (Mod FlagFields (Diff m) -> Parser (Diff m))
-> Mod FlagFields (Diff m) -> Parser (Diff m)
forall a b. (a -> b) -> a -> b
$ [Mod FlagFields (Diff m)] -> Mod FlagFields (Diff m)
forall a. Monoid a => [a] -> a
mconcat [
        String -> Mod FlagFields (Diff m)
forall (f :: * -> *) a. HasName f => String -> Mod f a
OA.long String
"quiet"
      , String -> Mod FlagFields (Diff m)
forall (f :: * -> *) a. String -> Mod f a
OA.help String
"Disable all output of the program."
      ]
  , Diff m -> Parser (Diff m)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Diff m
forall (m :: * -> *).
(MonadIO m, MonadCatch m, MonadPlus m) =>
Diff m
diffDefault
  ]

optDiffPath :: OA.Parser [FilePath]
optDiffPath :: Parser [String]
optDiffPath = Parser String -> Parser [String]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
OA.many (Parser String -> Parser [String])
-> Parser String -> Parser [String]
forall a b. (a -> b) -> a -> b
$ ReadM String -> Mod ArgumentFields String -> Parser String
forall a. ReadM a -> Mod ArgumentFields a -> Parser a
OA.argument ReadM String
forall s. IsString s => ReadM s
OA.str (Mod ArgumentFields String -> Parser String)
-> Mod ArgumentFields String -> Parser String
forall a b. (a -> b) -> a -> b
$ [Mod ArgumentFields String] -> Mod ArgumentFields String
forall a. Monoid a => [a] -> a
mconcat [
    String -> Mod ArgumentFields String
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
OA.metavar String
"<path>..."
  , String -> Mod ArgumentFields String
forall (f :: * -> *) a. String -> Mod f a
OA.help (String -> Mod ArgumentFields String)
-> String -> Mod ArgumentFields String
forall a b. (a -> b) -> a -> b
$ [String] -> String
unwords [
        String
"The <paths> parameters, when given,"
       , String
"are used to limit the diff to the named paths"
       , String
"(you can give directory names and get diff for all files under them)."
       ]
  ]

noPrefix :: OA.Parser Bool
noPrefix :: Parser Bool
noPrefix = Mod FlagFields Bool -> Parser Bool
OA.switch (Mod FlagFields Bool -> Parser Bool)
-> Mod FlagFields Bool -> Parser Bool
forall a b. (a -> b) -> a -> b
$ [Mod FlagFields Bool] -> Mod FlagFields Bool
forall a. Monoid a => [a] -> a
mconcat [
    String -> Mod FlagFields Bool
forall (f :: * -> *) a. HasName f => String -> Mod f a
OA.long String
"no-prefix"
  , String -> Mod FlagFields Bool
forall (f :: * -> *) a. String -> Mod f a
OA.help String
"Do not show any source or destination prefix."
  ]

srcPrefix :: OA.Parser String
srcPrefix :: Parser String
srcPrefix = ReadM String -> Mod OptionFields String -> Parser String
forall a. ReadM a -> Mod OptionFields a -> Parser a
OA.option ReadM String
forall s. IsString s => ReadM s
OA.str (Mod OptionFields String -> Parser String)
-> Mod OptionFields String -> Parser String
forall a b. (a -> b) -> a -> b
$ [Mod OptionFields String] -> Mod OptionFields String
forall a. Monoid a => [a] -> a
mconcat [
    String -> Mod OptionFields String
forall (f :: * -> *) a. HasName f => String -> Mod f a
OA.long String
"src-prefix"
  , String -> Mod OptionFields String
forall (f :: * -> *) a. HasValue f => a -> Mod f a
OA.value String
"a/"
  , String -> Mod OptionFields String
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
OA.metavar String
"<prefix>"
  , String -> Mod OptionFields String
forall (f :: * -> *) a. String -> Mod f a
OA.help String
"Show the given source prefix instead of \"a/\"."
  ]

dstPrefix :: OA.Parser String
dstPrefix :: Parser String
dstPrefix = ReadM String -> Mod OptionFields String -> Parser String
forall a. ReadM a -> Mod OptionFields a -> Parser a
OA.option ReadM String
forall s. IsString s => ReadM s
OA.str (Mod OptionFields String -> Parser String)
-> Mod OptionFields String -> Parser String
forall a b. (a -> b) -> a -> b
$ [Mod OptionFields String] -> Mod OptionFields String
forall a. Monoid a => [a] -> a
mconcat [
    String -> Mod OptionFields String
forall (f :: * -> *) a. HasName f => String -> Mod f a
OA.long String
"dst-prefix"
  , String -> Mod OptionFields String
forall (f :: * -> *) a. HasValue f => a -> Mod f a
OA.value String
"b/"
  , String -> Mod OptionFields String
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
OA.metavar String
"<prefix>"
  , String -> Mod OptionFields String
forall (f :: * -> *) a. String -> Mod f a
OA.help String
"Show the given destination prefix instead of \"b/\"."
  ]

diffCmd :: (MonadCatch m, MonadIO m, MonadPlus m) => OA.Mod OA.CommandFields (Cmd m)
diffCmd :: Mod CommandFields (Cmd m)
diffCmd = String -> ParserInfo (Cmd m) -> Mod CommandFields (Cmd m)
forall a. String -> ParserInfo a -> Mod CommandFields a
OA.command String
"diff"
    (ParserInfo (Cmd m) -> Mod CommandFields (Cmd m))
-> ParserInfo (Cmd m) -> Mod CommandFields (Cmd m)
forall a b. (a -> b) -> a -> b
$ Parser (Cmd m) -> InfoMod (Cmd m) -> ParserInfo (Cmd m)
forall a. Parser a -> InfoMod a -> ParserInfo a
OA.info (Diff m -> DiffCfg -> Cmd m
forall (m :: * -> *). Diff m -> DiffCfg -> Cmd m
CmdDiff
        (Diff m -> DiffCfg -> Cmd m)
-> Parser (Diff m) -> Parser (DiffCfg -> Cmd m)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Parser (Diff m -> Diff m)
forall a. Parser (a -> a)
OA.helper Parser (Diff m -> Diff m) -> Parser (Diff m) -> Parser (Diff m)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser (Diff m)
forall (m :: * -> *).
(MonadCatch m, MonadIO m, MonadPlus m) =>
Parser (Diff m)
diffMode)
        Parser (DiffCfg -> Cmd m) -> Parser DiffCfg -> Parser (Cmd m)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (ShowDiff -> [String] -> DiffCfg
DiffCfg
            (ShowDiff -> [String] -> DiffCfg)
-> Parser ShowDiff -> Parser ([String] -> DiffCfg)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ((\Bool
b String
s String
d -> if Bool
b then String -> String -> ShowDiff
showDiff String
forall a. Monoid a => a
mempty String
forall a. Monoid a => a
mempty else String -> String -> ShowDiff
showDiff String
s String
d)
                (Bool -> String -> String -> ShowDiff)
-> Parser Bool -> Parser (String -> String -> ShowDiff)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Bool
noPrefix
                Parser (String -> String -> ShowDiff)
-> Parser String -> Parser (String -> ShowDiff)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser String
srcPrefix
                Parser (String -> ShowDiff) -> Parser String -> Parser ShowDiff
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser String
dstPrefix)
            Parser ([String] -> DiffCfg) -> Parser [String] -> Parser DiffCfg
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser [String]
optDiffPath))
    (InfoMod (Cmd m) -> ParserInfo (Cmd m))
-> InfoMod (Cmd m) -> ParserInfo (Cmd m)
forall a b. (a -> b) -> a -> b
$ String -> InfoMod (Cmd m)
forall a. String -> InfoMod a
OA.progDesc String
"Show changes between commits, commit and working tree, etc"