NAME

Getopt::Panjang - Parse command-line options

VERSION

This document describes version 0.04 of Getopt::Panjang (from Perl distribution Getopt-Panjang), released on 2015-09-15.

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 => {
        'bar'   => sub { $opts->{bar} = 1 },
        'baz=s' => sub { my %a = @_; $opts->{baz} = $a{value} },
        'err=s' => sub { die "Bzzt\n" },
    },
    argv => ["--baz", 1, "--bar"], # defaults to @ARGV
);

if ($res->[0] == 200) {
    # do stuffs with parsed options, $opts
} else {
    die $res->[1];
}

Sample success result when @ARGV is ["--baz", 1, "--bar"]:

[200, "OK", undef, { "func.remaining_argv" => [] }]

Sample error result (ambiguous option) when @ARGV is ["--ba", 1]:

[
  500,
  "Ambiguous option 'ba' (bar/baz?)",
  undef,
  {
    "func.ambiguous_opts" => { ba => ["bar", "baz"] },
    "func.remaining_argv" => [1],
  },
]

Sample error result (option with missing value) when @ARGV is ["--bar", "--baz"]:

[ 500, "Missing required value for option 'baz'", undef, { "func.remaining_argv" => [], "func.val_missing_opts" => { baz => 1 }, }, ]

Sample error result (unknown option) when @ARGV is ["--foo", "--qux"]:

[
   500,
  "Unknown options 'foo', 'qux'",
  undef,
  {
    "func.remaining_argv" => ["--foo", "--qux"],
    "func.unknown_opts"   => { foo => 1, qux => 1 },
  },
]

Sample error result (option with invalid value where the option handler dies) when @ARGV is ["--err", 1]:

[
  500,
  "Invalid value for option 'err': Invalid value for option 'err': Bzzt\n",
  undef,
  {
    "func.remaining_argv"   => [],
    "func.val_invalid_opts" => { err => "Invalid value for option 'err': Bzzt\n" },
  },
]

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:

                           Rate     load_gl      run_gl     load_gp       run_gp run_gl_less load_gl_less load_gl_evenless run_gl_evenless   perl
load_gl           73.23+-0.35/s          --       -2.6%      -65.4%       -65.5%      -68.0%       -70.9%           -78.9%          -80.0% -88.7%
run_gl            75.22+-0.17/s 2.71+-0.55%          --      -64.4%       -64.6%      -67.2%       -70.1%           -78.3%          -79.4% -88.3%
load_gp            211.4+-2.2/s 188.7+-3.3% 181.1+-2.9%          --        -0.5%       -7.7%       -16.0%           -39.1%          -42.2% -67.2%
run_gp           212.44+-0.86/s 190.1+-1.8% 182.4+-1.3%   0.5+-1.1%           --       -7.2%       -15.6%           -38.8%          -41.9% -67.1%
run_gl_less          229+-1.3/s 212.7+-2.3% 204.5+-1.8%   8.3+-1.3%   7.8+-0.74%          --        -9.0%           -34.0%          -37.4% -64.5%
load_gl_less     251.76+-0.83/s   243.8+-2% 234.7+-1.4%  19.1+-1.3% 18.51+-0.62% 9.93+-0.71%           --           -27.5%          -31.2% -61.0%
load_gl_evenless   347.1+-3.5/s   374+-5.3% 361.5+-4.8%  64.2+-2.4%   63.4+-1.8%  51.6+-1.7%   37.9+-1.5%               --           -5.1% -46.2%
run_gl_evenless    365.7+-1.8/s 399.4+-3.4% 386.2+-2.6%      73+-2%   72.1+-1.1%  59.7+-1.2% 45.26+-0.85%        5.3+-1.2%              -- -43.4%
perl               645.6+-6.8/s    782+-10% 758.3+-9.3% 205.3+-4.5%  203.9+-3.4% 181.9+-3.4%  156.4+-2.8%         86+-2.7%      76.5+-2.1%     --

Average times:
  perl            :     1.5489ms
  run_gl_evenless :     2.7345ms
  load_gl_evenless:     2.8810ms
  load_gl_less    :     3.9720ms
  run_gl_less     :     4.3668ms
  run_gp          :     4.7072ms
  load_gp         :     4.7304ms
  run_gl          :    13.2943ms
  load_gl         :    13.6556ms

FUNCTIONS

get_options(%args) -> [status, msg, result, meta]

Parse command-line options.

Arguments ('*' denotes required arguments):

  • argv => array[str]

    Command-line arguments, which will be parsed.

    If unspecified, will default to @ARGV.

  • spec* => hash

    Options specification.

    Similar like Getopt::Long and Getopt::Long::Evenless, this argument should be a hash. The keys should be option name specifications, while the values should be option handlers.

    Option name specification is like in Getopt::Long::EvenLess, e.g. name, name=s, name|alias=s.

    Option handler will be passed %args with the possible keys as follow: name (str, option name), value (any, option value). A handler can die with an error message to signify failed validation for the option value.

Returns an enveloped result (an array).

First element (status) is an integer containing HTTP status code (200 means OK, 4xx caller error, 5xx function error). Second element (msg) is a string containing error message, or 'OK' if status is 200. Third element (result) is optional, the actual result. Fourth element (meta) is called result metadata and is optional, a hash that contains extra information.

Return value: (any)

Will return 200 on parse success. If there is an error, like missing option value or unknown option, will return 500. The result metadata will contain more information about the error.

SEE ALSO

Getopt::Long

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

Perinci::Sub::Getopt

HOMEPAGE

Please visit the project's homepage at https://metacpan.org/release/Getopt-Panjang.

SOURCE

Source repository is at https://github.com/perlancar/perl-Getopt-Panjang.

BUGS

Please report any bugs or feature requests on the bugtracker website https://rt.cpan.org/Public/Dist/Display.html?Name=Getopt-Panjang

When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature.

AUTHOR

perlancar <perlancar@cpan.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2015 by perlancar@cpan.org.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.