Getopt::Declare(3pm)
π Getopt::Declare(3pm) π
okay so bestie, this is the manual page for Getopt::Declare from the User Contributed Perl Documentation. It's giving iconic, it's giving powerful, and we're about to break it all the way down. β¨
πΈ NAME πΈ
Getopt::Declare β Declaratively Expressed Command-Line Arguments via Regular Expressions. periodt. π
π VERSION π
This document describes version 1.14 of Getopt::Declare. No cap. π«Ά
π¦ SYNOPSIS π¦
use Getopt::Declare;
$args = Getopt::Declare->new($specification_string, $optional_source);
# or:
use Getopt::Declare $specification_string => $args;
π DESCRIPTION π
π Overview π
Getopt::Declare is yet another command-line argument parser, one which is specifically designed to be powerful but exceptionally easy to use. Like, it really said "I'm the main character" and then delivered. π
To parse the command-line in @ARGV, one simply creates a Getopt::Declare object, by passing Getopt::Declare::new() a specification of the various parameters that may be encountered:
use Getopt::Declare;
$args = Getopt::Declare->new($specification);
This may also be done in a one-liner:
use Getopt::Declare, $specification => $args;
The specification is a single string such as this:
$specification = q(
-a Process all data
-b <N:n> Set mean byte length threshold to <N>
{ bytelen = $N; }
+c <FILE> Create new file <FILE>
--del Delete old file
{ delold() }
delete [ditto]
e <H:i>x<W:i> Expand image to height <H> and width <W>
{ expand($H,$W); }
-F <file>... Process named file(s)
{ defer {for (@file) {process()}} }
=getrand [<N>] Get a random number
(or, optionally, <N> of them)
{ $N = 1 unless defined $N; }
-- Traditionally indicates end of arguments
{ finish }
);
Note that in each of the cases above, there is a tab between each parameter definition and description (even if you can't see it)! In the specification, the syntax of each parameter is declared, along with a description and (optionally) one or more actions to be performed when the parameter is encountered. The specification string may also include other usage formatting information (such as group headings or separators) as well as standard Perl comments (which are ignored). π§
Calling Getopt::Delare::new() parses the contents of the array @ARGV, extracting any arguments which match the parameters defined in the specification string, and storing the parsed values as hash elements within the new Getopt::Declare object being created. (And yes, the typo Delare is literally in the original, bestie β we don't fix it, we respect the lore. π)
Other features of the Getopt::Declare package include:
- The use of full Perl regular expressions to constrain matching of parameter components. π₯
- Automatic generation of error, usage and version information. β¨
- Optional conditional execution of embedded actions (i.e. only on successful parsing of the entire command-line) π
- Strict or non-strict parsing (unrecognized command-line elements may either trigger an error or may simply be left in
@ARGV) π - Declarative specification of various inter-parameter relationships (for example, two parameters may be declared mutually exclusive and this relationship will then be automatically enforced). π
- Intelligent clustering of adjacent flags (for example: the command-line sequence
-a -b -cmay be abbreviated to-abc, unless there is also a-abcflag declared). π§ - Selective or global case-insensitivity of parameters. π
- The ability to parse files (especially configuration files) instead of the command-line. π
π Terminology π
The terminology of command-line processing is often confusing, with various terms (such as "argument", "parameter", "option", "flag", etc.) frequently being used interchangeably and inconsistently in the various Getopt:: packages available. In this documentation, the following terms are used consistently:
"command-line"β The space-separated concatenation of the elements of the array@ARGVat the time aGetopt::Declareobject is created."parameter specification"(or just"parameter") β A specification of a single entity which may appear in the command-line. Always includes at least one syntax for the entity. Optionally may include other (variant) syntaxes, one or more descriptions of the entity, and/or actions to be performed when the entity is encountered. For example, the following is a single parameter specification (with two variants):
--window <height> x <width> Set window to <height> by <width>
{ setwin($width,$height); }
--window <h>x<w>@<x>,<y> Set window size and centroid
{ setwin($w,$h,$x,$y); }
"argument"β A substring of the command-line which matches a single parameter variant. Unlike some otherGetopt::packages, inGetopt::Declarean argument may be a single element of@ARGV, or part of a single@ARGVelement, or the concatenation of several adjacent@ARGVelements."parameter definition"β A specification of one actual syntax variant matched by a parameter. Always consists of a leading parameter flag or parameter variable, optionally followed by one or more parameter components (that is, other parameter variables or punctuators). In the above example,"--window <height> x <width>"is a parameter definition."parameter flag"(or just"flag") β A sequence of non-space characters which introduces a parameter. Traditionally a parameter flag begins with"-"or"--", butGetopt::Declareallows almost any sequence of characters to be used as a flag. In the above example,"--window"is the parameter flag."parameter variable"β A place-holder (within a parameter specification) for a value that will appear in any argument matching that parameter. In the above example,"<height>","<width>","<h>","<y>","<x>", and"<y>"are all parameter variables."parameter punctuator"(or just"punctuator") β A literal sequence of characters (within a parameter specification) which will appear in any argument matching that parameter. In the above example, the literals"x"and"@"are punctuators."parameter description"β A textual description of the purpose and/or use of a particular variant of parameter. In the above examples, the string:
Set window to <height> by <width>
is a parameter description.
"parameter action"(or just"action") β A block of Perl code to be executed in response to encountering a specific parameter. In the above example:
{ setwin($width,$height); }
is a parameter action.
"parameter variants"β One or more different syntaxes for a single parameter, all sharing the same leading flag, but having different trailing parameter variables and/or punctuators.Getopt::Declareconsiders all parameter definitions with the same leading flag to be merely variant forms of a single "underlying" parameter. The above example shows two parameter variants for the"--window"parameter.
π¦ Parameter definitions π¦
As indicated above, a parameter specification consists of three parts: the parameter definition, a textual description, and any actions to be performed when the parameter is matched.
The parameter definition consists of a leading flag or parameter variable, followed by any number of parameter variables or punctuators, optionally separated by spaces. The parameter definition is terminated by the first tab that is encountered after the start of the parameter definition. At least one trailing tab must be present.
For example, all of the following are valid Getopt::Declare parameter definitions:
-v
in=<infile>
+range <from>..<to>
--lines <start> - <stop>
ignore bad lines
<outfile>
Note that each of the above examples has at least one trailing tab (even if you can't see them)!. Note too that this hodge-podge of parameter styles is certainly not recommended within a single program, but is shown so as to illustrate some of the range of parameter syntax conventions Getopt::Declare supports. iykyk. π
The spaces between components of the parameter definition are optional but significant, both in the definition itself and in the arguments that the definition may match. If there is no space between components in the specification, then no space is allowed between corresponding arguments on the command-line. If there is space between components of the specification, then space between those components is optional on the command-line.
For example, the "--lines" parameter above matches:
--lines1-10
--lines 1-10
--lines 1 -10
--lines 1 - 10
--lines1- 10
If it were instead specified as:
--lines <start>-<stop>
then it would match only:
--lines1-10
--lines 1-10
Note that the optional nature of spaces in parameter specification implies that flags and punctuators cannot contain the character '<' (which is taken as the delimiter for a parameter variable) nor the character '[' (which introduces an optional parameter component - see "Optional parameter components"). important!! π¨
π Types of parameter variables π
By default, a parameter variable will match a single blank-terminated or comma-delimited string. For example, the parameter:
-val <value>
would match any of the following arguments:
-value # <value> <- "ue"
-val abcd # <value> <- "abcd"
-val 1234 # <value> <- "1234"
-val "a value" # <value> <- "a value"
It is also possible to restrict the types of values which may be matched by a given parameter variable. For example:
-limit <threshold:n> Set threshold to some (real) value
-count <N:i> Set count to <N> (must be an integer)
If a parameter variable is suffixed with ":n", it will match any reasonable numeric value, whilst the ":i" suffix restricts a parameter variable to only matching integer values. These two "type specifiers" are the simplest examples of a much more powerful mechanism, which allows parameter variables to be restricted to matching any specific regular expression. See "Defining new parameter variable types". the plot thickensβ¦ π
Parameter variables are treated as scalars by default, but bestie, that too can be altered π
. Any parameter variable that's immediately followed by an ellipsis (...) becomes a list variable, and it matches its specified type sequentially as many times as it possibly can. Like, as many as it can get away with. For example, this parameter spec:
-pages <page:i>...
would match either of these arguments:
-pages 1
-pages 1 2 7 20
ngl, the way both scalar and list parameter variables are "respectful" of the flags of other parameters, and of their own trailing punctuators? Iconic behaviour, honestly π«Ά. For example, given these specs:
-a
-b <b_list>...
-c <c_list>... ;
the following arguments will be parsed as indicated:
-b -d -e -a # <b_list> <- ("-d", "-e")
-b -d ; # <b_list> <- ("-d", ";")
-c -d ; # <c_list> <- ("-d")
List parameter variables are also respectful of the needs of subsequent parameter variables, which is very giving-and-taking of them. So a parameter spec like:
-copy <files>... <dir>
will behave exactly as expected, putting all but the very last string after the -copy flag into the parameter variable <files>, whilst the very last string gets assigned to <dir>. No stealing, no drama π.
Optional parameter components π
Except for the leading flag, any part of a parameter definition may be made optional by wrapping it in square brackets. Like so:
+range <from> [..] [<to>]
which matches any of:
+range 1..10
+range 1..
+range 1 10
+range 1
List parameter variables can be made optional too β but heads up, the ellipsis has to follow the parameter variable name immediately, so it goes inside the square brackets:
-list [<page>...]
Two or more parameter components can be made jointly optional by putting them in the same pair of brackets. And optional components can be nested, because of course they can, we love recursion β¨:
-range <from> [.. [<to>] ]
Scalar optional parameter variables (like [<to>]) get given undefined values if they get skipped during a successful parameter match. List optional parameter variables (like [<page>...]) get assigned an empty list if unmatched. Fair's fair πΈ.
One important use for optional punctuators is to give you abbreviated versions of specific flags. For example:
-num[eric] # Match "-num" or "-numeric"
-lexic[ographic]al # Match "-lexical" or "-lexicographical"
-b[ells+]w[histles] # Match "-bw" or "-bells+whistles"
Note that the actual flags for these three parameters are -num, -lexic and -b, respectively. iykyk π
Parameter descriptions π
Giving a textual description for each parameter (or parameter variant) is optional, but likeβ¦ strongly recommended, bestie. Apart from being internal documentation (which your future self will thank you for, fr fr), parameter descriptions are what get used in the automatically-generated usage information provided by Getopt::Declare. So it's not just for you, it's for everyone π.
Descriptions go after the first tab(s) following the parameter definition, and can continue onto subsequent lines β provided those lines do not contain any tabs after the first non-whitespace character, because any line that does will instead be treated as a new parameter specification. The description is terminated by a blank line, an action specification (see below) or another parameter specification.
For example:
-v Verbose mode
in=<infile> Specify input file
(will fail if file does not exist)
+range <from>..<to> Specify range of columns to consider
--lines <start> - <stop> Specify range of lines to process
ignore bad lines Ignore bad lines :-)
<outfile> Specify an output file
The parameter description may also contain special directives which alter the way in which the parameter is parsed. See the various subsections of "ADVANCED FEATURES" for more information π.
A common mistake β and bestie, not me watching you do this β is to use tabs to separate components of a parameter description:
-delete <filename> Delete the named file
-d <filename> Delete the named file
The tabs after -delete and -d do a genuinely great job of lining up the two <filename> parameter variables⦠but they also mark the start of the description, which means that once descriptions are stripped, the two parameters are actually just:
-delete
-d
The solution? Use spaces, not tabs, to align components within a parameter specification. Periodt π .
Actions β‘
Each parameter specification may also include one or more blocks of Perl code, specified in a pair of curly brackets β and those brackets must start on a new line.
Each action is executed as soon as the corresponding parameter is successfully matched in the command-line (but see "Deferred actions" for a means of delaying this response, if you're into that π).
For example:
-v Verbose mode
{ $::verbose = 1; }
-q Quiet mode
{ $::verbose = 0; }
Actions are executed (as do blocks) in the package in which the Getopt::Declare object containing them was created. So they have access to all package variables and functions in that namespace β main character energy, obviously π.
In addition, each parameter variable belonging to the corresponding parameter is made available as a (block-scoped) Perl variable with the same name. For example:
+range <from>..<to> Set range
{ setrange($from, $to); }
-list <page:i>... Specify pages to list
{ foreach (@page)
{
list($_) if $_ > 0;
}
}
Note that scalar parameter variables become scalar Perl variables, and list parameter variables become Perl arrays. Simple as π¦.
Predefined variables available in actions π
Within an action the following variables are also available:
$_PARAM_
Stores the identifier of the current parameter: either the leading flag or, if there is no leading flag, the name of the first parameter variable. Either way, it's serving cunt π .
%_PUNCT_
Stores the substring matched by each punctuator in the current parameter. The hash is indexed by the punctuator itself. The main purpose of this variable is to allow actions to check whether optional punctuators were in fact matched. For example:
-v[erbose] Set verbose mode
(doubly verbose if full word used)
{ if ($_PUNCT_{"erbose"}) { $verbose = 2; }
else { $verbose = 1; }
}
%_FOUND_
This hash stores boolean values indicating whether or not a given parameter has already been found. The hash keys are the leading flags or parameter variables of each parameter. For instance, the following specification makes the -q and -v parameters mutually exclusive (but see "Parameter dependencies" for a much easier way to achieve this effect β because bestie, there absolutely is one π):
-v Set verbose mode
{ die "Can't be verbose *and* quiet!\n"
if $_FOUND_{"-q"};
}
-q Set quiet mode
{ die "Can't be quiet *and* verbose!\n"
if $_FOUND_{"-v"};
}
For reasons that will be explained in "Rejection and termination", a given parameter is not marked as found until after its associated actions are executed. That is, $_FOUND_{$_PARAM_} will not (usually) be true during a parameter action. Sneaky little timing thing, we love her π.
β οΈ Note that, although numerous other internal variables on which the generated parser relies are also visible within parameter actions, accessing any of them may have Dire Consequences. Moreover, these other variables may no longer be accessible (or even present) in future versions of Getopt::Declare. All such internal variables have names beginning with an underscore. Avoiding such variable names will ensure there are no conflicts between actions and the parser itself. Do not touch. Not even a little. π
The command-line parsing process π
Whenever a Getopt::Declare object is created, the current command-line is parsed sequentially, by attempting to match each parameter in the object's specification string against the current elements in the @ARGV array (but see "Parsing from other sources"). The order in which parameters are compared against the arguments in @ARGV is determined by three rules:
- Parameters with longer flags are tried first. Hence the command-line argument
-quietwould be parsed as matching the parameter-quietrather than the parameter-q <string>, even if the-qparameter was defined first. - Parameter variants with the most components are matched first. Hence the argument
-rand 12345would be parsed as matching the parameter variant-rand <seed>, rather than the variant-rand, even if the "shorter"-randvariant was defined first. - Otherwise, parameters are matched in the order they are defined.
Note, however, that the arguments themselves are considered strictly in the order they appear on the command line. That is: Getopt::Declare takes the first (leftmost) argument and compares it against all the parameter specifications in the order described above. Then it gets the second argument and does the same. Et cetera. So, whilst parameters are considered "flags-first-by-length", arguments are considered "left-to-right". If that seems paradoxical, bestie, you probably need to review the difference between "arguments" and "parameters", as explained in "Terminology" π§.
Elements of @ARGV which do not match any defined parameter are collected during the parse and are eventually put back into @ARGV (see "Strict and non-strict command-line parsing"). They're not lost, they're justβ¦ chilling β¨.
β¨ ADVANCED FEATURES β¨
Case-insensitive parameter matching π
By default, a Getopt::Declare object parses the command-line in a case-sensitive manner. The [nocase] directive enables a specific parameter (or, alternatively, all parameters) to be matched case-insensitively.
If a [nocase] directive is included in the description of a specific parameter variant, then that variant (and only that variant) will be matched without regard for case. For example, this specification:
-q Quiet mode [nocase]
-v Verbose mode
means that the arguments -q and -Q will both match the -q parameter, but that only -v (and not -V) will match the -v parameter. Picky! And we respect it π
.
If a [nocase] directive shows up anywhere outside a parameter description, then the whole entire spec gets declared case-insensitive and every parameter defined in that spec gets matched without regard to case. periodt π
π Termination and rejection π
Sometimes you wanna bail out of command-line processing before all the arguments have been parsed. Like, you're done, you've seen enough, bye. For that, Getopt::Declare hands you a special local operator called finish that you can drop inside actions. It takes one optional argument: if that argument is true (or you just omit it entirely), command-line processing stops right then and there β though the current parameter still counts as successfully matched, bestie, don't worry π
Check it:
-- Traditional argument list terminator
{ finish }
-no-- Use non-traditional terminator instead
{ $nontrad = 1; }
## Non-traditional terminator (only valid if -no-- flag seen)
{ finish($nontrad); }
You can also reject a single parameter match from inside an action, and then keep on trying other candidates. This is the move when you want your actions to do fancier tests on the type of a parameter variable, or to implement messy complicated parameter interdependencies β¨
To reject a parameter match you use the reject operator, which also takes an optional argument. If that argument is true (or was omitted), the current parameter match gets rejected immediately. Like so:
-ar <R:n> Set aspect ratio (must be in the range (0..1])
{
$::sawaspect++;
reject $R <= 0 || $R > 1 ;
setaspect($R);
}
-q Quiet option (not available on Wednesdays)
{
reject((localtime)[6] == 3);
$::verbose = 0;
}
β οΈ Heads up bestie: any actions you already ran before the call torejectstill take effect. So yeah β the variable$::sawaspectstays incremented even if the aspect ratio parameter gets rejected afterwards. The side effects are already out there, no take-backs π
The reject operator can also take a second argument, which gets used as an error message if the rejected argument then fails to match any other parameter. Like:
-q Quiet option (not available on Wednesdays)
{
reject((localtime)[6] == 3 => "Not today!");
$::verbose = 0;
}
π’ Specifying other parameter variable types π’
So remember back in "Type of parameter variables" we said parameter variables can be restricted to matching only numbers or only integers with the type specifiers :n and :i? Well, Getopt::Declare also serves up seven other inbuilt type specifiers, plus two whole mechanisms for defining your own new restrictions on parameter variables. Iconic behaviour honestly π
The other inbuilt type specifiers are:
:+iβ restricts a parameter variable to matching positive, non-zero integers (that is:1,2,3, etc.):+nβ restricts a parameter variable to matching positive, non-zero numbers (that is, floating point numbers strictly greater than zero).:0+iβ restricts a parameter variable to matching non-negative integers (that is:0,1,2,3, etc.):0+nβ restricts a parameter variable to matching non-negative numbers (that is, floating point numbers greater than or equal to zero).:qsβ allows a parameter variable to match any quote-delimited or whitespace-terminated string. Note that this specifier simply makes explicit the default behaviour.:idβ allows a parameter variable to match any identifier sequence. That is: a alphabetic or underscore, followed by zero-or-more alphanumerics or underscores.:ifβ used to match input file names. Like type:s, type:ifmatches any quote-delimited or whitespace-terminated string. However this type does not respect other command-line flags and also requires that the matched string is either-(indicating standard input) or the name of a readable file.:ofβ used to match output file names. It is exactly like type:ifexcept that it requires that the string is either-(indicating standard output) or the name of a file that is either writable or non-existent.:sβ allows a parameter variable to match any quote-delimited or whitespace-terminated string. Note that this specifier simply makes explicit the default behaviour.
For example:
-repeat <count:+i> Repeat <count> times (must be > 0)
-scale <factor:0+n> Set scaling factor (cannot be negative)
Alternatively, parameter variables can be restricted to matching a specific regular expression, by handing over the required pattern explicitly (in matched / delimiters after the :). For example:
-parity <p:/even|odd|both/> Set parity (<p> must be "even",
"odd" or "both")
-file <name:/\w*\.[A-Z]{3}/> File name must have a three-
capital-letter extension
If you go with an explicit regular expression, there are three "convenience" extensions you get to use, and they're lowkey so handy:
%Tβ if the sequence%Tappears in a pattern, it is translated to a negative lookahead containing the parameter variable's trailing context. Hence the parameter definition:
-find <what:/(%T\.)+/> ;
ensures that the command line argument -find abcd; causes <what> to match abcd, not abcd;. π
%Dβ if the sequence%Dappears in a pattern, it is translated into a subpattern which matches any single digit (like a\d), but only if that digit would not match the parameter variable's trailing context. Hence%Dis just a convenient short-hand for(?:%T\d)(and is actually implemented that way).%Fβ by default, any explicit pattern is modified by Getopt::Declare so that it fails if the argument being matched represents some defined parameter flag. If however the sequence%Fappears anywhere in a pattern, it causes the pattern not to reject strings which would otherwise match another flag. By default, no inbuilt type allows arguments to match a flag.
π§ͺ Defining new parameter variable types π§ͺ
Explicit regular expressions are super powerful, no cap, but they're also kinda cumbersome to use (or reuse) in some situations. So Getopt::Declare gives you a general "parameter variable type definition" mechanism to make those cases way simpler π
To declare a new parameter variable type, you use the [pvtype:...] directive. A [pvtype...] directive specifies the name, matching pattern, and action for the new parameter variable type β though both the pattern and the action are optional.
The name string may be any whitespace-terminated sequence of characters which does not include a >. The name may also be specified within a pair of quotation marks (single or double) or within any Perl quotelike operation. For example:
[pvtype: num ] # Makes this valid: -count <N:num>
[pvtype: 'a num' ] # Makes this valid: -count <N:a num>
[pvtype: q{nbr} ] # Makes this valid: -count <N:nbr>
The pattern is used in initial matching of the parameter variable. Patterns are normally specified as a /.../-delimited Perl regular expression:
[pvtype: num /\d+/ ]
[pvtype: 'a num' /\d+(?:\.\d*)/ ]
[pvtype: q{nbr} /[+-]?\d+/ ]
π Okay important: the regular expression should not contain any capturing parentheses, because that will interfere with the correct processing of subsequent parameter variables. Not a vibe, just don't.
Alternatively the pattern associated with a new type may be specified as a : followed by the name of another parameter variable type (in quotes if necessary). In this case the new type matches the same pattern (and action! β see below) as the named type. For example:
[pvtype: num :+i ] # <X:num> is the same as <X:+i>
[pvtype: 'a num' :n ] # <X:a num> is the same as <X:n>
[pvtype: q{nbr} :'a num' ] # <X:nbr> is also the same as <X:n>
As a third alternative, the pattern may be omitted altogether, in which case the new type matches whatever the inbuilt pattern :s matches.
The optional action which may be included in any [pvtype:...] directive is executed after the corresponding parameter variable matches the command line but before any actions belonging to the enclosing parameter are executed. Typically, such type actions will call the reject operator (see "Termination and rejection") to test extra conditions, but any valid Perl code is acceptable. For example:
[pvtype: num /\d+/ { reject if (localtime)[6]==3 } ]
[pvtype: 'a num' :n { print "a num!" } ]
[pvtype: q{nbr} :'a num' { reject $::no_nbr } ]
If a new type is defined in terms of another (for example, :a num and :nbr above), any action specified by that new type is prepended to the action of that other type. Hence:
- the new type
:nummatches any string of digits, but then rejects the match if it's Wednesday. - the new type
:a nummatches any string of digits (like its parent type:num), then prints outa num!, and then rejects the match if it's Wednesday (like its parent type:num). - the new type
:nbrmatches any string of digits (like its parent type:a num), but then rejects the match if the global$::no_nbrvariable is true. Otherwise it next prints outa num!(like its parent type:a num), and finally rejects the match if it's Wednesday (like its grandparent type:num).
When a type action is executed (as part of a particular parameter match), three local variables are available to you:
$_VAL_β which contains the value matched by the type's pattern. It is this value which is ultimately assigned to the local Perl variable which is available to parameter actions. Hence if the type action changes the value of$_VAL_, that changed value becomes the "real" value of the corresponding parameter variable (see the Roman numeral example below). πΈ$_VAR_β which contains the name of the parameter variable being matched.$_PARAM_β which contains the name of the parameter currently being matched.
Here is a example of the use of these variables:
$specs = q{
[pvtype: type /[OAB]|AB')/ ]
[pvtype: Rh? /Rh[+-]/ ]
[pvtype: days :+i { reject $_VAL_<14 " $_PARAM_ (too soon!)"} ]
-donated <D:days> Days since last donation
-applied <A:days> Days since applied to donate
-blood <type:type> [<rh:Rh?>] Specify blood type
and (optionally) rhesus factor
};
$args = Getopt::Declare->new($specs);
ok so in that lil example up there, the :days parameter variable type is defined to match whatever the :+i type matches β so like, positive non-zero integers, bestie β with the extra catch that the matching value ($_VAL_) has to be at least 14. So if you pass a shorter value for the <D> or <A> parameter variables, Getopt::Declare hits you with these respective error messages:
Error: -donated (too soon!)
Error: -applied (too soon!)
And heads up, the "inbuilt" parameter variable types (i, n, etc.) are literally just predefined type names, so you can absolutely alter them if you need to:
$args = Getopt::Declare->new(<<'EOPARAM');
[pvtype: 'n' /[MDCLXVI]+/ { reject !($_VAL_=to_roman $_VAL_) } ]
-index <number:n> Index number
{ print $data[$number]; }
EOPARAM
That [pvtype:...] directive up there means every parameter variable specified with a type :n from that point on only matches valid Roman numerals, but any such numerals get auto-converted into ordinary numbers (by passing $_VAL_ through the to_roman function). π«
So the requirement that all :n numbers now have to be Roman can be imposed transparently, at least as far as the actual parameter variables that use the :n type are concerned. Which means $number can still be used to index the array @data even with the new restrictions the redefinition of type :n places on it. slay.
Also note β because the :+n and :0+n types are implicitly defined in terms of the original :n type (like, as if these directives:
[pvtype: '+n' :n { reject if $_VAL <= 0 } ]
[pvtype: '0+n' :n { reject if $_VAL < 0 } ]
were included in every single specification), that redefinition of :n up there affects those types too. In such cases the format conversion happens before the "sign" tests β aka, the "inherited" actions run after any newly defined ones.
Parameter variable type definitions can appear anywhere in a Getopt::Declare specification and are effective for the entire scope of the specification. And yes, that means new parameter variable types can be defined after they're used. no cap. π
π Undocumented parameters π
If a parameter description is omitted, or is entirely whitespace, or contains the special directive [undocumented], then the parameter still gets parsed like normal β but it won't show up in the automatically generated usage information (peep "Usage information").
Other than enabling "secret" parameters (a, uh, dubious benefit ngl), this feature lets the programmer specify some undocumented action to take on encountering an otherwise unknown argument. Like:
<unknown>
{ handle_unknown($unknown); }
πͺ "Dittoed" parameters πͺ
Sometimes you want two or more alternate flags that do the same thing (usually a short form and a long form). To save you the pain of specifying such pairs, there's a special directive: [ditto]. If a parameter's description begins with a [ditto] directive, that directive gets replaced with the description of the immediately preceding parameter (including any other directives). For example:
-v Verbose mode
--verbose [ditto] (long form)
In the automatically generated usage information this displays as:
-v Verbose mode
--verbose " " (long form)
And bonus: if the "dittoed" parameter has no action(s) specified, the action(s) of the preceding parameter get reused. So this spec:
-v Verbose mode
{ $::verbose = 1; }
--verbose [ditto]
would make the --verbose option set $::verbose just like -v does. But on the flip side, this spec:
-v Verbose mode
{ $::verbose = 1; }
--verbose [ditto]
{ $::verbose = 2; }
gives separate actions to each flag. choose your fighter bestie π
β³ Deferred actions β³
It's often desirable (or straight up necessary) to defer actions taken in response to particular flags until the entire command-line has been parsed. The most obvious case? When modifier flags have to be specifiable after the command-line arguments they modify. iconic behavior honestly.
To support this, Getopt::Declare gives you a local operator called defer, which delays the execution of a particular action until command-line processing is done. The defer operator takes a single block, and that block's execution is deferred until the command-line is fully and successfully parsed. And if command-line processing fails for some reason (see "DIAGNOSTICS"), the deferred blocks are never executed. π
For example:
<files>... Files to be processed
{ defer { foreach (@files) { proc($_); } } }
-rev[erse] Process in reverse order
{ $::ordered = -1; }
-rand[om] Process in random order
{ $::ordered = 0; }
With that spec up there, the -rev and/or -rand flags can be specified after the list of files and still affect how those files get processed. And even better β if the command-line parsing fails for some reason (maybe an unrecognized argument π), the deferred processing won't be performed at all. safe. π«Ά
πΈ Flag clustering πΈ
Like some other Getopt:: packages, Getopt::Declare lets parameter flags be "clustered". Meaning: if two or more flags share the same "flag prefix" (one or more leading non-whitespace, non-alphanumeric characters), those flags can be concatenated behind a single copy of that flag prefix. For example, given these parameter specifications:
-+ Swap signs
-a Append mode
-b Bitwise compare
-c <FILE> Create new file
+del Delete old file
+e <NICE:i> Execute (at specified nice level) when complete
The following command-lines (amongst others) are all exactly equivalent:
-a -b -c newfile +e20 +del
-abc newfile +dele20
-abcnewfile+dele20
-abcnewfile +e 20del
The last two alternatives parse correctly because Getopt::Declare allows flag clustering at any point where the remainder of the command-line being processed starts with a non-whitespace character and where the remaining substring wouldn't otherwise immediately match a parameter flag.
So that trailing +dele20 in the third command-line example parses as +del +e20, not -+ del +e20. Why? Because the previous - prefix isn't propagated (since the leading +del is a valid flag).
Meanwhile the trailing +e 20del in the fourth example parses as +e 20 +del, because after the 20 gets parsed (as the integer parameter variable <NICE>), the next characters are del β which don't form a flag themselves unless prefixed with the controlling +.
In some circumstances a clustered sequence of flags on the command-line might also match a single (multicharacter) parameter flag. For example, given these specs:
-a Blood type is A
-b Blood type is B
-ab Blood type is AB
-ba Donor has a Bachelor of Arts
A command-line argument -aba might parse as -a -b -a or -a -ba or -ab -a. In all such cases, Getopt::Declare prefers the longest unmatched flag first. So the previous example would parse as -ab -a, unless the -ab flag had already appeared in the command-line (in which case it'd parse as -a -ba).
These rules are designed to produce consistency and "least surprise", but (as the example above shows π) they may not always manage it. If unconstrained flag clustering is too libertarian for your particular application, you can restrict it (or remove it entirely) by including a [cluster:...] directive anywhere in the specification string.
The options are:
"[cluster: any]"β this version of the directive allows any flag to be clustered (it just makes the default behaviour explicit, basically)."[cluster: flags]"β this version restricts clustering to parameters which are "pure" flags (aka those with no parameter variables or punctuators)."[cluster: singles]"β this version restricts clustering to parameters which are "pure" flags and which consist of a flag prefix followed by a single alphanumeric character."[cluster: none]"β this version turns clustering off completely. bye. π
For example:
$args = Getopt::Declare->new(<<'EOSPEC');
-a Append mode
-b Back-up mode
-bu [ditto]
-c <file> Copy mode
-d [<file>] Delete mode
-e[xec] Execute mode
[cluster:singles]
EOSPEC
In that example up there, only the -a and -b parameters can be clustered. The -bu parameter is excluded because it's more than one letter, while -c and -d are excluded because they take (or may take, in -d's case) a variable. The -e[xec] parameter is excluded because it may take a trailing punctuator ([xec]).
By comparison, if the directive had been [cluster: flags], then -bu could be clustered, though -c, -d and -e[xec] would still be excluded since they're not "pure flags".
π Strict and non-strict command-line parsing π
"Strictness" in Getopt::Declare is all about how unrecognized command-line arguments get handled. By default, Getopt::Declare is "non-strict" β meaning it just silently skips over any unrecognized command-line argument, leaving it in @ARGV at the conclusion of command-line processing (but only if they were originally parsed from @ARGV).
No matter where they came from, those leftover args? They're still yours, bestie. You can grab them by calling the unused method on the Getopt::Declare object after it has parsed. In a list context? It gives you a whole list of the unprocessed arguments, slay. In a scalar context? You get one single string with all the unused arguments concatenated together. Periodt. π
Likewise, there's a used method that returns the arguments that were successfully processed by the parser. Iconic. β¨
But wait β if you create a new Getopt::Declare object with a specification string that contains the [strict] directive (and it can be at any point in the spec), then things get serious:
$args = Getopt::Declare->new(<<'EOSPEC');
[strict]
-a Append mode
-b Back-up mode
-c Copy mode
EOSPEC
Then the command-line is parsed "strictly". In this case, any unrecognized argument causes an error message (see "DIAGNOSTICS") to be written to STDERR, and command-line processing to (eventually) fail. On such a failure, the call to Getopt::Declare::new() returns undef instead of the usual hash reference. No cap. π
The only concession that strict mode makes to the unknown is that, if command-line processing is prematurely terminated via the finish operator, any command-line arguments which have not yet been examined are left in @ARGV and do not cause the parse to fail (of course, if any unknown arguments were encountered before the finish was executed, those earlier arguments will cause command-line processing to fail).
The strict option is useful when all possible parameters can be specified in a single Getopt::Declare object, whereas the non-strict approach is needed when unrecognized arguments are either to be quietly tolerated, or processed at a later point (possibly in a second Getopt::Declare object).
β¨ Parameter dependencies β¨
Getopt::Declare provides five other directives which modify the behaviour of the command-line parser in some way. One or more of these directives may be included in any parameter description. In addition, the [mutex:...] directive may also appear in any usage "decoration" (see "Usage information").
Each directive specifies a particular set of conditions that a command-line must fulfil (for example, that certain parameters may not appear on the same command-line). If any such condition is violated, an appropriate error message is printed (see "DIAGNOSTICS"). Furthermore, once the command-line is completely parsed, if any condition was violated, the program terminates (whilst still inside Getopt::Declare::new()).
The directives are:
[required]β Specifies that an argument matching at least one variant of the corresponding parameter must be specified somewhere in the command-line. That is, if two or more required parameters share the same flag, it suffices that any one of them matches an argument (recall that Getopt::Declare considers all parameter specifications with the same flag merely to be variant forms of a single "underlying" parameter).
If an argument matching a required flag is not found in the command-line, an error message to that effect is issued, command-line processing fails, and Getopt::Declare::new() returns undef.
[repeatable]β By default, Getopt::Declare objects allow each of their parameters to be matched only once (that is, once any variant of a particular parameter matches an argument, all variants of that same parameter are subsequently excluded from further consideration when parsing the rest of the command-line).
However, it is sometimes useful to allow a particular parameter to match more than once. Any parameter whose description includes the directive [repeatable] is never excluded as a potential argument match, no matter how many times it has matched previously:
-nice Increase nice value (linearly if repeated)
[repeatable]
{ set_nice( get_nice()+1 ); }
-w Toggle warnings [repeatable] for the rest
of the command-line
{ $warn = !$warn; }
And here's a more general mechanism: if a [repeatable] directive appears in a specification anywhere other than a flag's description, then all parameters are marked repeatable:
[repeatable]
-nice Increase nice value (linearly if repeated)
{ set_nice( get_nice()+1 ); }
-w Toggle warnings for the rest of the command-line
{ $warn = !$warn; }
[mutex: <flag list>]β The[mutex:...]directive specifies that the parameters whose flags it lists are mutually exclusive. That is, no two or more of them may appear in the same command-line. For example:
-case set to all lower case
-CASE SET TO ALL UPPER CASE
-Case Set to sentence case
-CaSe SeT tO "RAnSom nOTe" CasE
[mutex: -case -CASE -Case -CaSe]
The interaction of the [mutex:...] and [required] directives is potentially awkward in the case where two required arguments are also mutually exclusive (since the [required] directives insist that both parameters must appear in the command-line, whilst the [mutex:...] directive expressly forbids this).
Getopt::Declare resolves such contradictory constraints by relaxing the meaning of required slightly. If a flag is marked required, it is considered found for the purposes of error checking if it or any other flag with which it is mutually exclusive appears on the command-line.
Hence the specifications:
-case set to all lower case [required]
-CASE SET TO ALL UPPER CASE [required]
-Case Set to sentence case [required]
-CaSe SeT tO "RAnSom nOTe" CasE [required]
[mutex: -case -CASE -Case -CaSe]
mean that exactly one of these four flags must appear on the command-line, but that the presence of any one of them will suffice to satisfy the requiredness of all four.
It should also be noted that mutual exclusion is only tested for after a parameter has been completely matched (that is, after the execution of its actions, if any). This prevents rejected parameters (see "Termination and rejection") from incorrectly generating mutual exclusion errors. However, it also sometimes makes it necessary to defer the actions of a pair of mutually exclusive parameters (for example, if those actions are expensive or irreversible).
[excludes: <flag list>]β The[excludes:...]directive provides apairwiseversion of mutual exclusion, specifying that the current parameter is mutually exclusive with all the other parameters lists, but those other parameters are not mutually exclusive with each other. That is, whereas the specification:
-left Justify to left margin
-right Justify to right margin
-centre Centre each line
[mutex: -left -right -centre]
means that only one of these three justification alternatives can ever be used at once, the specification:
-left Justify to left margin
-right Justify to right margin
-centre Centre each line [excludes: -left -right]
means that -left and -right can still be used together (probably to indicate left and right justification), but that neither can be used with -centre. Note that the [excludes:...] directive also differs from the [mutex:...] in that it is always connected with a particular parameter, implicitly using the flag of that parameter as the target of exclusion.
[requires: <condition>]β The[requires]directive specifies a set of flags which must also appear in order for a particular flag to be permitted in the command-line. The condition is a boolean expression, in which the terms are the flags or various parameters, and the operations are&&,||,!, and bracketting. For example, the specifications:
-num Use numeric sort order
-lex Use "dictionary" sort order
-len Sort on length of line (or field)
-field <N:+i> Sort on value of field <N>
-rev Reverse sort order
[requires: -num || -lex || !(-len && -field)]
means that the -rev flag is allowed only if either the -num or the -lex parameter has been used, or if it is not true that both the -len and the -field parameters have been used.
Note that the operators &&, ||, and ! retain their normal Perl precedences.
π¦ Parsing from other sources π¦
Getopt::Declare normally parses the contents of @ARGV, but can be made to parse specified files instead. To accommodate this, Getopt::Declare::new() takes an optional second parameter, which specifies a file to be parsed. The parameter may be either:
- A
IO::Handlereference or a filehandle GLOB reference β in which caseGetopt::Declare::new()reads the corresponding handle until end-of-file, and parses the resulting text (even if it is an empty string). - An ARRAY reference containing the single string
'-CONFIG'β in which caseGetopt::Declare::new()looks for the files$ENV{HOME}/.${progname}rcand$ENV{PWD}/.${progname}rc, concatenates their contents, and parses that.
If neither file is found (or if both are inaccessible) Getopt::Declare::new() immediately returns zero. If a file is found but the parse subsequently fails, undef is returned.
- An ARRAY reference containing the single string
'-BUILD'β in which caseGetopt::Declare::new()builds a parser from the supplied grammar and returns a reference to it, but does not parse anything. See "The Getopt::Declare::code() method" and "The Getopt::Declare::parse() method". - An ARRAY reference containing the single string
'-SKIP'or the single valueundefor nothing β in which caseGetopt::Declare::new()immediately returns zero. This alternative is useful when using aFileHandle:
my $args = Getopt::Declare->new($grammar, new FileHandle ($filename) || -SKIP);
β¦because it makes it so explicit what goes down if FileHandle::new() fails. And honestly? If you just omit the -SKIP alternative, Getopt::Declare::new still bails immediately anyway, having spotted undef as its second argument. The universe provides. π
Any other ARRAY reference
Okay so if you hand it literally any other array ref, Getopt::Declare::new() treats the array's elements as a list of filenames, glues their contents together, and parses that. Bestie, it's concatenating your files.
But watch out π β if the list doesn't point at any accessible file(s), Getopt::Declare::new() immediately returns zero. And if matching files are found but don't parse successfully? You get undef back. No cap.
A string
If it's just a string, Getopt::Declare::new() parses that string directly. Simple as that. β¨
Heads up, queen: whenGetopt::Declare::new()parses from a source that isn't@ARGV, any unrecognized arguments are not put back into@ARGV. They justβ¦ vanish into the void. π«
π Using Getopt::Declare objects after command-line processing π
Once command-line processing is done, the object that Getopt::Declare::new() gave you has these features. The afterparty, if you will. πͺ©
Parameter data
For every successfully matched parameter, the Getopt::Declare object holds a hash element. The key is the leading flag or parameter variable name of that parameter.
The value of that element is a reference to another hash, which holds the names and values of each distinct parameter variable and/or punctuator that got matched:
- Punctuators β generate string values containing the actual text matched.
- Scalar parameter variables β generate scalar values.
- List parameter variables β generate array references.
Special case alert π¨: if a parameter is just a single component (a single flag or a single parameter variable), then the value for that hash key is not a hash reference β it's the actual value matched. No nesting, no drama.
Here's an example showing all the flavors:
$args = Getopt::Declare->new( q{
-v <value> [etc] One or more values
<infile> Input file [required]
-o <outfiles>... Output files
} );
if ( $args->{'-v'} )
{
print "Using value: ", $args->{'-v'}{'<value>'};
print " (et cetera)" if $args->{'-v'}{'etc'};
print "\n";
}
open INFILE, $args->{'<infile>'} or die;
@data = <INFILE>;
foreach $outfile ( @{$args->{'-o'}{'<outfiles>'}} )
{
open OUTFILE, ">$outfile" or die;
print OUTFILE process(@data);
close OUTFILE;
}
The values assigned to those hash elements are copied from the corresponding block-scoped variables available inside actions. Which means: if you change one of those block-scoped variables inside an action, the changed value is what gets saved to the hash. Periodt.
Like, check this spec out:
$args = Getopt::Declare->new( q{
-ar <R:n> Set aspect ratio (will be clipped to [0..1])
{
$R = 0 if $R < 0;
$R = 1 if $R > 1;
}
} );
β¦then $args->{'-ar'}{'<R>'} will always be between zero and one. Iconic clamping behaviour, honestly. π₯
The @ARGV array
In its "non-strict" mode, once a Getopt::Declare object finishes its command-line processing, it pushes any unrecognized arguments back into the (now emptied) command-line array @ARGV. Meanwhile, every recognized argument has been removed. Bye bestie π
Note that these remaining arguments land in sequential elements (starting at$ARGV[0]) β not in their original positions in@ARGV. The seats got rearranged, sorry. π
The Getopt::Declare::usage() method
Once a Getopt::Declare object exists, you can call its usage() method to explicitly print usage info matching the spec it was built with. More deets over in "Usage information".
If you call usage() with an argument, that argument gets passed to exit after the usage info prints. The no-argument version of usage() justβ¦ returns at that point. No exit, no drama. π§
The Getopt::Declare::version() method
Another banger method is version(), which prints out:
- the name of the enclosing program,
- the last time it was modified,
- and the value of
$::VERSION, if it's defined.
Heads up: this means all Getopt::Declare objects in a single program will print out identical version info. They're all sharing the same vibe. π
Just like usage(), if version is passed an argument, it exits with that value after printing. Slay.
The Getopt::Declare::parse() method
You can totally separate building a Getopt::Declare parser from the actual parsing it does. If Getopt::Declare::new() is called with a second parameter -BUILD (peep "Parsing from other sources"), it constructs and returns a parser without parsing anything. That parser object can then parse multiple sources by calling its parse() method. Reusable, bestie. β»οΈ
Getopt::Declare::parse() takes an optional parameter specifying the source of the text to parse β and if you omit it, it parses @ARGV. This parameter takes the same set of values as the optional second parameter of Getopt::Declare::new() (again, "Parsing from other sources").
Return values, listen up:
- Returns true if the source is located and parsed successfully. β¨
- Returns a defined false (zero) if the source is not located.
- Returns
undefif the source is located but not successfully parsed.
So this code first builds a parser for a bunch of alternate config files plus the command line, then parses them:
# BUILD PARSERS
my $config = Getopt::Declare->new($config_grammar, -BUILD);
my $cmdline = Getopt::Declare->new($cmdline_grammar, -BUILD);
# TRY STANDARD CONFIG FILES
$config->parse(-CONFIG)
# OTHERWISE, TRY GLOBAL CONFIG
or $config->parse('/usr/local/config/.demo_rc')
# OTHERWISE, TRY OPENING A FILEHANDLE (OR JUST GIVE UP)
or $config->parse(new FileHandle (".config") || -SKIP);
# NOW PARSE THE COMMAND LINE
$cmdline->parse() or die;
The Getopt::Declare::code() method
You can also retrieve the command-line parsing code that Getopt::Declare::new() generated internally. The Getopt::Declare::code() method returns a string containing the complete command-line processing code β as a single do block plus a leading package declaration. Look at the source, bestie, it's right there. π
Getopt::Declare::code() takes as its sole argument a string containing the complete name of the package (for that leading package declaration in the generated code). If that string is empty or undefined, the package name defaults to main.
Since the default behaviour of Getopt::Declare::new() is to execute the command-line parsing code it generates, if your goal is only to generate parser code, you should specify the optional second -BUILD parameter (yep, "Parsing from other sources") when calling <Getopt::Declare::new()>.
For example, this program "inlines" a Getopt::Declare specification by extracting it from between the first =for Getopt::Declare and the next =cut appearing on STDIN:
use Getopt::Declare;
sub encode { return Getopt::Declare->new(shift,-BUILD)->code() || die }
undef $/;
if (<>)
{
s {^=for\s+Getopt::Declare\s*\n(.*?)\n=cut}
{'my (\$self,$source) = ({});'.encode($1).' or die "\n";'}
esm;
}
print;
Note that the generated inlined version expects to find a lexical variable named$source, which tells it what to parse. That variable is normally set by the optional parameters ofGetopt::Declare::new()orGetopt::Declare::parse().
And one more thing π
: the inlined code leaves all extracted parameters in the lexical variable $self, and it does not autogenerate help or version flags β since there's no actual Getopt::Declare object in the inlined code to generate them through. No object, no flags. It's giving minimalism. π¦
π AUTOGENERATED FEATURES π
okay so here's the tea, bestie β Getopt::Declare just gives you a bunch of stuff for free, no extra work, no cap. π
β¨ Usage information β¨
The spec you hand over to Getopt::Declare::new gets used (like, almost word-for-word) as the usage display whenever somebody asks for usage info. Iconic behavior honestly. π
And how do they ask? Two ways, bestie:
- by passing an argument that matches the help parameter (peep Help parameters below), or
- by straight-up calling the
Getopt::Declare::usage()method yourself β from inside an action, or after command-line processing is done.
Watch this:
$args = Getopt::Declare->new( q{
-usage Show usage information and exit
{ $self->usage(0); }
+usage Show usage information at end of program
} );
# PROGRAM HERE
$args->usage() if $args->{'+usage'};
now before it shows your spec to the world, it does a lil glow-up pass on it. These changes get made to the original spec before display:
- all actions and comments get deleted ποΈ
- any
[ditto]directive gets converted into an appropriate set ofdittomarks - any text sitting in matching square brackets (including any directive inside) gets deleted
- any parameter variable type specifier (things like
:i,:n,:/pat/, etc.) gets deleted
Other than that? Every bit of formatting from your original spec stays exactly where it was. π
AND, on top of all that β if the input source is @ARGV, Getopt::Declare also shows you three sample command-lines:
- one showing normal usage (required parameter variables included, obviously),
- one showing how to invoke help (see Help parameters), and
- one showing how to find out the current version of the program (see Version parameters).
The usage info gets printed to STDOUT, and β because Getopt::Declare lowkey encourages you to write longer and better-documented parameter lists β if the IO::Pager package is available, an IO::Pager object pages out the entire usage documentation. Fancy. π
π Usage "decoration" π
Sometimes you wanna add little β¨decorativeβ¨ bits to your program's usage info β subheadings, general notes, separators, the whole aesthetic. Getopt::Declare is obsessed with this: it just ignores those items when it's interpreting a specification string, but prints them when someone asks for usage info. Best of both worlds, fr fr.
So here's the rule: any line that can't be read as a parameter definition, a parameter description, or a parameter action gets treated as a "decorator" line, and it's printed verbatim (after any square-bracketted substrings have been yanked out of it). π«Ά
β οΈ if your decoration needs actual square brackets, you gotta escape the opening one with a backslash, like \[decoration]. Otherwise it's getting deleted, bestie, sorry.
The key to decorating successfully is making sure decorator lines are separated from whatever parameter specification comes before them β either by an action or by an empty line. Also, just like a parameter description, a decorator line cannot contain a tab character after the first non-whitespace character, because then it'd get treated as a parameter specification. π
Check out this spec β it shows off all the different decoration forms. And note: there are only four actual parameters in it (-in, -r, -p, and -out). Also peep that leading tabs are perfectly acceptible in decorator lines:
$args = Getopt::Declare->new(<<'EOPARAM');
============================================================
Required parameter:
-in <infile> Input file [required]
------------------------------------------------------------
Optional parameters:
(The first two are mutually exclusive) [mutex: -r -p]
-r[and[om]] Output in random order
-p[erm[ute]] Output all permutations
---------------------------------------------------
-out <outfile> Optional output file
------------------------------------------------------------
Note: this program is known to run very slowly of files with
long individual lines.
============================================================
EOPARAM
πΈ Help parameters πΈ
By default, Getopt::Declare is a girlboss and automatically defines ALL of these for you:
-help Show usage information [undocumented]
{ $self->usage(0); }
-Help [ditto]
-HELP [ditto]
--help [ditto]
--Help [ditto]
--HELP [ditto]
-h [ditto]
-H [ditto]
So basically, most of the ways a user might try to get help will just work automatically. slay. β¨
BUT β and this is the plot twist β if you explicitly specify a parameter using any of those flags in the string you pass to Getopt::Declare::new(), then that flag (and only that one) gets removed from the list of possible help flags. For example:
-w <pixels:+i> Specify width in pixels
-h <pixels:+i> Specify height in pixels
that would make the -h help parameter go bye-bye π (though help is still reachable through the other seven alternatives, so you're fine).
π Version parameters π
Getopt::Declare also auto-creates a lil set of parameters for pulling program version info:
-version Show version information [undocumented]
{ $self->version(0); }
-Version [ditto]
-VERSION [ditto]
--version [ditto]
--Version [ditto]
--VERSION [ditto]
-v [ditto]
-V [ditto]
And same energy as the help commands: if you explicitly specify a parameter with any of those flags, that flag gets removed from the version flags list. periodt. π
π¨ DIAGNOSTICS π¨
Getopt::Declare might hit you with these while it's parsing a command-line. All of them are fatal β and the first five? Instantly fatal. like, no takebacks. π
"Error: bad Getopt::Declare parameter variable specification near %s"β A matching pair of angle brackets showed up as part of a parameter definition, but they didn't form a valid parameter variable specification. i.e. it wasn't in the form<name>or<name:type>."Error: bad type in Getopt::Declare parameter variable specification near %s"β An unknown type specifier got used in a parameter variable type suffix."Error: bad action in Getopt::Declare specification:\n %s"β A Perl syntax error was detected in the indicated action."Error: unattached action in Getopt::Declare specification:\n %s"β An action was found with no preceding parameter specification. This usually happens because the trailing tab got left off the preceding parameter specification. (tragic, honestly.)"Error: incomplete action in Getopt::Declare specification:\n %s"β An action was found, but it was missing one or more closing}'s."Error: bad condition in directive [requires: %s]\n"β The condition in the indicated[requires:...]directive wasn't a well-formed boolean expression. Common culprits: forgetting a&&/||operator between two flags, mismatched brackets, or usingand/orinstead of&&/||."Error: in generated command-line parser code:\n %s"β Either there was a Perl syntax error in one of the actions (that the previous diagnostic didn't catch), or β much less likely β there's a bug in the code generator inside Getopt::Declare. π"Error: incorrect specification of %s parameter"β The flag for that parameter was found, but the argument didn't match any of that parameter's variant syntaxes."Error: parameter %s not allowed with %s"β Two mutually exclusive flags were specified together. pick a lane bestie."Error: required parameter %s not found"β No argument matching the specifiedrequiredparameter was found during command-line processing."Error: parameter %s can only be specified with %s"β That parameter has a[requires:...]directive, and it was not satisfied."Error: unknown command-line argument (%s)"β A command-line argument showed up that didn't match any specified parameter. This one can only appear if thestrictoption is in effect."Error: in parameter %s (%s must be an integer greater than zero)"β A parameter variable in that parameter was declared with the type:+i(or something derived from it), but the corresponding argument wasn't a positive, non-zero integer."Error: in parameter %s (%s must be a number greater than zero)"β A parameter variable in that parameter was declared with the type:+n(or something derived from it), but the corresponding argument wasn't a positive, non-zero number."Error: in parameter %s (%s must be an positive integer)"β A parameter variable in that parameter was declared with the type:0+i(or something derived from it), but the corresponding argument wasn't a positive integer."Error: in parameter %s (%s must be a positive number)"β A parameter variable in that parameter was declared with the type:0+n(or something derived from it), but the corresponding argument wasn't a positive number.
π AUTHOR π
Damian Conway <damian@conway.org> β the main character himself. π
π BUGS AND ANNOYANCES π
There are undoubtedly serious bugs lurking somewhere in this code. there always are, bestie.
If nothing else β it shouldn't take 1500 lines to explain a package that was designed for intuitive ease of use! π (iconic behavior, honestly.)
Bug reports and other feedback are most welcome at: https://rt.cpan.org/Public/Bug/Report.html?Queue=Getopt-Declare π«Ά
π COPYRIGHT π
Copyright (c) 1997-2000, Damian Conway. All Rights Reserved.
This module is free software. It may be used, redistributed
and/or modified under the terms of the Perl Artistic License
(see http://www.perl.com/perl/misc/Artistic.html)
and that's a wrap on the whole page, bestie!! πβ¨ this one's from perl v5.36.0, dated 2022-11-20, and it's the Getopt::Declare(3pm) page β go forth and parse some arguments, you absolute legend ππ¦πΈ
π¦ where this page comes from
- debian bookworm: libgetopt-declare-perl 1.14-4 Β· Artistic-1.0-Perl
- debian trixie: libgetopt-declare-perl 1.14-4 Β· Artistic-1.0-Perl
- ubuntu noble: libgetopt-declare-perl 1.14-4 Β· Artistic-1.0-Perl
- ubuntu resolute: libgetopt-declare-perl 1.14-4 Β· Artistic-1.0-Perl
- ubuntu stonking: libgetopt-declare-perl 1.14-4 Β· Artistic-1.0-Perl
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms