Skip to content
Fetching contributors…
Cannot retrieve contributors at this time
148 lines (129 sloc) 4.06 KB
/* Program Class
This class represents a program as a logical unit. Each Program object
contains a collection of modes. Modes represent distinct behavioral patterns
which are typically selected depending on patterns of command-line
arguments. In addition to user-specified modes, there is also a default mode
that is selected if no other modes are satisfied, and an error mode that is
used to catch argument parsing errors and runtime errors.
*/
class Rosella.CommandLine.Program
{
// TODO: Add an ability to pass arguments to the main routine flag instead of
// in a single Arguments object.
var program_name; // The string name of the program
var default_mode; // The default ProgramMode
var arg_defs; // Hash of all argument definitions
var on_error; // The error handler callback
var modes; // A hash of named program modes
var description; // Program help description
// Constructor
function Program(string program_name)
{
self.program_name = program_name;
self.modes = {};
self.default_mode = new Rosella.CommandLine.ProgramMode.Default();
}
/* Public Methods
*/
function define_arguments(var raw_defs)
{
self.arg_defs = Rosella.CommandLine.ArgumentDef.get_argument_definition(raw_defs);
return self;
}
function set_description(string desc)
{
self.description = desc;
return self;
}
// Set a function to execute on errors
function on_error(var e)
{
self.on_error = e;
return self;
}
// Add a new ProgramMode with the given name
function add_mode(string name)
{
var mode = new Rosella.CommandLine.ProgramMode(name);
self.modes[name] = mode;
return mode;
}
// Get the default ProgramMode instance
function default_mode()
{
return self.default_mode;
}
// Execute the program with the given args
function run(var raw_args)
{
// TODO: Take some optional parameters, such as handles to use for
// overriding standard handles, other options.
var args = new Rosella.CommandLine.Arguments(self);
try {
args.parse(raw_args, self.arg_defs);
} catch (e) {
say(e);
self.try_handle_error(args);
return;
}
var mode = self.__find_mode(args);
var main_func = mode.main_function();
if (main_func == null) {
self.try_handle_error(args);
return;
}
mode.alias_positionals(args);
int exit_code = 0;
int has_ec = false;
Rosella.Parrot.try_report(function () {
:(int ec [optional], int hec [opt_flag]) = main_func(args);
exit_code = ec;
has_ec = hec;
});
if (has_ec)
exit(exit_code);
}
function get_usage_text(var sb = new 'StringBuilder')
{
string name = self.program_name;
self.default_mode.get_usage(name, sb);
for (string modename in self.modes) {
var mode = self.modes[modename];
mode.get_usage(name, sb);
}
return sb;
}
function get_help_text()
{
var sb = new 'StringBuilder';
self.get_usage_text(sb);
push(sb, "\n");
if (self.description != null) {
string desc = self.description;
push(sb, desc);
push(sb, "\n");
}
push(sb, "\n");
return self.arg_defs.get_description(sb);
}
/* Private Methods
*/
function __find_mode(var args)
{
for (string modename in self.modes) {
var mode = self.modes[modename];
if (mode.can_accept(args))
return mode;
}
return self.default_mode;
}
// On error, try to execute the error handler, if any.
function try_handle_error(var args)
{
var on_error = self.on_error;
if (on_error == null) {
say(self.get_usage_text());
} else
on_error(args);
}
}
Something went wrong with that request. Please try again.