Reputation: 91
I would like the --import parameter to have a "sub-parameter" that will only work on this parameter, nowhere else. Example:
app.pl --import --fresh
output: command working
app.pl --export
output: command working
app.pl --export --fresh
output: command not found
Can this be achieved by GetOpt::Long? Please, guide me a little.
Upvotes: 2
Views: 207
Reputation: 66883
I take the purpose for this invocation, that matters for implementation here, to be the following.
There is a flag (call it $fresh
) that need be set under the --import
option, along with other flag(s) associated with --import
. Additionally, there may be an independent option --fresh
, which sets the $fresh
flag.
While Getopt::Long doesn't support nested options this can be achieved using its other facilities. Set --import
to take an optional argument with :
, and set variables in a sub. If the word fresh
is submitted as the value set the corresponding ($fresh
) flag.
use warnings;
use strict;
use feature 'say';
use Getopt::Long;
my ($import, $fresh);
GetOptions(
'import:s' => sub {
$import = 1;
$fresh = 1 if $_[1] eq 'fresh';
},
'fresh!' => \$fresh # if independent --fresh option is needed
);
say 'import: ', $import // 'not submitted'; #/
say 'fresh: ', $fresh // 'not submitted';
The sub receives two arguments, the option name and value, and the value is used to check whether fresh
was passed. The code as it stands does nothing for other words that may be passed, but it can be made to abort (with a usage message) if any value other than fresh
is submitted.
Whatever particular reasons there are to require this invocation can be coded in the sub.
If a separate --fresh
option is indeed provided then the user need be careful since it is possible to submit conflicting values for $fresh
– one with --import
and another in --fresh
itself. This can be checked for in the code.
The option --import
still works as a simple flag on its own.
Valid invocations are
gol.pl --import # $import is 1 gol.pl --import fresh # $import is 1, $fresh is 1 gol.pl --fresh # $fresh is 1
Since fresh
is set in a sub as a value of --import
it cannot be set with any other options.
This differs from the requirement by having fresh
as a word, without dashes.
Upvotes: 2
Reputation: 385657
Options can indeed require a parameter. The parameter doesn't use --
, though.
GetOptions(
'help' => \&help,
'import:s' => \$opt_import,
)
or usage();
defined($opt_import) && ( $opt_import eq '' || opt_import eq 'fresh' )
or usage("Invalid value for --import");
@ARGV == 0
or usage("Incorrect number of arguments");
# Convert into booleans for convenience.
$opt_fresh = defined($opt_import) && $opt_import eq 'fresh';
$opt_import = defined($opt_import);
The above accepts the following:
app.pl --import fresh
app.pl --import
app.pl
Note that using =s
instead of :s
will make providing a value mandatory.
Sample helpers:
use FIle::Basename qw( basename );
sub usage {
my $basename = basename($0);
print("usage: $basename [options]\n");
print(" $basename --help\n");
print("\n");
print("Options:\n");
print("\n");
print(" --import [fresh]\n");
exit(0);
}
sub usage {
if (@_) {
chomp( my $msg = shift );
warn("$msg\n");
}
my $basename = basename($0);
warn("Try '$basename --help' for more information.\n);
exit(1);
}
Upvotes: 2
Reputation: 2100
I think that without resorting to partial parsing the closest you can get to with Getopt::Long is this:
use strict;
use warnings;
use Data::Dumper;
use Getopt::Long;
GetOptions('export=s%{1,5}'=>\my %export, 'another_option=s'=>\my $ao);
print Dumper({ 'export'=> \%export, 'another_option'=>$ao});
perl t1.pl --export fresh=1 b=2 c=3 --another_option value
$VAR1 = {
'export' => {
'c' => '3',
'b' => '2',
'fresh' => '1'
},
'another_option' => 'value'
};
Here export=s%{1,5}
parses --export fresh=1 b=2 c=3
into hash %export
.
s%{1,5}
expects from 1 to 5 key=value
pairs
Upvotes: 3