NAME
    OptArgs2 - command-line argument and option processor

VERSION
    2.0.0_3 (2022-04-30)

SYNOPSIS
        #!/usr/bin/env perl
        use OptArgs2;

        my $opts = optargs2(
            comment => 'script to paint things',
            optargs => sub {
                arg item => (
                    isa      => 'Str',
                    required => 1,
                    comment  => 'the item to paint',
                );

                opt help => ( ishelp => 1 );

                opt quiet => (
                    isa     => 'Flag',
                    alias   => 'q',
                    comment => 'output nothing while working',
                );
            },
        );

        print "Painting $opts->{item}\n" unless $opts->{quiet};

DESCRIPTION
    OptArgs2 processes command line arguments, options, and subcommands
    according to the following definitions:

    Command
        A program run from the command line to perform a task.

    Arguments
        Arguments are positional parameters that pass information to a
        command. Arguments can be optional, but they should not be
        confused with Options below.

    Options
        Options are non-positional parameters that pass information to a
        command. They are generally not required to be present (hence
        the name Option) but that is configurable. All options have a
        long form prefixed by '--', and may have a single letter alias
        prefixed by '-'.

    Subcommands
        From the users point of view a subcommand is a special argument
        with its own set of arguments and options. However from a code
        authoring perspective subcommands are often implemented as
        stand-alone programs, called from the main script when the
        appropriate command arguments are given.

    OptArgs2 is a re-write of the original OptArgs module with a cleaner
    code base and improved API. It should be preferred over OptArgs for
    new projects however OptArgs is not likely to disappear from CPAN
    anytime soon. Users converting to OptArgs2 from OptArgs need to be
    aware of the following:

    Obvious API changes: cmd(), optargs2(), subcmd()
        Commands and subcommands must now be explicitly defined using
        "cmd()" and "subcmd()".

    class_optargs() no longer loads the class
        Users must specifically require the class if they want to use it
        afterwards:

            my ($class, $opts) = class_optargs('App::demo');
            eval "require $class" or die $@; # new requirement

    Bool options with no default display as "--[no-]bool"
        A Bool option without a default is now displayed with the
        "[no-]" prefix. What this means in practise is that many of your
        existing Bool options should likely become Flag options instead.

  Simple Commands
    To demonstrate the simple use case (i.e. with no subcommands) lets
    put the code from the synopsis in a file called "paint" and observe
    the following interactions from the shell:

        $ ./paint
        usage: paint ITEM [OPTIONS...]

          arguments:
            ITEM          the item to paint [required]

          options:
            --help,  -h   print a usage message and exit
            --quiet, -q   output nothing while working

    The "optargs2()" function parses the command line according to the
    included "opt()" and "arg()" declarations and returns a single HASH
    reference. If the command is not called correctly then an exception
    is thrown containing an automatically generated usage message as
    shown above. Because OptArgs2 fully knows the valid arguments and
    options it can detect a wide range of errors:

        $ ./paint wall Perl is great
        error: unexpected option or argument: Perl

    So let's add that missing argument definition inside the optargs
    sub:

        arg message => (
            isa      => 'Str',
            comment  => 'the message to paint on the item',
            greedy   => 1,
        );

    And then check the usage again:

        $ ./paint
        usage: paint ITEM [MESSAGE...] [OPTIONS...]

          arguments:
            ITEM          the item to paint [required]
            MESSAGE       the message to paint on the item

          options:
            --help,  -h   print a usage message and exit
            --quiet, -q   output nothing while working

    Note that optional arguments are surrounded by square brackets, and
    that three dots (...) are postfixed to greedy arguments. A greedy
    argument will swallow whatever is left on the comand line:

        $ ./paint wall Perl is great
        Painting on wall: "Perl is great".

    Note that it probably doesn't make sense to define any more
    arguments once you have a greedy argument. Let's imagine you now
    want the user to be able to choose the colour if they don't like the
    default. An option might make sense here:

        opt colour => (
            isa           => 'Str',
            default       => 'blue',
            comment       => 'the colour to use',
        );

    This now produces the following usage output:

        usage: paint ITEM [MESSAGE...] [OPTIONS...]

          arguments:
            ITEM               the item to paint
            MESSAGE            the message to paint on the item

          options:
            --colour=STR, -c   the colour to use [blue]
            --quiet,      -q   output nothing while working

    The command line is parsed first for arguments, then for options, in
    the same order in which they are defined. This probably only of
    interest if you are using trigger actions on your options (see
    FUNCTIONS below for details).

  Multi-Level Commands
    Commands with subcommands require a different coding model and
    syntax which we will describe over three phases:

    Definitions
        Your command structure is defined using calls to the "cmd()" and
        "subcmd()" functions. The first argument to both functions is
        the name of the Perl class that implements the (sub-)command.

            cmd 'App::demo' => (
                comment => 'the demo command',
                optargs => sub {
                    arg command => (
                        isa      => 'SubCmd',
                        required => 1,
                        comment  => 'command to run',
                    );

                    opt quiet => (
                        isa     => 'Flag',
                        alias   => 'q',
                        comment => 'run quietly',
                    );
                },
            );

            subcmd 'App::demo::foo' => (
                comment => 'demo foo',
                optargs => sub {
                    arg action => (
                        isa      => 'Str',
                        required => 1,
                        comment  => 'command to run',
                    );
                },
            );

            subcmd 'App::demo::bar' => (
                comment => 'demo bar',
                optargs => sub {
                    opt baz => (
                        isa => 'Counter',
                        comment => '+1',
                    );
                },
            );

            # Command hierarchy for the above code:
            # demo COMMAND [OPTIONS...]
            #     demo foo ACTION [OPTIONS...]
            #     demo bar [OPTIONS...]

        An argument of type 'SubCmd' is an explicit indication that
        subcommands can occur in that position. The command hierarchy is
        based upon the natural parent/child structure of the class
        names. This definition can be done in your main script, or in
        one or more separate packages or plugins, as you like.

    Parsing
        The "class_optargs()" function is called instead of "optargs()"
        to parse the @ARGV array and call the appropriate "arg()" and
        "opt()" definitions as needed. It's first argument is generally
        the top-level command name you used in your first "cmd()" call.

            my ($class, $opts) = class_optargs('App::demo');

            printf "Running %s with %s\n", $class, Dumper($opts)
              unless $opts->{quiet};

        The additional return value $class is the name of the actual
        (sub-)command to which the $opts HASHref applies. Usage
        exceptions are raised just the same as with the "optargs()"
        function.

            error: unknown option "--invalid"

            usage: demo COMMAND [OPTIONS...]

                COMMAND       command to run
                  bar           demo bar
                  foo           demo foo

                --quiet, -q   run quietly

        Note that options are inherited by subcommands.

    Dispatch/Execution
        Once you have the subcommand name and the option/argument
        hashref you can either execute the action or dispatch to the
        appropriate class/package as you like.

        There are probably several ways to layout command classes when
        you have lots of subcommands. Here is one way that seems to work
        for this module's author.

        lib/App/demo.pm, lib/App/demo/subcmd.pm
            I typically put the actual (sub-)command implementations in
            lib/App/demo.pm and lib/App/demo/subcmd.pm. App::demo itself
            only needs to exists if the root command does something.
            However I tend to also make App::demo the base class for all
            subcommands so it is often a non-trivial piece of code.

        lib/App/demo/OptArgs.pm
            App::demo::OptArgs is where I put all of my command
            definitions with names that match the actual implementation
            modules.

                package App::demo::OptArgs;
                use OptArgs2;

                cmd 'App::demo' => (
                    comment => 'the demo app',
                    optargs => sub {
                        #...
                    },
                )

            The reason for keeping this separate from lib/App/demo.pm is
            speed of loading. I don't want to have to load all of the
            modules that App::demo itself uses just to find out that I
            called the command incorrectly.

        bin/demo
            The command script itself is then usually fairly short:

                #!/usr/bin/env perl
                use OptArgs2 'class_optargs';
                use App::demo::OptArgs;

                my ($class, $opts) = class_optargs('App::demo');
                eval "require $class" or die $@;
                $class->new->run($opts);

            The above does nothing more than load the definitions from
            App::demo::OptArgs, obtain the command name and options
            hashref, and then loads the appropriate package to run the
            command.

  Formatting of Usage Messages
    Usage messages attempt to present as much information as possible to
    the caller. Here is a brief overview of how the various types look
    and/or change depending on things like defaults.

    The presentation of Bool options in usage messages is as follows:

        Name        Type        Default         Presentation
        ----        ----        -------         ------------
        option      Bool        undef           --[no-]option
        option      Bool        true            --no-option
        option      Bool        false           --option
        option      Counter     *               --option

    The Flag option type is like a Bool that can only be set to true or
    left undefined. This makes sense for things such as "--help" or
    "--version" for which you never need to see a "--no" prefix.

        Name        Type        Default         Presentation
        ----        ----        -------         ------------
        option      Flag        always undef    --option

    Note that Flags also makes sense for "negative" options which will
    only ever turn things off:

        Name        Type        Default         Presentation
        ----        ----        -------         ------------
        no_option   Flag        always undef    --no-option

        # In Perl
        opt no_foo => (
            isa     => 'Flag',
            comment => 'disable the foo feature',
        );

        # Then later do { } unless $opts->{no_foo}

    The remaining types are presented as follows:

        Name        Type        isa_name        Presentation
        ----        ----        --------        ------------
        option      ArrayRef    -               --option Str
        option      HashRef     -               --option Str
        option      Int         -               --option Int
        option      Num         -               --option Num
        option      Str         -               --option Str
        option      *           XX              --option XX

    Defaults TO BE COMPLETED.

FUNCTIONS
    The following functions are exported by default.

    arg( $name, %parameters )
        Define a command argument, for example:

            arg name => (
                comment  => 'the file to parse',
                default  => '-',
                greedy   => 0,
                isa      => 'Str',
                # required => 1,
            );

        The "arg()" function accepts the following parameters:

        comment
            Required. Used to generate the usage/help message.

        default
            The value set when the argument is not given. Conflicts with
            the 'required' parameter.

            If this is a subroutine reference it will be called with a
            hashref containg all option/argument values after parsing
            the source has finished. The value to be set must be
            returned, and any changes to the hashref are ignored.

        greedy
            If true the argument swallows the rest of the command line.

        fallback
            A hashref containing an argument definition for the event
            that a subcommand match is not found. This parameter is only
            valid when "isa" is a "SubCmd". The hashref must contain
            "isa", "name" and "comment" key/value pairs, and may contain
            a "greedy" key/value pair.

            This is generally useful when you want to calculate a
            command alias from a configuration file at runtime, or
            otherwise run commands which don't easily fall into the
            OptArgs2 subcommand model.

        isa Required. Is mapped to a Getopt::Long type according to the
            following table:

                 optargs         Getopt::Long
                ------------------------------
                 'Str'           '=s'
                 'Int'           '=i'
                 'Num'           '=f'
                 'ArrayRef'      's@'
                 'HashRef'       's%'
                 'SubCmd'        '=s'
                 'OptArgRef'     's@'

            An *OptArgRef* isa is an *ArrayRef* that doesn't undergo
            checks for unexpected options. It exists to capture options
            and arguments which get passed back into *class_optargs*
            again.

        isa_name
            When provided this parameter will be presented instead of
            the generic presentation for the 'isa' parameter.

        required
            Set to a true value when the caller must specify this
            argument. Conflicts with the 'default' parameter.

        show_default
            Boolean to indicate if the default value should be shown in
            usage messages. Overrides the (sub-)command's "show_default"
            setting.

    class_optargs( $class, [ @argv ] ) -> ($subclass, $opts)
        Parse @ARGV by default (or @argv when given) for the arguments
        and options defined for command $class. @ARGV will first be
        decoded into UTF-8 (if necessary) from whatever I18N::Langinfo
        says your current locale codeset is.

        Throws an error / usage exception object (typically
        "OptArgs2::Usage") for missing or invalid arguments/options.
        Uses OptArgs2::Pager for 'ishelp' output.

        Returns the following two values:

        $subclass
            The actual subcommand name that was matched by parsing the
            arguments. This may be the same as $class.

        $opts
            a hashref containing key/value pairs for options and
            arguments *combined*.

        As an aid for testing, if the passed in argument @argv (not
        @ARGV) contains a HASH reference, the key/value combinations of
        the hash will be added as options. An undefined value means a
        boolean option.

    cmd( $class, %parameters ) -> OptArgs2::Cmd
        Define a top-level command identified by $class which is
        typically a Perl package name. The following parameters are
        accepted:

        abbrev
            When set to true then subcommands can be abbreviated, up to
            their shortest, unique values.

        comment
            A description of the command. Required.

        optargs
            A subref containing calls to "arg()" and "opt". Note that
            options are inherited by subcommands so you don't need to
            define them again in child subcommands.

        show_color
            Boolean indicating if usage messages should use ANSI
            terminal color codes to highlight different elements. True
            by default.

        show_default
            Boolean indicating if default values for options and
            arguments should be shown in usage messages. Can be
            overriden by sub-commands, args and opts. Off by default.

    opt( $name, %parameters )
        Define a command option, for example:

            opt colour => (
                alias        => 'c',
                comment      => 'the colour to paint',
                default      => 'blue',
                show_default => 1,
                isa          => 'Str',
            );

        Any underscores in $name are be replaced by dashes (-) for
        presentation and command-line parsing. The "arg()" function
        accepts the following parameters:

        alias
            A single character alias.

        comment
            Required. Used to generate the usage/help message.

        default
            The value set when the option is not given. Conflicts with
            the 'required' parameter.

            If this is a subroutine reference it will be called with a
            hashref containing all option/argument values after parsing
            the source has finished. The value to be set must be
            returned, and any changes to the hashref are ignored.

        required
            Set to a true value when the caller must specify this
            option. Conflicts with the 'default' parameter.

        hidden
            When true this option will not appear in usage messages
            unless the usage message is a help request.

            This is handy if you have developer-only options, or options
            that are very rarely used that you don't want cluttering up
            your normal usage message.

        isa Required. Is mapped to a Getopt::Long type according to the
            following table:

                isa              Getopt::Long
                ---              ------------
                 'ArrayRef'      's@'
                 'Flag'          '!'
                 'Bool'          '!'
                 'Counter'       '+'
                 'HashRef'       's%'
                 'Int'           '=i'
                 'Num'           '=f'
                 'Str'           '=s'

        isa_name
            When provided this parameter will be presented instead of
            the generic presentation for the 'isa' parameter.

        ishelp
            Makes the option behave like a typical "--help", that
            displays a usage message and exits before errors are
            generated. Typically used alone as follows:

                opt help => (
                    ishelp => OptArgs2::STYLE_HELP,
                );

                opt help_tree => (
                    ishelp => OptArgs2::STYLE_HELPTREE,
                    alias  => 'T', # or 'undef' if you don't want an alias
                );

            The first option above is similar to this longhand version:

                opt help => (
                    isa     => 'Flag',
                    alias   => 'h',   # first character of the opt name
                    comment => 'print a usage message and exit',
                    trigger => sub {
                        # Start a pager for long messages
                        print OptArgs2::usage(undef, OptArgs2::STYLE_HELP);
                        # Stop the pager
                        exit;
                    }
                );

            You can override any of the above with your own parameters.

        show_default
            Boolean to indicate if the default value should be shown in
            usage messages. Overrides the (sub-)command's "show_default"
            setting.

        trigger
            The trigger parameter lets you define a subroutine that is
            called after processing before usage exceptions are raised.
            This is primarily to support --help or --version options
            which would typically override usage errors.

                opt version => (
                    isa     => 'Flag',
                    alias   => 'V',
                    comment => 'print version string and exit',
                    trigger => sub {
                        my ( $cmd, $value ) = @_;
                        die "$cmd version $VERSION\n";
                    }
                );

            The trigger subref is passed two parameters: a OptArgs2::Cmd
            object and the value (if any) of the option. The
            OptArgs2::Cmd object is an internal one, but one public
            interface is has (in addition to the usage() method
            described in 'ishelp' above) is the usage_tree() method
            which gives a usage overview of all subcommands in the
            command hierarchy.

                opt usage_tree => (
                    isa     => 'Flag',
                    alias   => 'U',
                    comment => 'print usage tree and exit',
                    trigger => sub {
                        my ( $cmd, $value ) = @_;
                        die $cmd->usage_tree;
                    }
                );

                # demo COMMAND [OPTIONS...]
                #     demo foo ACTION [OPTIONS...]
                #     demo bar [OPTIONS...]

    optargs( [@argv] ) -> HASHref
        Parse @ARGV by default (or @argv when given) for the arguments
        and options defined for the *default global* command. Argument
        decoding and exceptions are the same as for "class_optargs", but
        this function returns only the combined argument/option values
        HASHref.

        This interface has been superceeded by "optargs2()".

    optargs2( @command_args_and_opts ) -> HASHref
        This all-in-one function passes it's arguments directly to
        "cmd()", calls "class_optargs()", and returns only the $opts
        HASHref result. It is the most convenient OptArgs2 interface for
        simple scripts.

    subcmd( $class, %parameters ) -> OptArgs2::Cmd
        Defines a subcommand identified by $class which must include the
        name of a previously defined (sub)command + '::'.

        Accepts the same parameters as "cmd()" in addition to the
        following:

        hidden
            Hide the existence of this subcommand in non-help usage
            messages. This is handy if you have developer-only or
            rarely-used commands that you don't want cluttering up your
            normal usage message.

    usage( $class, [STYLE] ) -> Str
        Only exported on request, this function returns the usage string
        for the command $class.

SEE ALSO
    OptArgs2::Pager, OptArgs2::StatusLine, Getopt::Long

    This module is duplicated on CPAN as Getopt::Args2, to cover both
    its original name and yet still be found in the mess that is
    Getopt::*.

SUPPORT & DEVELOPMENT
    This distribution is managed via github:

        https://github.com/mlawren/p5-OptArgs2/tree/devel

    This distribution follows the semantic versioning model:

        http://semver.org/

    Code is tidied up on Git commit using githook-perltidy:

        http://github.com/mlawren/githook-perltidy

AUTHOR
    Mark Lawrence <nomad@null.net>

LICENSE
    Copyright 2016-2022 Mark Lawrence <nomad@null.net>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

