App::Yath::Option - Representation of a yath option.
This class represents a single command line option for yath.
You usually will not be creating option instances directly. Usually you will use
App::Yath::Options which provides sugar, and helps make sure options get to
the right place.
use App::Yath::Options;
# You can specify a single option:
option color => (
prefix => 'display',
category => "Display Options",
description => "Turn color on, default is true if STDOUT is a TTY.",
default => sub { -t STDOUT ? 1 : 0 },
);
# If you are specifying multiple options you can use an option_group to
# define common parameters.
option_group {prefix => 'display', category => "Display Options"} => sub {
option color => (
description => "Turn color on, default is true if STDOUT is a TTY.",
default => sub { -t STDOUT ? 1 : 0 },
);
option verbose => (
short => 'v',
type => 'c',
description => "Be more verbose",
default => 0,
);
};
These can be provided at object construction, or are generated internally.
- applicable => sub { ... }
- This is callback is used by the "applicable()"
method.
option foo => (
...,
applicable => sub {
my ($opt, $options) = @_;
...
return $bool;
},
);
REQUIRED
- $class->new(prefix => 'my_prefix')
- $scalar = $opt->prefix()
- A prefix is required. All options have their values
inserted into the settings structure, an instance of
Test2::Harness::Settings. The structure is
"$settings->PREFIX->OPTION".
If you do not specify a "name" attribute then the default name
will be "PREFIX-TITLE". The name is the main command line
argument, so "--PREFIX-TITLE" is the default name.
- $class->new(type => $type)
- $type = $opt->type()
- All options must have a type, if non is specified the
default is 'b' aka boolean.
Here are all the possible types, along with their aliases. You may use the
type character, or any of the aliases to specify that type.
- b bool boolean
- True of false values, will be normalized to 0 or 1 in most
cases.
- c count counter counting
- Counter, starts at 0 and then increments every time the
option is used.
- s scalar string number
- Requires an argument which is treated as a scalar value. No
type checking is done by the option itself, though you can check it using
"action" or "normalize" callbacks which are documented
under those attributes.
- m multi multiple list array
- Requires an argument which is treated as a scalar value.
Can be used multiple times. All arguments provided are appended to an
array.
- d def default
- Argument is optional, scalar when provided.
"--opt=arg" to provide an argument, "--opt arg" will
not work, "arg" will be seen as its own item on the command
line. Can be specified without an arg "--opt" to signify a
default argument should be used (set via the "action" callback,
not the "default" attribute which is a default value regardless
of if the option is used.)
Real world example from the debug options (simplified for doc purposes):
option summary => (
type => 'd',
description => "Write out a summary json file, if no path is provided 'summary.json' will be used. The .json extension is added automatically if omitted.",
long_examples => ['', '=/path/to/summary.json'],
# New way to specify an auto-fill value for when no =VAL is provided.
# If you do not specify this the default autofill is '1' for legacy support.
autofill => 'VALUE',
# Old way to autofill a value (default is 1 for auto-fill)
# Using autofill is significantly better.
# You can also use action for additional behavior along with autofill,
# but the default will be your auto-fill value, not '1'.
action => sub {
my ($prefix, $field, $raw, $norm, $slot, $settings) = @_;
# $norm will be '1' if option was used without an argument, so we
# just use the provided value when it is not 1'.
return $$slot = $norm unless $norm eq '1';
# $norm was 1, so this is our no-arg "default" behavior
# Do nothing if a value is already set
return if $$slot;
# Set the default value of 'summary.json'
return $$slot = 'summary.json';
},
);
};
- D multi-def multiple-default list-default
array-default
- This is a combination of "d" and "m".
You can use the opt multiple times to list multiple values, and you can
call it without args to add a set of "default" values (not to be
confused with THE default attribute, which is used even if the option
never appears on the command line.)
Real world example (simplified for doc purposes):
option dev_libs => (
type => 'D',
short => 'D',
name => 'dev-lib',
category => 'Developer',
description => 'Add paths to @INC before loading ANYTHING. This is what you use if you are developing yath or yath plugins to make sure the yath script finds the local code instead of the installed versions of the same code. You can provide an argument (-Dfoo) to provide a custom path, or you can just use -D without and arg to add lib, blib/lib and blib/arch.',
long_examples => ['', '=lib'],
short_examples => ['', '=lib', 'lib'],
# New way to specify the auto-fill values. This may be a single scalar,
# or an arrayref.
autofill => [ 'lib', 'blib/lib', 'blib/arch' ],
# Old way to specify the auto-fill values.
action => sub {
my ($prefix, $field, $raw, $norm, $slot, $settings) = @_;
# If no argument was provided use the 'lib', 'blib/lib', and 'blib/arch' defaults.
# If an argument was provided, use it.
push @{$$slot} => ($norm eq '1') ? ('lib', 'blib/lib', 'blib/arch') : ($norm);
},
);
- h hash
- The hash type. Each time the option is used it is to add a
single key/value pair to the hash. Use an "=" sign to split the
key and value. The option can be used multiple times. A value is required.
yath --opt foo=bar --opt baz=bat
- H hash-list
- Similar to the 'h' type except the key/value pair expects a
comma separated list for the value, and it will be placed under the key as
an arrayef.
yath --opt foo=a,b,c --opt bar=1,2,3
The yath command obove would produce this structure:
{
foo => ['a', 'b', 'c'],
bar => ['1', '2', '3'],
}
- $class->new(title => 'my_title')
- $title = $opt->title()
- You MUST specify either a title, or BOTH a name and
field. If you only specify a title it will be used to generate the name
and field.
If your title is 'foo-bar_baz' then your field will be 'foo_bar_baz' and
your name will be '$PREFIX-foo-bar-baz'.
Basically title is used to generate a sane field and/or name if niether are
specified. For field all dashes are changed to underscores. The field is
used as a key in the settings: "$settings->prefix->field".
For the name all underscores are changed to dashes, if the option is
provided by a plugin then 'prefix-' is prepended as well. The name is used
for the command line argument '--name'.
If you do not want/like the name and field generated from a title then you
can specify a name or title directly.
- $class->new(name => 'my-name')
- $name = $opt->name()
- You MUST specify either a title, or BOTH a name and
field. If you only specify a title it will be used to generate the name
and field.
This name is used as your primary command line argument. If your name is
"foo" then your command line argument is "--foo".
- $class->new(field => 'my_field')
- $field = $opt->field()
- You MUST specify either a title, or BOTH a name and
field. If you only specify a title it will be used to generate the name
and field.
The field is used in the settings hash. If your field is "foo"
then your settings path is "$setting->prefix->foo".
OPTIONAL
- $class->new(action => sub ...)
- $coderef = $opt->action()
-
option foo => (
...,
action => sub {
my ($prefix, $field_name, $raw_value, $normalized_value, $slot_ref, $settings, $handler, $options) = @_;
# If no action is specified the following is all that is normally
# done. Having an action means this is not done, so if you want the
# value stored you must call this or similar.
$handler->($slot, $normalized_value);
},
);
- $prefix
- The prefix for the option, specified when the option was
defined.
- $field_name
- The field for the option, specified whent the option was
defined.
- $raw_value
- The value/argument provided at the command line "--foo
bar" would give us "bar". This is BEFORE any
processing/normalizing is done.
For options that do not take arguments, or where argumentes are optional and
none are provided, this will be '1'.
- $normalized_value
- If a normalize callback was provided this will be the
result of putting the $raw_value through the normalize callback.
- $slot_ref
- This is a scalar reference to the settings slot that holds
the option value(s).
The default behavior when no action is specified is usually one of these:
$$slot_ref = $normalized_value;
push @{$$slot_ref} => $normalized_value;
However, to save yourself trouble you can use the $handler instead (see
below).
- $settings
- The Test2::Harness::Settings instance.
- $handler
- A callback that "does the right thing" as far as
setting the value in the settings hash. This is what is used when you do
not set an action callback.
$handler->($slot, $normalized_value);
- $options
- The App::Yath::Options instance this options belongs to.
This is mainly useful if you have an option that may add even more options
(such as the "--plugin" option can do). Note that if you do this
you should also set the "adds_options" attribute to true, if you
do not then the options list will not be refreshed and your new options
may not show up.
- $class->new(adds_options => $bool)
- $bool = $opt->adds_options()
- If this is true then it means using this option could
result in more options being available (example: Loading a plugin).
- $class->new(alt => ['alt1', 'alt2', ...])
- $arrayref = $opt->alt()
- Provide alternative names for the option. These are aliases
that can be used to achieve the same thing on the command line. This is
mainly useful for backcompat if an option is renamed.
- $class->new(builds => 'My::Class')
- $my_class = $opt->builds()
- If this option is used in the construction of another
object (such as the group it belongs to is composed of options that
translate 1-to-1 to fields in another object to build) then this can be
used to specify that. The ultimate effect is that an exception will be
thrown if that class does not have the correct attribute. This is a safety
net to catch errors early if field names change, or are missing between
this representation and the object being composed.
- $class->new(category => 'My Category')
- $category = $opt->category()
- This is used to sort/display help and POD documentation for
your option. If you do not provide a category it is set to 'NO CATEGORY -
FIX ME'. The default value makes sure everyone knows that you do not know
what you are doing :-).
- $class->new(clear_env_vars => $bool)
- $bool = $opt->clear_env_vars()
- This option is only useful when paired with the
"env_vars" attribute.
Example:
option foo => (
...
env_vars => ['foo', 'bar', 'baz'],
clear_env_vars => 1,
):
In this case you are saying option foo can be set to the value of $ENV{foo},
$ENV{bar}, or $ENV{baz} vars if any are defined. The
"clear_env_vars" tell it to then delete the environment
variables after they are used to set the option. This is useful if you
want to use the env var to set an option, but do not want any tests to be
able to see the env var after it is used to set the option.
- $class->new(default => $scalar)
- $class->new(default => sub { return $default })
- $scalar_or_coderef = $opt->default()
- This sets a default value for the field in the settings
hash, the default is set before any command line processing is done, so if
the option is never used in the command line the default value will be
there.
Be sure to use the correct default value for your type. A scalar for 's', an
arrayref for 'm', etc.
Note, for any non-scalar type you want to use a subref to define the value:
option foo => (
...
type => 'm',
default => sub { [qw/a b c/] },
);
- $class->new(description => "Fe Fi Fo
Fum")
- $multiline_string = $opt->description()
- Description of your option. This is used in help output and
POD. If you do not provide a value the default is 'NO DESCRIPTION - FIX
ME'.
- $class->new(env_vars => \@LIST)
- $arrayref = $opt->env_vars()
- If set, this should be an arrayref of environment variable
names. If any of the environment variables are defined then the settings
will be updated as though the option was provided onthe command line with
that value.
Example:
option foo => (
prefix => 'blah',
type => 's',
env_vars => ['FOO', 'BAR'],
);
Then command line:
FOO="xxx" yath test
Should be the same as
yath test --foo "xxx"
You can also ask to have the environment variables cleared after they are
checked:
option foo => (
prefix => 'blah',
type => 's',
env_vars => ['FOO', 'BAR'],
clear_env_vars => 1, # This tells yath to clear the env vars after they
are used.
);
If you would like the option set to the opposite of the envarinment variable
you can prefix it with a '!' character:
option foo =>(
...
env_vars => ['!FOO'],
);
In this case these are equivelent:
FOO=0 yath test
yath test --foo=1
Note that this only works when the variable is defined. If $ENV{FOO} is not
defined then the variable is not used.
- $class->new(from_command =>
'App::Yath::Command::COMMAND')
- $cmd_class = $opt->from_command()
- If your option was defined for a specific command this will
be set. You do not normally set this yourself, the tools in
App::Yath::Options usually handle that for you.
- $class->new(from_plugin =>
'App::Yath::Plugin::PLUGIN')
- $plugin_class = $opt->from_plugin()
- If your option was defined for a specific plugin this will
be set. You do not normally set this yourself, the tools in
App::Yath::Options usually handle that for you.
- $class->new(long_examples => [' foo', '=bar',
...])
- $arrayref = $opt->long_examples()
- Used for documentation purposes. If your option takes
arguments then you can give examples here. The examples should not include
the option itself, so "--foo bar" would be wrong, you should
just do " bar".
- $class->new(negate => sub { ... })
- $coderef = $opt->negate()
- If you want a custom handler for negation
"--no-OPT" you can provide one here.
option foo => (
...
negate => sub {
my ($prefix, $field, $slot, $settings, $options) = @_;
...
},
);
The variables are the same as those in the "action" callback.
- $class->new(normalize => sub { ... })
- $coderef = $opt->normalize()
- The normalize attribute holds a callback sub that takes the
raw value as input and returns the normalized form.
option foo => (
...,
normalize => sub {
my $raw = shift;
...
return $norm;
},
);
- $class->new(pre_command => $bool)
- $bool = $opt->pre_command()
- Options are either command-specific, or pre-command.
Pre-command options are ones yath processes even if it has not determined
what comamnd is being used. Good examples are "--dev-lib" and
"--plugin".
yath --pre-command-opt COMMAND --command-opt
Most of the time this should be false, very few options qualify as
pre-command.
- $class->new(pre_process => sub { ... })
- $coderef = $opt->pre_process()
- This is essentially a BEGIN block for options. This
callback is called as soon as the option is parsed from the command line,
well before the value is normalized and added to settings. A good use for
this is if your option needs to inject additional App::Yath::Option
instances into the App::Yath::Options instance.
option foo => (
...
pre_process => sub {
my %params = @_;
my $opt = $params{opt};
my $options = $params{options};
my $action = $params{action};
my $type = $params{type};
my $val = $params{val};
...;
},
);
Explanation of paremeters:
- $params{opt}
- The op instance
- $params{options}
- The App::Yath::Options instance.
- $params{action}
- A string, usually either "handle" or
"handle_negation"
- $params{type}
- A string, usually "pre-command" or "command
($CLASS)" where the second has the command package in the
parentheses.
- $params{val}
- The value being set, if any. For options that do not take
arguments, or in the case of negation this key may not exist.
- $class->new(short => $single_character_string)
- $single_character_string = $opt->short()
- If you want your option to be usable as a short option
(single character, single dash "-X") then you can provide the
character to use here. If the option does not require an argument then it
can be used along with other no-argument short options: "-xyz"
would be equivilent to "-x -y -z".
There are only so many single-characters available, so options are
restricted to picking only 1.
Please note: Yath reserves the right to add any single-character
short options in the main distribution, if they conflict with third party
plugins/commands then the third party must adapt and change its options.
As such it is not recommended to use any short options in third party
addons.
- $class->new(short_examples => [' foo', ...])
- $arrayref = $opt->short_examples()
- Used for documentation purposes. If your option takes
arguments then you can give examples here. The examples should not include
the option itself, so "-f bar" would be wrong, you should just
do " bar".
This attribute is not used if you do not provide a "short"
attribute.
- $class->new(trace => [$package, $file, $line])
- $arrayref = $opt->trace()
- This is almost always auto-populated for you via
"caller()". It should be an arrayref with a package, filename
and line number. This is used if there is a conflict between parameter
names and/or short options. If such a situation arises the file/line
number of all conflicting options will be reported so it can be
fixed.
- $bool = $opt->allows_arg()
- True if arguments can be provided to the option (based on
type). This does not mean the option MUST accept arguments. 'D' type
options can accept arguments, but can also be used without arguments.
- $bool = $opt->applicable($options)
- If an option provides an applicability callback this will
use it to determine if the option is applicable given the
App::Yath::Options instance.
If no callback was provided then this returns true.
- $character = $opt->canon_type($type_name)
- Given a long alias for an option type this will return the
single-character canonical name. This will return undef for any unknown
strings. This will not translate single character names to themselves, so
"$opt->canon_type('s')" will return undef while
"$opt->canon_type('string')" will return 's'.
- $val = $opt->get_default()
- This will return the proper default value for the option.
If a custom default was provided it will be returned, otherwise the
correct generic default for the option type will be used.
Here is a snippet showing the defaults for types:
# First check env vars and return any values from there
...
# Then check for a custom default and use it.
...
return 0
if $self->{+TYPE} eq 'c'
|| $self->{+TYPE} eq 'b';
return []
if $self->{+TYPE} eq 'm'
|| $self->{+TYPE} eq 'D';
return {}
if $self->{+TYPE} eq 'h'
|| $self->{+TYPE} eq 'H';
# All others get undef
return undef;
- $val $opt->get_normalized($raw)
- This converts a raw value to a normalized one. If a custom
"normalize" attribute was set then it will be used, otherwise it
is normalized in accordance to the type.
This is where booleans are turned into 0 or 1, hashes are split, hash-lists
are split further, etc.
- $opt->handle($raw, $settings, $options, $list)
- This method handles setting the value in $settings. You
should not normally need to call this yourself.
- $opt->handle_negation()
- This method is used to handle a negated option. You should
not normally need to call this yourself.
- @list = $opt->long_args()
- Returns the name and any aliases.
- $ref = $opt->option_slot($settings)
- Get the settings->prefix->field reference. This
creates the setting field if necessary.
- $bool = $opt->requires_arg()
- Returns true if this option requires an argument when
used.
- $string = $opt->trace_string()
- return a string like "somefile.pm line 42" based
on where the option was defined.
- $bool = $opt->valid_type($character)
- Check if a single character type is valid.
- $string = $opt->cli_docs()
- Get the option documentation in a format that works for the
"yath help COMMAND" command.
- $string = $opt->pod_docs()
- Get the option documentation in POD format.
=item ....
.. option details ...
The source code repository for Test2-Harness can be found at
http://github.com/Test-More/Test2-Harness/.
- Chad Granum <[email protected]>
- Chad Granum <[email protected]>
Copyright 2020 Chad Granum <
[email protected]>.
This program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.
See
http://dev.perl.org/licenses/