=pod

=head1 NAME

Getopt::Guided - getopts implementation that follows POSIX utility guidelines

=head1 GENERAL

This module adheres to the L<Semantic
Versioning|http://semver.org/spec/v2.0.0.html> scheme.  All of its
public functions (C<getopts()>, C<processopts()>, C<readopts()>,
C<print_version_info()>) and constants (EOOD, EXIT_SUCCESS, EXIT_FAILURE,
EXIT_USAGE) are exported on request.

=head1 SYNOPSIS

  use Getopt::Guided qw( getopts );

  my @argv = qw( -e ek1=ev1 -d dv1 -c -va av1 -ddv2 -a av2 -d -- -eek2=ev2 -vv v1 v2 );

  # If omitted @argv defaults to @ARGV
  getopts( 'a:e=bcd,v+', my %opts, @argv );

  # Parse result
  # %opts == ( a => 'av2', c => !!1, d => [ qw( dv1 dv2 -- ) ], e => { ek1 => 'ev1', ek2 => 'ev2' }, v => 3 )
  # @argv == ( 'v1', 'v2' )

  # ---

  use Getopt::Guided qw( print_version_info processopts );

  my @argv = qw( -v -I lib -vv -I local/lib/perl5 );

  processopts( @argv, 'V' => \&print_version_info, 'v+' => \my $verbosity, 'I,' => \my @inc );

  # Processing result
  # $verbosity == 3
  # @inc       == ( 'lib', 'local/lib/perl5' )
  # @argv      == ()

=head1 DESCRIPTION

The
L<getopts|https://pubs.opengroup.org/onlinepubs/9799919799/utilities/getopts.html>
POSIX utility retrieves options and option-arguments from a
list of command-line arguments. It supports the L<POSIX utility syntax
guidelines|https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap12.html#tag_12_02>
3 to 10, inclusive. C<getopts> is an iterator. The variable C<OPTIND>
(option index) stores the position of the next element of the command-line
argument list to be searched for an option name.

The C<getopts( $;$ )> function of the L<Getopt::Std> Perl core module provides
an implementation of the C<getopts> utility. It isn't an iterator function but
parses the command-line argument list in a single call.  C<Getopt::Guided>
exposes a new implementation through the C<getopts( $\%;\@ )> function. The
primary implementation differences are

  Topic                    | Getopt::Std impl  | Getopt::Guided impl
  -------------------------+-------------------+----------------------------
  exported                 | by default        | on request
  2nd parameter            | hash reference    | hash (passed by reference)
  3rd parameter (optional) | none              | array (passed by reference),
                           |                   | which defaults to @ARGV
  unknown option           | partial parse and | restore @ARGV and warn user
                           | warn user         |
  missing option-argument  | partial parse and | restore @ARGV and warn user
                           | don't warn user   |

=head1 COMMAND-LINE ARGUMENTS

A list of command-line arguments consists of options, option-arguments, and
operands.  The arguments that consist of hyphen-minus (C<->) characters and
single alphanumeric (C<[[:alnum:]]>) characters, are known as options. Certain
options are followed by an option-argument.  The arguments following the
last options and option-arguments are named operands.

In Perl the array L<@ARGV|perlvar/@ARGV> contains the command-line arguments.

=head1 OPTIONS SPECIFICATION

The options specification C<$spec> is the first parameter of the C<getopts()>
function.  It is a non-empty string containing the option names (the single
alphanumeric characters) recognized by the C<getopts()> function.

If an option name ("a") is followed by a colon (C<:>) character, a comma
(C<,>) character, or an equal sign (C<=>) character, the option should
have an option-argument which either shall be supplied as a separate
argument ("-a foo") or shall be part of the same argument string as the
option name ("-afoo").  We call an option whose option name is followed by a
colon/comma/equal sign "option-argument indicator" a common/list/map option. A
list option is sometimes called "multi-value option".  The option-argument
of a map option is a string of the form "key=value". The equal sign is
required. Both the key and the value can be empty.  The POSIX standard knows
only common options.

An option that does not require an option-argument is called a flag. The flag
name can optionally be followed by an exclamation mark (C<!>) character or
a plus sign (C<+>) character. We call a flag whose flag name is followed by
an exclamation mark/plus sign "flag-type indicator" a "negatable flag"/an
"incrementable flag". An incrementable flag is sometimes called "cumulative
flag". The POSIX standard doesn't know flag-type indicators.

=head1 NAME-VALUE MAP

The name-value map C<%opts> is the second parameter of the C<getopts()>
function. It is an empty hash (passed by reference) that stores the parse
result of the C<getopts()> function. Each hash key refers to an option
name and the corresponding hash value refers to the option-argument value
(or the flag value). The hash value of a list option is an array reference.
The hash value of a map option is a hash reference.

=head1 COMMAND-LINE ARGUMENTS LIST

The command-line arguments list C<@argv> is the third (optional) parameter of
the C<getopts()> function. It must be passed by reference. If this parameter is
omitted, the C<getopts()> function defaults to using the global C<@ARGV> array.

=head1 PARSING

