Activator
view release on metacpan or search on metacpan
lib/Activator/Options.pm view on Meta::CPAN
C<--project> option if you like.
=head2 Realms
This module supports the concept of realms to allow multiple similar
configurations to override only the esential keys to "git 'er done".
=head2 Configuration Logic Summary
=over
=item *
All configuration files are read and merged together on a realm by
realm basis with higher precedence configuration files overriding
lower precedence. If duplicate level files exist in the Configuration
File Search Path, only the first discovered file is used.
=item *
All realms are then merged with the C<default> realm, I<realm> config
taking precedence.
=item *
All C<default> realm environment variables override all values for
each realm (excepting C<overrides> realm).
=item *
All specific realm environment variables override that realm's values
for the key.
=item *
The C<default> realm overrides section is used to override matching
keys in all realms.
=item *
The specific realm overrides section is used to override matching keys
in the requested realm.
=item *
Any command line options given override ALL matching keys for all
realms.
=item *
# TODO: NOT YET IMPLEMENTED
Perform variable substitution
=back
=head1 COMMAND LINE ARGUMENTS
This module allows long or short options using C<'-'> or C<'--'>
notation, allows barewords in any order, and recognizes the arguments
terminator C<'--'>. Also supported are multiple flag arguments:
#### turn on super verbosity. sets $opts->{v} = 2
myscript.pl -v -v
You can specify configured options at the command line for
override:
#### override the configuration file setting for 'foo'
myscript.pl --foo=bar
Command line overrides only apply to keys that exist in a
configuration file and any unrecognized options are ignored. C<@ARGV>
is modified to remove recognized options, leaving barewords and
unrecognized options in the order they were specified. This module has
no support for argument validation, and your script must handle
unrecognizd options and behave appropriately. There are numerous
modules on CPAN that can help you do that (L<Getopt::Long> for
example). If you do use another options module, make sure you call
C<get_opts()> BEFORE you call their processor, so that @ARGV will be
in an appropriate state.
Also, while YAML configuration (and this module) support deep
structures for options, you can only override top level keys that are
scalars using command line arguments and/or environment variables.
=head2 Special Arguments
There are a few special command line arguments that do not require
YAML existence:
--skip_env : ignore environment variables
--project=<> : use this value for <project> in config file search path.
--project_home=<> : useful for when utilizing <project_home>/.<project> config dir
--realm=<> : use <realm>.yml in config file processing and consider all
command line arguments to be in this realm
TODO: these are not implemented yet
Also supported are these variables which can be listed as many times
as necessary:
--conf_file=<> : include <> file for inclusion
--conf_path=<> : include <> path when looking for config files
=head1 ENVIRONMENT VARIABLES
Environment variables can be used to override any top level YAML
configuration key which is a scalar. The expected format is
C<ACT_OPT_[key]>. Note that YAML is case sensitive, so the environment
variables must match. Be especially wary of command shell senstive
characters in your YAML keys.
If you wish to override a key for only a particular realm, you
can insert the realm into the env variable wrapped by double
underscores:
ACT_OPT_foo - set 'foo' for default realm
ACT_OPT__bar__foo - set 'foo' only for 'bar' realm
lib/Activator/Options.pm view on Meta::CPAN
my $found_terminator = 0;
foreach my $arg ( @$argv_raw ) {
my ( $key, $value ) = $self->_get_arg( $arg );
if ( $found_terminator || !defined( $key ) ) {
DEBUG("'$arg' is a bareword or after the args terminator '--'");
push @$barewords, $arg;
next;
}
if( $key eq '--' ) {
DEBUG("'$arg' is the terminator");
$found_terminator = 1;
next;
}
if ( defined $value ) {
DEBUG("got key '$key' = '$value'");
# if we see an argument again, coerce this value into an
# array
if ( exists $argv->{ $key } ) {
if ( reftype ( $argv->{ $key } ) eq 'ARRAY' ) {
DEBUG("added '$value' to key list '$key'" );
push @{ $argv->{ $key } }, $value;
}
else {
DEBUG("created key list '$key' and added '$value'" );
$argv->{ $key } = [ $argv->{ $key }, $value ];
}
}
# just set it
else {
$argv->{ $key } = $value;
}
}
else {
# if we see a value again, increment the occurence count
if ( exists $argv->{ $key } ) {
DEBUG("incremented key '$key'" );
$argv->{ $key }++;
}
else {
DEBUG("set $key" );
$argv->{ $key } = 1;
}
}
}
# save these so we don't have to do it again
$self->{ARGV} = $argv;
$self->{BAREWORDS} = $barewords;
return ( $argv, $barewords );
}
# Helper to split an arg into key/value. Returns ($key, $value), where
# $value is undef if the argument is flag format (--debug), undef if
# it is a bareword ( foo ) and '--' if it is the arguments terminator
# symbol.
#
sub _get_arg {
my ( $self, $arg ) = @_;
if ( $arg !~ /^-(-)?/ ) {
return;
}
if ( $arg eq '--' ) {
return $arg;
}
my ( $key, $value ) = split /=/xms, $arg, 2;
if ( !defined $key ) {
Activator::Exception::Options->throw( 'argument',
'invalid',
$arg );
}
# clean up key
$key =~ s/^--?//;
# clean up value, if quoted
if ( defined $value ) {
$value =~ s/^"//;
$value =~ s/"$//;
}
return ( $key, $value );
}
# Merge config files into this objects Activator::Registry object
sub _process_config_for {
my ( $pkg, $realm ) = @_;
my $self = &new( @_ );
# figure out what project we are working on
my $project =
$self->{ARGV}->{project} ||
$ENV{ACT_OPT_project} ||
Activator::Exception::Options->throw( 'project', 'missing' );
# assemble a list of paths to look for config files
# TODO: look in all these places:
# --conf_path
# ACT_OPT_conf_path
# $ENV{ACT_OPT_project_home}/.<$ENV{ACT_OPT_project}>.d/
# $ENV{HOME}/.<$ENV{ACT_OPT_project}>.d/
# $ENV{HOME}/.activator.d/
# /etc/<$ENV{ACT_OPT_project}>.d/
# /etc/activator.d/
#
# assemble a list of files to process into the keys of $seach_paths
# TODO: assemble list of files for each of the above dirs
# --conf_file= : use $self->{ARGV}->{conf_file} (which could be an arrayref )
# ACT_OPT_conf_file= : comma separated list of files
( run in 0.671 second using v1.01-cache-2.11-cpan-39bf76dae61 )