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

问题描述 投票:3回答:1

我使用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

perl command command-line-interface
1个回答
0
投票

我花了一些时间在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;
© www.soinside.com 2019 - 2024. All rights reserved.