use std::env;
use std::path::Path;
use getopts;
use types::{Params, CommandCallback};
use types::{Options, Argument};
use formatting::HelpFormatter;
pub struct Command {
name: String, callback: CommandCallback, options: Vec<Options>, arguments: Vec<Argument>, help: String, epilog: String, short_help: String, }
impl Command {
pub fn new(name: &str, callback: CommandCallback) -> Command {
Command {
name: name.to_string(),
callback: callback,
options: Vec::new(),
arguments: Vec::new(),
help: String::new(),
epilog: String::new(),
short_help: String::new(),
}
}
pub fn option(&mut self, short_name: &'static str, long_name: &'static str, help: &'static str,
is_flag: bool, is_bool_flag: bool, multiple: bool,
required: bool, default: Option<&'static str>) {
let option = Options::new(short_name, long_name, help, is_flag,
is_bool_flag, multiple, required, default);
self.options.push(option);
}
pub fn argument(&mut self, name: &'static str, required: bool, default: Option<&'static str>) {
let argument = Argument::new(name, required, default);
self.arguments.push(argument);
}
fn make_formatter(&self) -> HelpFormatter {
HelpFormatter::new(80, 2)
}
fn format_usage(&self, formatter: &mut HelpFormatter) {
let mut pieces: Vec<String> = Vec::new();
pieces.push("[OPTIONS]".to_string());
for argument in self.arguments.iter() {
pieces.push(argument.get_usage_piece());
}
formatter.write_usage(&self.name, pieces.concat(), "Usage: ")
}
pub fn get_usage(&self) -> String {
let mut formatter = self.make_formatter();
self.format_usage(&mut formatter);
formatter.getvalue()
}
fn format_help_text(&self, formatter: &mut HelpFormatter) {
if !self.help.is_empty() {
formatter.write_paragraph();
formatter.indent();
formatter.write_text(self.help.clone());
formatter.dedent();
}
}
fn format_options(&self, formatter: &mut HelpFormatter) {
let mut opts: Vec<(String, String)> = Vec::new();
for option in self.get_options().iter() {
opts.push(option.get_help_record());
}
if !opts.is_empty() {
formatter.enter_section("Options");
formatter.write_dl(opts);
formatter.exit_section();
}
}
fn format_epilog(&self, formatter: &mut HelpFormatter) {
if !self.epilog.is_empty() {
formatter.write_paragraph();
formatter.indent();
formatter.write_text(self.epilog.clone());
formatter.dedent();
}
}
fn format_help(&self, formatter: &mut HelpFormatter) {
self.format_usage(formatter);
self.format_help_text(formatter);
self.format_options(formatter);
self.format_epilog(formatter);
}
pub fn get_help(&self) -> String {
let mut formatter = self.make_formatter();
self.format_help(&mut formatter);
formatter.getvalue()
}
fn get_help_option(&self) -> Options {
let help_option_names = vec!["h", "help"];
let show_help = |params: Params| {
print!("{}", self.get_help());
};
return Options::new(help_option_names[0], help_option_names[1],
"Show this message and exit.", true, true, false, false, None);
}
pub fn invoke(&self, pragram_name: String, args: Vec<String>) {
let args = self.parse_args(args);
let callback = self.callback;
callback(args);
}
fn get_options(&self) -> Vec<Options> {
let mut options: Vec<Options> = Vec::new();
for option in self.options.iter() {
options.push(option.clone());
}
let help_option = self.get_help_option();
options.push(help_option);
return options;
}
fn make_parser(&self) -> getopts::Options {
let mut parser = getopts::Options::new();
for option in self.get_options().iter() {
option.add_to_parser(&mut parser);
}
return parser;
}
fn parse_args(&self, args: Vec<String>) -> Vec<String> {
args
}
pub fn run(&self) {
let mut args = env::args();
let program = args.nth(0).unwrap();
let program_path = Path::new(&program);
let program_name = program_path.file_name().unwrap().to_str().unwrap();
self.invoke(program_name.to_string(), args.collect());
}
}