NAME
CLI::Framework::Command - CLIF Command superclass
SYNOPSIS
# Define commands and subcommands for use in a CLIF application...
# (placing package files with this content in the command search path for
# a CLIF app will make the commands available to the application)
# Command:
package My::Example::Command;
use base qw( CLI::Framework::Command );
sub usage_text { ... }
sub notify { ... }
1;
# Sub-command:
package My::Example::Subcommand;
use base qw( My::Example::Command );
sub usage_text { ... }
sub run { ... }
1;
# Sub-sub-command:
package My::Example:SubSubcommand;
use base qw( My::Example::Subcommand );
sub usage_text { ... }
sub run { ... }
1;
...
DESCRIPTION
CLI::Framework::Command (command class for use with CLI::Framework::Application) is the base class for CLIF commands. All CLIF commands should inherit from this class.
CONCEPTS
- subcommands
-
Commands can have "subcommands," which are also objects of this class. Subcommands can, in turn, have their own subcommands, and this pattern repeats recursively.
NOTE that in this documentation, the term "command" may be used to refer to both commands and subcommands.
METHODS: OBJECT CONSTRUCTION
manufacture
# (manufacture MyApp::Command::Go)
my $go = CLI::Framework::Command->manufacture(
command_search_path => "MyApp/Command", command => 'go'
);
# (manufacture MyApp::Command::Go::Fast)
$go->manufacture( command => 'fast' );
CLI::Framework::Command is an abstract factory; this is the factory method that constructs and returns an object of the specific command that is requested. Called as a class method, the named command is constructed and returned. As an object method, the named subcommand is constructed and registered under the main command that manufacture()
is being invoked on.
new
$object = $cli_framework_command_subclass->new() or die "Cannot instantiate $class";
Basic constructor.
METHODS: SESSION DATA
CLIF commands may need to share data with other commands and with their associated application. These methods support those needs.
set_session
$app->set_session( \%session_data );
Set the entire session from the given hash.
session
# get a single item from the session...
$value = $app->session( $key );
# save a single item in the session...
$app->session( $key => $value );
# get the entire session...
$s = $app->session();
Accessor/mutator for the session
METHODS: COMMAND DISPATCHING
set_default_usage
$cmd->set_default_usage( $usage_message );
Set the default usage message for the command.
get_default_usage
$usage_msg = $cmd->get_default_usage();
Get the default usage message for the command. This message is used by usage.
NOTE: get_default_usage()
merely retrieves the usage data that has already been set. CLIF only sets the default usage message for a command when processing a run request for the command. Therefore, the default usage message for a command may be empty.
usage
# Command usage...
print $cmd->usage();
# Subcommand usage...
print $cmd->usage( $subcommand_name, @subcommand_chain );
Attempts to find and return a usage message for a command or subcommand.
If a subcommand is given, returns a usage message for that subcommand. If no subcommand is given or if the subcommand cannot produce a usage message, returns a general usage message for the application.
Logically, here is how the usage message is produced:
If registered subcommand(s) are given, attempt to get usage message from a subcommand (NOTE that a sequence of subcommands could be given, e.g.
qw(task list completed)
, which would result in the usage message for final subcommand,completed
). If no usage message is defined for the subcommand, the usage message for the command is used instead.If the command has implemented usage_text, its return value is used as the usage message.
Finally, if no usage message has been found, the default usage message produced by get_default_usage is returned.
dispatch
$command->dispatch( $cmd_opts, @args );
For the given command request, perform any applicable validation and initialization with respect to the supplied options $cmd_opts
and arguments (@args
).
@args
may indicate the request for a subcommand:
{ <subcmd> [subcmd-opts] {...} } [subcmd-args]
If a subcommand registered under the indicated command is requested, initialize and dispatch
the subcommand with its options [subcmd-opts]
and arguments. Otherwise, run
the command itself.
This means that a request for a subcommand will result in the run()
method of only the deepest-nested subcommand (because dispatch()
will keep forwarding to subcommands until the args no longer indicate that a subcommand is requested). Furthermore, the only command that can receive args is the final subcommand in the chain (but all commands in the chain can receive options). However, each command in the chain can affect the execution process through its notify method.
METHODS: COMMAND REGISTRATION
get_registered_command_names
This is an alias for registered_subcommand_names.
registered_subcommand_names
@registered_subcommands = $cmd->registered_subcommand_names();
Return a list of the currently-registered subcommands.
get_registered_command
This is an alias for get_registered_subcommand.
get_registered_subcommand
$subcmd_obj = $cmd->get_registered_subcommand('name');
Given the name of a registered subcommand, return a reference to the subcommand object. If the subcommand is not registered, returns undef.
register_command
This is an alias for register_subcommand.
register_subcommand
$cmd->register_subcommand( $subcmd_obj );
Register $subcmd_obj
as a subcommand under master command $cmd
.
If $subcmd_obj
is not a CLI::Framework::Command, returns undef. Otherwise, returns $subcmd_obj
.
NOTE: Subcommand names must be unique. If register_subcommand()
is called with a subcommand having the same name as an existing registered subcommand, the existing one will be replaced by the new one.
COMMAND SUBCLASS HOOKS
Just as CLIF Applications have hooks that subclasses can take advantage of, CLIF Commands are able to influence the command dispatch process via several hooks. Subclasses can (and must, in some cases, as noted) override the following methods:
name
Class method that takes no arguments and returns the name of the command. The default implementation of this method uses the normalized base name of the package as the command name, e.g. the command defined by the package My::Application::Command::Xyz would be named 'xyz'.
Subclasses may override this if a different naming scheme is desired.
option_spec
sub option_spec {
(
[ "verbose|v" => "be verbose" ],
[ "logfile=s" => "path to log file" ],
)
}
This method should return an option specification as expected by the Getopt::Long::Descriptive function describe_options
. The option specification defines what options are allowed and recognized by the command.
Subclasses should override this method if commands accept options (otherwise, the command will not recognize any options).
subcommand_alias
sub subcommand_alias {
rm => 'remove',
new => 'create',
j => 'jump',
r => 'run',
}
Subcommands can have aliases to support shorthand versions of subcommand names.
Subclasses should override this method if subcommand aliases are desired. Otherwise, the commands will only be recognized by their full names.
validate
To provide strict validation of a command request, a subclass may override this method. Otherwise, validation is skipped.
validate
is called during command dispatch as follows:
$cmd->validate( $cmd_opts, @args );
$cmd_opts
is an options hash with received command options as keys and their values as hash values.
@args
is a list of received command arguments.
validate
is expected to throw an exception if validation fails. This allows your validation routine to provide a context-specific failure message.
NOTE that Getop::Long::Descriptive performs some validation of its own based on the option_spec. However, validate
allows more flexibility in validating command options and also allows validation of arguments.
notify
If a request for a subcommand is received, the master command itself does not run(). Instead, its notify() method is called. This gives the master command a chance to act before the subcommand is run.
The <notify> method is called as follows:
$cmd->notify( $subcommand, $cmd_opts, @args );
$subcommand
is the subcommand object.
$cmd_opts
is the options hash for the subcommand.
@args
is the argument list for the subcommand.
usage_text
If implemented, this method should simply return a string containing usage information for the command. It is used automatically to provide context-specific help.
Implementing this method is optional. See usage for details on how usage information is generated within the context of a CLIF application.
run
This method is responsible for the main execution of the command. It is called as follows:
$output = $cmd->run( $cmd_opts, @args )
$cmd_opts
is a pre-validated options hash with command options as keys and their values as hash values.
@args
is a list of the command arguments.
The default implementation of this method simply calls usage to show help information for the command. Therefore, subclasses will usually override run()
(Occasionally, it is useful to have a command that does little or nothing on its own but has subcommands that define the real behavior. In such relatively uncommon cases, it may make sense not to override run()
).
If an error occurs during the execution of a command via its run
method, the run
method code should throw an exception. The exception will be caught and handled appropriately by CLIF.
The return value of the run
method is treated as data to be output by the render method in your CLIF Application class. Note that nothing should be printed directly. Also note that if no output is produced, the run
method should return undef or empty string.
SUBCLASSING
Inheriting from CLI::Framework::Command to produce new commands is almost as easy as implementing the purely abstract methods in "COMMAND SUBCLASS HOOKS" and overriding the others as necessary for your new command class. However, there are a few additional details to be aware of...
METACOMMANDS
CLI::Framework::Command::Meta - Class defining application-aware commands.
This class is a subclass of CLI::Framework::Command. It defines "metacommands", commands that are application-aware (and thus, implicitly aware of all other commands registered within the application). Metacommands have methods that set and retrieve the application within which they are running. This class exists as a separate class because, with few exceptions, commands should be independent of the application they are associated with and should not affect that application. Metacommands represent the exception to that rule.
app
$app = $command->app();
Return the application object associated with a command object.
set_app
$command->set_app( $app );
Set the application object associated with a command object.
DIAGNOSTICS
Missing required param 'command'
-
manufacture requires a named parameter
command
, which specifies the name of the requested command. Error: failed to require() subcommand from package file '<file path>'
-
manufacture failed when trying to
require()
a subcommand (a package located in a directory named after the master command). Error: failed to instantiate subcommand '<class>' via method new()
-
Object construction for the subcommand <class> (whose package has already been
require()d
) was unsuccessful. Must specify 'command_search_path' for command construction
-
manufacture requires the
command_search_path
parameter when called as a class method. Error: failed to require() base command from package file '<file path>'
-
manufacture failed when trying to
require()
a "master command." Error: Cannot instantiate class '<class>' via method new()
-
Object construction for the "master command" <class> was unsuccessful.
CONFIGURATION & ENVIRONMENT
When called as an object method on an existing Command object "X", manufacture looks for the named subcommand in the directory path X:
# Where $x isa X...
$x->manufacture( command => 'foo' );
# ...CLIF will search for X/Foo.pm
So remember that subcommands should be given names that explicitly convey their class hierarchy (e.g. subcommand of Do::Something
should be Do::Something::Now
and not Some::Other::Now), and located as such on the filesystem.
DEPENDENCIES
Carp
Getopt::Long::Descriptive
Class::ISA
File::Spec
Class::Inspector
CLI::Framework::Exceptions
SEE ALSO
CLI::Framework::Application
LICENSE AND COPYRIGHT
Copyright (c) 2009 Karl Erisman (karl.erisman@icainformatics.com), ICA Informatics. All rights reserved.
This is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic.
AUTHOR
Karl Erisman (kerisman@cpan.org)