SYNOPSIS

     use Getopt::Panjang qw(get_options);
    
     my $opts;
     my $res = get_options(
         # similar to Getopt::Long, except values must be coderef (handler), and
         # handler receives hash argument
         spec => {
             'foo'   => sub { $opts->{foo} = 1 },
             'bar=s' => sub { my %a = @_; $opts->{bar} = $a{value} },
         },
         argv => ["--bar", 1, "--foo"], # defaults to @ARGV
     );
    
     if ($res->[0] == 200) {
         # do stuffs with parsed options, $opts
     } else {
        warn "Can't parse command-line options";
        if ($res->[3]{'func.unknown_opts'}) {
            warn "There are some unknown options: ",
                join(",", keys %{$res->[3]{'func.unknown_opts'}});
        }
        if ($res->[3]{'func.ambiguous_opts'}) {
            warn "There are some ambiguous options: ",
                join(",", keys %{$res->[3]{'func.ambiguous_opts'}});
        }
        if ($res->[3]{'func.val_missing_opts'}) {
            warn "There are some options which miss values: ",
                join(",", keys %{$res->[3]{'func.val_missing_opts'}});
        }
        if ($res->[3]{'func.val_invalid_opts'}) {
            warn "There are some options with invalid values: ",
                join(",", keys %{$res->[3]{'func.val_invalid_opts'}});
        }
     }

DESCRIPTION

    EXPERIMENTAL WORK.

    This module is similar to Getopt::Long, but with a rather different
    interface. After experimenting with Getopt::Long::Less and
    Getopt::Long::EvenLess (which offers interface compatibility with
    Getopt::Long), I'm now trying a different interface which will enable
    me to "clean up" or do "more advanced" stuffs.

    Here are the goals of Getopt::Panjang:

      * low startup overhead

      Less than Getopt::Long, comparable to Getopt::Long::EvenLess.

      * feature parity with Getopt::Long::EvenLess

      More features will be offered in the future.

      * more detailed error return

      This is the main goal which motivates me to write Getopt::Panjang. In
      Getopt::Long, if there is an error like an unknown option, or
      validation error for an option's value, or missing option value, you
      only get a string warning. Getopt::Panjang will instead return a data
      structure with more details so you can know which option is missing
      the value, which unknown option is specified by the user, etc. This
      will enable scripts/frameworks to do something about it, e.g. suggest
      the correct option when mistyped.

    The interface differences with Getopt::Long:

      * There is only a single function, and no default exports

      Getopt::Long has GetOptions, GetOptionsFromArray,
      GetOptionsFromString. We only offer get_options which must be
      exported explicitly.

      * capitalization of function names

      Lowercase with underscores (get_options) is used instead of camel
      case (GetOptions).

      * get_options accepts hash argument

      This future-proofs the function when we want to add more
      configuration.

      * option handler also accepts hash argument

      This future-proofs the handler when we want to give more arguments to
      the handler.

      * There are no globals

      Every configuration is specified through the get_options function.
      This is cleaner.

      * get_options never dies, never prints warnings

      It only returns the detailed error structure so you can do whatever
      about it.

      * get_options never modifies argv/@ARGV

      Remaining argv after parsing is returned in the result metadata.

    Sample startup overhead benchmark:

    # COMMAND: perl devscripts/bench-startup 2>&1

SEE ALSO

    Getopt::Long

    Getopt::Long::Less, Getopt::Long::EvenLess

    Perinci::Sub::Getopt

