我发现App::Cmd对编写命令行应用非常有帮助,但是覆盖默认命令很有挑战性。有两个默认命令,help
和commands
。似乎help
命令解析子命令类中的opt_spec
定义以生成列表形式的帮助菜单。对于具有多个选项的命令,此默认帮助菜单非常难以理解。
我想要的是覆盖help
命令以提供我自己的自定义菜单,或完全禁用help
命令,只允许通过特定子命令的选项生成菜单。后一种选择很容易实现,但我仍然希望在这种情况下禁用全局help
选项,以便不打印两个不同的菜单,具体取决于帮助选项的位置。
我首先尝试的是在子命令类中定义usage_desc
和description
方法(在App::Cmd::Command::help文档中解释),但这只是在选项列表之前添加要打印的文本。例如,将自定义菜单添加到opt_spec
只会导致打印两个菜单。
我还尝试在我的help
课程中停用MyApp::Command
插件:
package MyApp::Command;
sub validate_args {
my ( $self, $opt, $args ) = @_;
$self->app->no_help_plugin;
$self->validate( $opt, $args );
}
但这似乎没有效果。我也尝试修改default_command
方法但没有成功。没有看到例子,很难理解如何使用这些方法。
任何人都可以提供一个示例(或指向CPAN上的一个示例),了解如何在使用App :: Cmd时覆盖或禁用全局help
命令?
答案 0 :(得分:0)
经过大量的实验,我能够找到解决问题的方法。文档没有告诉您的是,如果您停用帮助插件,则还必须提供自己的default_command
并在opt_spec
中对其进行定义。文档说您可以提供自己的默认命令或覆盖默认命令,但我的发现是您必须同时执行这两项操作来禁止显示警告消息。我将提供一个例子。
在MyApp.pm中:
package MyApp;
use App::Cmd::Setup -app;
sub global_opt_spec {
return (
[ 'man|m' => "Get the manual entry for a command" ],
[ 'help|h' => "Print some usage" ],
);
}
sub help {
print STDERR<<END
Usage:
myapp <command> [-h] [-m]
-m --man Get the manual entry for a command
-h --help Print some usage
Available commands:
commands: list the application's commands
initialize: A really useful description
END
}
在MyApp :: Command :: initialize中:
package MyApp::Command::initialize;
use strict;
use warnings;
use MyApp -command;
sub opt_spec {
return (
[ "file|f=s", "A required file"],
);
}
sub validate_args {
my ($self, $opt, $args) = @_;
my $command = __FILE__;
if ($self->app->global_options->{man}) {
system("perldoc $command");
}
elsif ($self->app->global_options->{help}) {
$self->help;
}
else {
$self->help and exit(0) unless $opt->{file};
}
}
sub execute {
my ($self, $opt, $args) = @_;
exit(0) if $self->app->global_options->{man} ||
$self->app->global_options->{help};
my $result = _some_method($opt);
}
sub help {
print STDERR<<END
Usage:
myapp <command> [-h] [-m]
-m --man Get the manual entry for a command
-h --help Print some usage
Options:
-f --file A required file
END
}
在myapp中:
#!/usr/bin/env perl
use strict;
use warnings;
use MyApp;
my $cmd = MyApp->new({ no_help_plugin => 1 });
$cmd->default_command( $cmd->help ) and exit unless @ARGV;
$cmd->run;
现在您可以运行myapp
,它将生成您提供的使用菜单。因为我已经定义了default_command
,所以默认帮助只会呈现您的帮助菜单而不会抱怨缺少命令。请注意,myapp help initialize
现在不会被识别,因此使用情况会更为熟悉myapp initialize -h
。前一个命令将只呈现我们想要的自定义帮助。
此外,现在每个子命令都有一个唯一的菜单。与仅编写自己的脚本或类相比,这对于一个简单的例子来说是多么荒谬的工作,但是对于复杂的命令,这应该使得使用更容易理解。
我愿意接受改进或简化此代码的建议,但它似乎正是我想要的,并且与App :: Cmd期望的一致。