ETOOBUSY 🚀 minimal blogging for the impatient
App::Easer "multilevel" example
TL;DR
Another example on App-Easer, this time with additional sub-commands.
In last post App::Easer example we took a look at a simple example
where the main “upper level” command had two sub-commands only, i.e. the
ones generated automatically (help
and commands
).
In the following example, we extend to add two more sub-commands, bar
and date
.
#!/usr/bin/env perl
use v5.24;
use experimental 'signatures';
use App::Easer 'run';
my $app = {
commands => {
MAIN => {
name => 'main app',
help => 'this is the main app',
description => 'Yes, this really is the main app',
options => [
{
name => 'foo',
description => 'option foo!',
getopt => 'foo|f=s',
environment => 'EX2_FOO',
default => 'bar',
},
],
execute => sub ($global, $conf, $args) {
my $foo = $conf->{foo};
say "Hello, $foo!";
return 0;
},
'default-child' => '', # run execute by default
children => [qw< bar date >],
},
bar => {
name => 'bar',
supports => [qw< bar Bar BAR >],
help => 'sub command to bar your gaahs',
description => <<'END',
What should we say more about sub-command bar?
Have you ever needed to bar something? Now you can!
END
options => [
{
getopt => 'what|w=i',
description => 'number of times to say what',
environment => 'EX2_BAR_WHAT',
default => 3,
},
{
getopt => 'ever|e!',
description => 'say ever at the end or not',
environment => 'EX2_BAR_EVER',
default => 0,
}
],
'default-child' => '',
'no-auto' => '*',
execute => sub ($global, $conf, $args) {
say join ' ', ('what') x $conf->{what};
say 'ever!' if $conf->{ever};
return 0;
},
},
date => {
supports => [qw< date time now wtii >],
help => 'print the current date and time',
description => 'Just the plain date from Perl',
options => [
{
getopt => 'gm|g!',
description => 'print in GMT instead of local',
environment => 'EX2_DATE_GM',
default => 0,
},
],
'default-child' => '',
'no-auto' => '*',
execute => sub ($global, $conf, $args) {
my $time = $conf->{gm} ? gmtime() : localtime();
# $conf->{foo} comes from the parent command!!!
say "$conf->{foo} says: $time";
},
},
},
};
exit run($app, [@ARGV]);
The code above is available as ex2.pl.
Let’s first take a look at the help for the new commands:
$ ./ex2.pl help
this is the main app
Description:
Yes, this really is the main app
Options:
foo:
command-line: mandatory string option
--foo <value>
-f <value>
environment : EX2_FOO
default : bar
Sub commands:
bar: sub command to bar your gaahs
(also as: Bar, BAR)
date: print the current date and time
(also as: time, now, wtii)
help: print a help message
commands: list sub-commands
One thing that we can note is that the two new sub-commands can be
invoked using multiple aliases, e.g. bar
can also be invoked as Bar
or BAR
(but not baR
):
$ ./ex2.pl bar --what 5 --ever
what what what what what
ever!
$ ./ex2.pl Bar --what 5 --ever
what what what what what
ever!
$ ./ex2.pl BAR --what 5 --ever
what what what what what
ever!
$ ./ex2.pl baR --what 5 --ever
cannot find sub-command 'baR'
The sub-commands get their help too:
$ ./ex2.pl help BAR
sub command to bar your gaahs
Description:
What should we say more about sub-command bar?
Have you ever needed to bar something? Now you can!
Can be called as: bar, Bar, BAR
Options:
what:
command-line: mandatory integer option
--what <value>
-w <value>
environment : EX2_BAR_WHAT
default : 3
ever:
command-line: boolean option
--ever | --no-ever
-e
environment : EX2_BAR_EVER
default : 0
$ ./ex2.pl help time
print the current date and time
Description:
Just the plain date from Perl
Can be called as: date, time, now, wtii
Options:
gm:
command-line: boolean option
--gm | --no-gm
-g
environment : EX2_DATE_GM
default : 0
Command date
/time
/… shows that descendant commands inherit
option values from parents:
execute => sub ($global, $conf, $args) {
my $time = $conf->{gm} ? gmtime() : localtime();
# $conf->{foo} comes from the parent command!!!
say "$conf->{foo} says: $time";
},
The resulting execution is:
$ ./ex2.pl date
bar says: Sat Jul 3 00:08:28 2021
$ ./ex2.pl --foo Oyeee date
Oyeee says: Sat Jul 3 00:08:32 2021
So… it seems that App-Easer works fine, now I have to write a ton of tests!