如何使用App :: Cmd模块实现子命令?

时间:2018-12-21 18:02:18

标签: perl command command-line-interface

我使用App::Cmd来构建我的CLI应用程序。

是否可以实现docker network inspect之类的子命令? (假设inspect是子命令)

我有以下代码用于实现命令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;

我通过将foo bar baz修改为实现了子命令lib/Foo/Command/bar.pm

sub execute {
    my ( $self, $opt, $args ) = @_;    
    my $subcommand = $args->[0];

    if ( $subcommand eq 'baz' ) {
        print "Subcommand baz is working\n";
    }

    ...
}

还有什么更好的方法吗?

$args->[0]方法的最大缺点是您无法自动生成--helpfoo bar将显示与foo bar baz相同的帮助)

换句话说,App::Cmd适用于<bin_name> <command> [-?h] [long options...]调用语法,但是我需要<bin_name> <command> <subcommand> [-?h] [long options...]语法。

P.S。我为实验创建了Github repository

1 个答案:

答案 0 :(得分:1)

花了我一段时间才能在Github([1][2])上找到一些示例代码来弄清楚这一点。 对于foo bar baz用例,您需要满足以下条件:

# 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;