I use App::Cmd for building my CLI apps.
Is it possible to implement subcommand like docker network inspect ? (assuming that inspect is subcommand)
I have following code for implementing command foo bar
$ cat bin/foo
#!/usr/bin/perl
use Foo;
Foo->run;
$ cat lib/Foo.pm
package Foo;
use App::Cmd::Setup -app;
1;
$ cat lib/Foo/Command/bar.pm
package Foo::Command::bar;
use App::Cmd::Setup -command;
sub execute {
print "Hello world\n";
}
1;
I implemented subcommand foo bar baz by modifying lib/Foo/Command/bar.pm as:
sub execute {
my ( $self, $opt, $args ) = @_;
my $subcommand = $args->[0];
if ( $subcommand eq 'baz' ) {
print "Subcommand baz is working\n";
}
...
}
Is there any better way ?
Big minus of $args->[0] approach is that you can not auto generate --help (foo bar will show same help as foo bar baz)
In other words, App::Cmd is sharpen for <bin_name> <command> [-?h] [long options...] call syntax, but I need <bin_name> <command> <subcommand> [-?h] [long options...] syntax.
P.S. I created Github repository for experiments
It took me a while to find some example code on Github ([1], [2]) to figure this out.
For the foo bar baz use case, you need the following:
# Foo.pm is unchanged from your code
# Bar.pm is no longer a command module
$ cat lib/Foo/Command/Bar.pm
package Foo::Command::Bar;
use base qw/App::Cmd::Subdispatch/;
use constant plugin_search_path => __PACKAGE__;
# no need for execute(), this module only dispatches subcommands
# abstract() and show_desc() are still supported
1;
# Finally, a subcommand like `baz` needs its own script Baz.pm
# (mind the file location)
$ cat lib/Foo/Command/Bar/Baz.pm
package Foo::Command::Bar::Baz;
use App::Cmd::Setup -command;
sub execute {
print "Hello world\n";
}
1;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With