    {-# LANGUAGE RecordWildCards, PatternGuards #-}
    {-|
        This module provides simple command line argument processing.
        The main function of interest is 'cmdArgs'.
        A simple example is:

        @data Sample = Sample {hello :: String} deriving (Show, Data, Typeable)@

    @
    sample = Sample{hello = 'def' '&=' 'help' \"World argument\" '&=' 'opt' \"world\"}
             '&=' 'summary' \"Sample v1\"
    @

        @main = print =<< 'cmdArgs' sample@

        Attributes are used to control a number of behaviours:

        * The help message: 'help', 'typ', 'details', 'summary', 'program', 'groupname'

        * Flag behaviour: 'opt', 'enum', 'verbosity', 'ignore'

        * Flag name assignment: 'name', 'explicit'

        * Controlling non-flag arguments: 'args', 'argPos'

        * multi-mode programs: 'modes', 'auto'

        /Supported Types/: Each field in the record must be one of the supported
        atomic types (@String@, @Int@, @Integer@, @Float@, @Double@, @Bool@, an
        enumeration, a tuple of atomic types) or a list (@[]@) or @Maybe@ wrapping
        at atomic type.

        /Missing Fields/: If a field is shared by multiple modes, it may be omitted
        in subsequent modes, and will default to the previous value.

        /Purity/: Values created with annotations are not pure - the first
        time they are computed they will include the annotations, but subsequently
        they will not. If you wish to run the above example in a more robust way:

        @sample = 'cmdArgsMode' $ Sample{hello = ... -- as before@

        @main = print =<< 'cmdArgsRun' sample@

        Even using this scheme, sometimes GHC's optimisations may share values who
        have the same annotation. To disable sharing you may need to specify
        @\{\-\# OPTIONS_GHC -fno-cse \#\-\}@ in the module you define the flags.

        /Pure annotations/: Alternatively, you may use pure annotations, which are
        referentially transparent, but less type safe and more verbose. The initial
        example may be written as:

        @sample = 'record' Sample{} [hello := 'def' '+=' 'help' \"World argument\" '+=' 'opt' \"world\"]@
        @         '+=' 'summary' \"Sample v1\"@

        @main = print =<< (cmdArgs_ sample :: IO Sample)@

        All the examples are written using impure annotations. To convert to pure
        annotations follow the rules:

        > Ctor {field1 = value1 &= ann1, field2 = value2} &= ann2 ==> record Ctor{} [field1 := value1 += ann1, field2 := value2] += ann2
        > Ctor (value1 &= ann1) value2 &= ann2 ==> record Ctor{} [atom value1 += ann1, atom value2] += ann2
        > modes [Ctor1{...}, Ctor2{...}] ==> modes_ [record Ctor1{} [...], record Ctor2{} [...]]
        > Ctor {field1 = enum [X &= ann, Y]} ==> record Ctor{} [enum_ field1 [atom X += ann, atom Y]]

        If you are willing to use TemplateHaskell, you can write in the impure syntax,
        but have your code automatically translated to the pure style. For more details see
        "System.Console.CmdArgs.Quote".

    -}
    module System.Console.CmdArgs.Implicit(
        -- * Running command lines
        cmdArgs, cmdArgsMode, cmdArgsRun, cmdArgs_, cmdArgsMode_, cmdArgsApply, CmdArgs(..), -- cmdArgsReform,
        -- * Constructing command lines
        -- | Attributes can work on a flag (inside a field), on a mode (outside the record),
        --   or on all modes (outside the 'modes' call).
        module System.Console.CmdArgs.Implicit.UI,
        -- ** Impure
        (&=), modes, enum,
        -- ** Pure
        (+=), record, atom, Annotate((:=)), enum_, modes_,
        -- * Re-exported for convenience
        -- | Provides a few opaque types (for writing type signatures),
        --   verbosity control, default values with 'def' and the
        --   @Data@/@Typeable@ type classes.
        module System.Console.CmdArgs.Verbosity,
        module System.Console.CmdArgs.Default,
        Ann, Mode,
        Data, Typeable
        ) where

    import Data.Data
    import Data.Maybe
    import Data.Generics.Any
    import System.Exit
    import System.Console.CmdArgs.Explicit(Mode,processArgs,remap,modeReform)
    import System.Console.CmdArgs.Implicit.Ann
    import System.Console.CmdArgs.Annotate hiding ((&=))
    import qualified System.Console.CmdArgs.Annotate as A((&=))
    import System.Console.CmdArgs.Implicit.Type
    import System.Console.CmdArgs.Implicit.Local
    import System.Console.CmdArgs.Implicit.Global
    import System.Console.CmdArgs.Implicit.UI
    import System.Console.CmdArgs.Verbosity
    import System.Console.CmdArgs.Default

    -- | Take impurely annotated records and run the corresponding command line.
    --   Shortcut for @'cmdArgsRun' . 'cmdArgsMode'@.
    --
    --   To use 'cmdArgs' with custom command line arguments see
    --   'System.Environment.withArgs'.
    cmdArgs :: Data a => a -> IO a
    cmdArgs :: forall a. Data a => a -> IO a
    cmdArgs = Mode (CmdArgs a) -> IO a
    forall a. Mode (CmdArgs a) -> IO a
    cmdArgsRun (Mode (CmdArgs a) -> IO a) -> (a -> Mode (CmdArgs a)) -> a -> IO a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> Mode (CmdArgs a)
    forall a. Data a => a -> Mode (CmdArgs a)
    cmdArgsMode

    -- | Take purely annotated records and run the corresponding command line.
    --   Shortcut for @'cmdArgsRun' . 'cmdArgsMode_'@.
    --
    --   To use 'cmdArgs_' with custom command line arguments see
    --   'System.Environment.withArgs'.
    cmdArgs_ :: Data a => Annotate Ann -> IO a
    cmdArgs_ :: forall a. Data a => Annotate Ann -> IO a
    cmdArgs_ = Mode (CmdArgs a) -> IO a
    forall a. Mode (CmdArgs a) -> IO a
    cmdArgsRun (Mode (CmdArgs a) -> IO a)
    -> (Annotate Ann -> Mode (CmdArgs a)) -> Annotate Ann -> IO a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Annotate Ann -> Mode (CmdArgs a)
    forall a. Data a => Annotate Ann -> Mode (CmdArgs a)
    cmdArgsMode_

    cmdArgsCapture :: Data a => Capture Ann -> Mode (CmdArgs a)
    cmdArgsCapture :: forall a. Data a => Capture Ann -> Mode (CmdArgs a)
    cmdArgsCapture = (CmdArgs Any -> CmdArgs a)
    -> (CmdArgs a -> (CmdArgs Any, CmdArgs Any -> CmdArgs a))
    -> Mode (CmdArgs Any)
    -> Mode (CmdArgs a)
    forall a b. (a -> b) -> (b -> (a, a -> b)) -> Mode a -> Mode b
    forall (m :: * -> *) a b.
    Remap m =>
    (a -> b) -> (b -> (a, a -> b)) -> m a -> m b
    remap CmdArgs Any -> CmdArgs a
    embed CmdArgs a -> (CmdArgs Any, CmdArgs Any -> CmdArgs a)
    forall {f :: * -> *} {a}.
    (Functor f, Data a) =>
    f a -> (f Any, CmdArgs Any -> CmdArgs a)
    proj (Mode (CmdArgs Any) -> Mode (CmdArgs a))
    -> (Capture Ann -> Mode (CmdArgs Any))
    -> Capture Ann
    -> Mode (CmdArgs a)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Prog_ -> Mode (CmdArgs Any)
    global (Prog_ -> Mode (CmdArgs Any))
    -> (Capture Ann -> Prog_) -> Capture Ann -> Mode (CmdArgs Any)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Capture Ann -> Prog_
    local
        where embed :: CmdArgs Any -> CmdArgs a
    embed = (Any -> a) -> CmdArgs Any -> CmdArgs a
    forall a b. (a -> b) -> CmdArgs a -> CmdArgs b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Any -> a
    forall a. Typeable a => Any -> a
    fromAny
              proj :: f a -> (f Any, CmdArgs Any -> CmdArgs a)
    proj f a
    x = ((a -> Any) -> f a -> f Any
    forall a b. (a -> b) -> f a -> f b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap a -> Any
    forall a. Data a => a -> Any
    Any f a
    x, CmdArgs Any -> CmdArgs a
    embed)

    -- | Take impurely annotated records and turn them in to a 'Mode' value, that can
    --   make use of the "System.Console.CmdArgs.Explicit" functions (i.e. 'process').
    --
    --   Annotated records are impure, and will only contain annotations on
    --   their first use. The result of this function is pure, and can be reused.
    cmdArgsMode :: Data a => a -> Mode (CmdArgs a)
    cmdArgsMode :: forall a. Data a => a -> Mode (CmdArgs a)
    cmdArgsMode = Capture Ann -> Mode (CmdArgs a)
    forall a. Data a => Capture Ann -> Mode (CmdArgs a)
    cmdArgsCapture (Capture Ann -> Mode (CmdArgs a))
    -> (a -> Capture Ann) -> a -> Mode (CmdArgs a)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> Capture Ann
    forall val ann. (Data val, Data ann) => val -> Capture ann
    capture

    -- | Take purely annotated records and turn them in to a 'Mode' value, that can
    --   make use of the "System.Console.CmdArgs.Explicit" functions (i.e. 'process').
    cmdArgsMode_ :: Data a => Annotate Ann -> Mode (CmdArgs a)
    cmdArgsMode_ :: forall a. Data a => Annotate Ann -> Mode (CmdArgs a)
    cmdArgsMode_ = Capture Ann -> Mode (CmdArgs a)
    forall a. Data a => Capture Ann -> Mode (CmdArgs a)
    cmdArgsCapture (Capture Ann -> Mode (CmdArgs a))
    -> (Annotate Ann -> Capture Ann)
    -> Annotate Ann
    -> Mode (CmdArgs a)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Annotate Ann -> Capture Ann
    forall a. Show a => Annotate a -> Capture a
    capture_

    -- | Run a Mode structure. This function reads the command line arguments
    --   and then performs as follows:
    --
    --   * If invalid arguments are given, it will display the error message
    --     and exit.
    --
    --   * If @--help@ is given, it will display the help message and exit.
    --
    --   * If @--version@ is given, it will display the version and exit.
    --
    --   * In all other circumstances the program will return a value.
    --
    --   * Additionally, if either @--quiet@ or @--verbose@ is given (see 'verbosity')
    --     it will set the verbosity (see 'setVerbosity').
    cmdArgsRun :: Mode (CmdArgs a) -> IO a
    cmdArgsRun :: forall a. Mode (CmdArgs a) -> IO a
    cmdArgsRun Mode (CmdArgs a)
    m = CmdArgs a -> IO a
    forall a. CmdArgs a -> IO a
    cmdArgsApply (CmdArgs a -> IO a) -> IO (CmdArgs a) -> IO a
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< Mode (CmdArgs a) -> IO (CmdArgs a)
    forall a. Mode a -> IO a
    processArgs Mode (CmdArgs a)
    m

    -- | Perform the necessary actions dictated by a 'CmdArgs' structure.
    --
    --   * If 'cmdArgsHelp' is @Just@, it will display the help message and exit.
    --
    --   * If 'cmdArgsVersion' is @Just@, it will display the version and exit.
    --
    --   * In all other circumstances it will return a value.
    --
    --   * Additionally, if 'cmdArgsVerbosity' is @Just@ (see 'verbosity')
    --     it will set the verbosity (see 'setVerbosity').
    cmdArgsApply :: CmdArgs a -> IO a
    cmdArgsApply :: forall a. CmdArgs a -> IO a
    cmdArgsApply CmdArgs{a
    Maybe String
    Maybe Verbosity
    CmdArgsPrivate
    cmdArgsHelp :: forall a. CmdArgs a -> Maybe String
    cmdArgsVersion :: forall a. CmdArgs a -> Maybe String
    cmdArgsVerbosity :: forall a. CmdArgs a -> Maybe Verbosity
    cmdArgsValue :: a
    cmdArgsHelp :: Maybe String
    cmdArgsVersion :: Maybe String
    cmdArgsVerbosity :: Maybe Verbosity
    cmdArgsPrivate :: CmdArgsPrivate
    cmdArgsPrivate :: forall a. CmdArgs a -> CmdArgsPrivate
    cmdArgsValue :: forall a. CmdArgs a -> a
    ..}
        | Just String
    x <- Maybe String
    cmdArgsHelp = do String -> IO ()
    putStr String
    x; IO a
    forall a. IO a
    exitSuccess
        | Just String
    x <- Maybe String
    cmdArgsVersion = do String -> IO ()
    putStr String
    x; IO a
    forall a. IO a
    exitSuccess
        | Bool
    otherwise = do
            IO () -> (Verbosity -> IO ()) -> Maybe Verbosity -> IO ()
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe (() -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()) Verbosity -> IO ()
    setVerbosity Maybe Verbosity
    cmdArgsVerbosity
            a -> IO a
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return a
    cmdArgsValue

    -- | Produce command line arguments that would generate the given value. This
    --   function is useful for taking a value resulting from a command line,
    --   modifying it (perhaps changing the value of a flag) and generating fresh
    --   command line arguments.
    --
    -- > forall mode values constructed by cmdArgsMode/cmdArgsMode:
    -- > forall args which successfully parse with mode
    -- > let x = processValue mode args
    -- > processValue mode (cmdArgsReform mode $ fromRight x) == x
    _cmdArgsReform :: Mode (CmdArgs a) -> CmdArgs a -> [String]
    _cmdArgsReform :: forall a. Mode (CmdArgs a) -> CmdArgs a -> [String]
    _cmdArgsReform Mode (CmdArgs a)
    m CmdArgs a
    x = [String] -> Maybe [String] -> [String]
    forall a. a -> Maybe a -> a
    fromMaybe (String -> [String]
    forall a. HasCallStack => String -> a
    error String
    err) (Maybe [String] -> [String]) -> Maybe [String] -> [String]
    forall a b. (a -> b) -> a -> b
    $ Mode (CmdArgs a) -> CmdArgs a -> Maybe [String]
    forall a. Mode a -> a -> Maybe [String]
    modeReform Mode (CmdArgs a)
    m CmdArgs a
    x
        where err :: String
    err = String
    "System.Console.CmdArgs.Implicit.cmdArgsReform: cannot reform the arguments, perhaps the mode was not " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++
                    String
    "generated by cmdArgsMode/cmdArgsMode_ ?"

    -- | Modes: \"I want a program with multiple modes, like darcs or cabal.\"
    --
    --   Takes a list of modes, and creates a mode which includes them all.
    --   If you want one of the modes to be chosen by default, see 'auto'.
    --
    -- > data Modes = Mode1 | Mode2 | Mode3 deriving Data
    -- > cmdArgs $ modes [Mode1,Mode2,Mode3]
    modes :: Data val => [val] -> val
    modes :: forall val. Data val => [val] -> val
    modes = [val] -> val
    forall val. Data val => [val] -> val
    many

    -- | Flag: \"I want several different flags to set this one field to different values.\"
    --
    --   This annotation takes a type which is an enumeration, and provides multiple
    --   separate flags to set the field to each value. The first element in the list
    --   is used as the value of the field.
    --
    -- > data State = On | Off deriving Data
    -- > data Mode = Mode {state :: State}
    -- > cmdArgs $ Mode {state = enum [On &= help "Turn on",Off &= help "Turn off"]}
    -- >   --on   Turn on
    -- >   --off  Turn off
    --
    --   This annotation can be used to allow multiple flags within a field:
    --
    -- > data Mode = Mode {state :: [State]}
    -- > cmdArgs $ Mode {state = enum [[] &= ignore, [On] &= help "Turn on", [Off] &= help "Turn off"]}
    --
    --   Now @--on --off@ would produce @Mode [On,Off]@.
    enum :: Data val => [val] -> val
    enum :: forall val. Data val => [val] -> val
    enum = [val] -> val
    forall val. Data val => [val] -> val
    many

    -- | Add an annotation to a value. Note that if the value is evaluated
    --   more than once the annotation will only be available the first time.
    {-# INLINE (&=) #-}
    (&=) :: Data val => val -> Ann -> val
    &= :: forall val. Data val => val -> Ann -> val
    (&=) = val -> Ann -> val
    forall val ann. (Data val, Data ann) => val -> ann -> val
    (A.&=)

    -- | Like 'enum', but using the pure annotations.
    enum_ :: (Data c, Data f) => (c -> f) -> [Annotate Ann] -> Annotate Ann
    enum_ :: forall c f.
    (Data c, Data f) =>
    (c -> f) -> [Annotate Ann] -> Annotate Ann
    enum_ = (c -> f) -> [Annotate Ann] -> Annotate Ann
    forall ann c f.
    (Data c, Data f) =>
    (c -> f) -> [Annotate ann] -> Annotate ann
    (:=+)

    -- | Like 'modes', but using the pure annotations.
    modes_ :: [Annotate Ann] -> Annotate Ann
    modes_ :: [Annotate Ann] -> Annotate Ann
    modes_ = [Annotate Ann] -> Annotate Ann
    forall a. [Annotate a] -> Annotate a
    many_