=pod

=head1 NAME

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

=head1 SYNOPSIS

  use Getopt::Guided qw( getopts );

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

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

  # Parse result
  # %opts == ( a => 'av2', c => !!1, d => [ 'dv1', 'dv2', '--' ], v => 3 )
  # @ARGV == ( 'v1', 'v2' )

=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 (C<a>) is followed by a colon (C<:>) character or a comma
(C<,>) character, the option should have an option-argument which either
shall be supplied as a separate argument (C<-a foo>) or shall be part of the
same argument string as the option name (C<-afoo>).  We call an option whose
option name is followed by a colon/comma "option-argument indicator" a "common
option"/"list option". A list option is sometimes called "multi-value option".
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.

=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.

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 C<v+>
incrementable flag.

=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>

=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
