|
Well, as the saying goes, "There's More Than One Way...", but you asked for the "best" way. I would rather not call any particular approach the "best" (it depends on your situation), but I'll give you a few alternatives. By the way, I'm answering this based on version 0.03_01 because you didn't specify a version and your error handling question implies that that's the version you're using. In any case, after the API is stable, I anticipate that these will still be valid:
(1) Use the built-in console command and design your interface to accept a command explicitly indicating interactive mode (of course, you can call it anything you want using command_alias()).
(2) Use the built-in console command but use your app's init() method to determine whether or not to invoke the console command (and thus, run interactively or not) based on whatever logic you need. Here's an example:
# interactivity.pl -- the application script:
CLI::Interactivity->run();
################################################
package CLI::Interactivity;
use base qw( CLI::Framework::Application );
sub option_spec {
[ 'interactive|i' => 'run interactively' ],
}
sub command_map {
{
scream => 'CLI::Interactive::Command::Scream',
console => 'CLI::Framework::Command::Console',
}
}
sub noninteractive_commands {'console'}
sub init {
my ($app, $opts) = @_;
# imagine fancy logic to determine whether or not to run interactively...
if( $opts->{interactive} ) {
$app->set_current_command('console');
}
return 1;
}
################################################
package CLI::Interactive::Command::Scream;
use base qw( CLI::Framework::Command );
sub usage_text {
q{
scream <something>: yell <something> loudly
}
}
sub validate {
my ($self, $cmd_opts, @args) = @_;
@args == 1 or die 'cannot scream without one arg';
}
sub run {
my ($self, $cmd_opts, @args) = @_;
return uc($args[0]).'!';
}
(3) You can call run_interactive() from a command's run() method. To do this, the command must be a metacommand (inherit from CLI::Framework::Command::Meta) so it can access the application object. In fact, this is how the console command works.
(4) Your suggestion could be made to work, but I don't advise it. The problem is that, after interactive mode exits, CLIF will try to execute the "current" command. That will probably be the last command run interactively. You probably don't want that. One way around this would be to define a dummy command class that overrides run() to do nothing and, in init, use $app->set_current_command('dummy') immediately following your call to run_interactive(). This would cause the dummy command to run after interactive mode, taking no action. But I'd classify that as a hack, so it is not recommended.
There may be other acceptable choices. I've personally never needed anything more than the built-in console command. |