The implementation follows the L<POSIX utility syntax
guidelines|https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap12.html#tag_12_02>
4 to 10, inclusive. The C<getopts()> function warns and returns false if
a parse error occurs; otherwise the function returns true. The parse error
types are:

=over 3

=item 1.

illegal option

=item 2.

option requires an argument

=back

The 2nd parse error occurs if either no argument or the C<undef> value is
provided for an option that has to have an option-argument.  If any of the
parse errors occurs, the C<getopts()> function restores C<@ARGV> and clears
C<%opts> before it warns and returns false.

=head2 REPEATED OPTIONS

If a common option is repeated, its option-arguments overwrite each other
and the last option-argument wins.  If a list option is repeated, its
option-arguments are pushed onto a list. If a map option is repeated, its
option-arguments are parsed into key-value pairs and are added to a map.

The appearance of a flag on the command line sets its value (initial value)
to true (C<!!1>).  If a flag with no flag-type indicator is repeated, its
initial value will not change.  If a negatable flag is repeated, its initial
value will be logically negated on each occurrence.  If an incrementable flag
is repeated, its initial value (its IV value) will be incremented by one on
each occurrence.  Use case: A verbosity level can be represented by a "v+"
incrementable flag.

=head1 SEMANTIC

The C<processopts( \@@ )> function adds semantic to the parse result provided
by the C<getopts()> function.

The command-line arguments list C<@argv> is the first parameter of the
C<processopts()> function.  The list must be passed by reference. A possible
value of this parameter is the global C<ARGV> array.  The remaining function
parameters form a non-empty list with an even number of elements. Each
even-numbered element represents a single "option specification".  The element
that follows such an option specification (an odd-numbered element) is called
its "option destination". The destination has to be a SCALAR, an ARRAY,
a HASH, or a CODE reference.

The option specification/option destination pairs are applied in order to
the parse result. This feature can be used to implement best practices such
as ensuring that a "-V" (version) option should have a higher precedence
(semantic priority) than a "-h" (help) option:

  processopts @argv, 'V' => sub { ... }, 'h' => sub { ... };

If an option belongs to the parse result and its destination is a SCALAR
reference, this reference points to the value of the corresponding C<%opts>
name-value map entry.

If a list option belongs to the parse result and its destination is an ARRAY
reference, this reference points to the list value of the corresponding
C<%opts> name-value map entry.

If a map option belongs to the parse result and its destination is a HASH
reference, this reference points to the hash value of the corresponding
C<%opts> name-value map entry.

If an option belongs to the parse result and its destination is a CODE
reference, the corresponding anonymous callback function is called with the
option-argument value (or the flag value) as its first, with the option
name as its second, and with the option-argument indicator (or flag-type
indicator) as its third argument. If the option (or flag) has no indicator,
the third argument is an empty string. The callback function is invoked in
scalar context. If the callback function returns the end of options delimiter
(C<-->), the C<processopts()> function stops prematurely. EOOD is a constant
that returns the end of options delimiter. If the callback function dies the
C<processopts()> function catches the error, warns and returns false.

The C<processopts()> function returns true (C<!!1>) on success; otherwise the
function returns false (C<!!0>). If the function stops prematurely, its return
value for true changes to the option name prefixed by the options delimiter.

=head1 DEFAULT OPTIONS

The C<readopts( \@ )> function reads default command-line options from a
rcfile and prepends them to the command-line arguments list C<@argv>. This
function is usually called immediately before the C<processopts()> function.

The basename of the rcfile is the program name with the
extension C<rc>. The dirname of the rcfile is defined by the
environment variable XDG_CONFIG_HOME (L<XDG Base Directory
Specification|https://specifications.freedesktop.org/basedir/latest/>).

The rcfile must contain one option per line. This implies that options must
not be grouped. Each line is either a simple flag name or an option name
followed by a space character and an option-argument value. Neither the
flag name nor the option name should start with the option delimiter (C<->).
Option-argument values should not be quoted even if they include spaces.
Example rcfile content:

  # verbose
  v
  # jobs
  j 9

=head1 PROGRAM VERSION

The GNU coding standard provides some guideline how a "-V" (version) option
should behave. This module provides the C<print_version_info()> function. It
can be used as a "-V" option destination callback function. The function
implements some recommendations. It prints information about the program name
(the basename of L<$0|perlvar/$0>), and its version to standard output. As
a second information line it prints the version of the perl interpreter to
standard output too. Example output:

  foo v1.2.3
  perl v5.14.2

The function returns the end of options delimiter, so that the C<processopts()>
function stops prematurely.

=head1 SEE ALSO

=over 2

=item *

L<Tie::Hash::MultiValueOpts>

=item *

L<Tacit list of POSIX short options|https://stackoverflow.com/questions/56131811/is-there-a-tacit-list-of-reserved-names-for-posix-short-options>

=item *

L<The -W option of GNU getopt()|https://stackoverflow.com/questions/14338223/what-is-the-w-option-of-gnu-getopt-used-for>

=item *

L<Getopt::ArgvFile>

=item *

L<Configuration file for command-line options|https://pasdoc.github.io/ConfigFileOption>

=back

=head1 AUTHOR

Sven Willenbuecher <sven.willenbuecher@gmx.de>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2025 by Sven Willenbuecher.

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

=cut
