use failure::*;
use std::collections::HashMap;
use std::collections::HashSet;
+use std::sync::Arc;
//use serde_json::Value;
use super::getopts;
-fn print_simple_usage(prefix: &str, _cli_cmd: &CliCommand, err: Error) {
+#[derive(Copy, Clone)]
+enum ParameterDisplayStyle {
+ //Config,
+ //SonfigSub,
+ Arg,
+ Fixed,
+}
+
+fn get_schema_type_text(schema: Arc<Schema>, _style: ParameterDisplayStyle) -> String {
+
+ let type_text = match *schema {
+ Schema::Null => String::from("<null>"), // should not happen
+ Schema::String(_) => String::from("<string>"),
+ Schema::Boolean(_) => String::from("<boolean>"),
+ Schema::Integer(_) => String::from("<integer>"),
+ Schema::Object(_) => String::from("<object>"),
+ Schema::Array(_) => String::from("<array>"),
+ };
+
+ type_text
+}
+
+fn get_property_description(
+ name: &str,
+ schema: Arc<Schema>,
+ style: ParameterDisplayStyle
+) -> String {
+
+ let type_text = get_schema_type_text(schema, style);
+
+ let display_name = match style {
+ ParameterDisplayStyle::Arg => {
+ format!("--{}", name)
+ }
+ ParameterDisplayStyle::Fixed => {
+ format!("<{}>", name)
+ }
+ };
- eprintln!("Error: {}", err);
- eprintln!("\nUsage: {} <TODO>", prefix);
+ format!(" {:-10} {}", display_name, type_text)
+}
+
+fn generate_usage_str(prefix: &str, cli_cmd: &CliCommand, indent: &str) -> String {
+
+ let arg_param = &cli_cmd.arg_param;
+ let fixed_param = &cli_cmd.fixed_param;
+ let properties = &cli_cmd.info.parameters.properties;
+
+ let mut done_hash = HashSet::<&str>::new();
+ let mut args = String::new();
+
+ for positional_arg in arg_param {
+ let (optional, _schema) = properties.get(positional_arg).unwrap();
+ args.push(' ');
+ if *optional { args.push('['); }
+ args.push('<'); args.push_str(positional_arg); args.push('>');
+ if *optional { args.push(']'); }
+
+ //arg_descr.push_str(&get_property_description(positional_arg, schema.clone(), ParameterDisplayStyle::Fixed));
+ done_hash.insert(positional_arg);
+ }
+
+ let mut options = String::new();
+
+ let mut prop_names: Vec<&str> = properties.keys().map(|v| *v).collect();
+ prop_names.sort();
+
+ for prop in prop_names {
+ let (optional, schema) = properties.get(prop).unwrap();
+ if done_hash.contains(prop) { continue; }
+ if fixed_param.contains(&prop) { continue; }
+
+ let type_text = get_schema_type_text(schema.clone(), ParameterDisplayStyle::Arg);
+
+ if *optional {
+
+ options.push(' ');
+ options.push_str(&get_property_description(prop, schema.clone(), ParameterDisplayStyle::Arg));
+
+ } else {
+ args.push_str("--"); args.push_str(prop);
+ args.push(' ');
+ args.push_str(&type_text);
+ }
+
+ done_hash.insert(prop);
+ }
+
+
+ format!("{}{}{}", indent, prefix, args)
+}
+
+fn print_simple_usage_error(prefix: &str, cli_cmd: &CliCommand, err: Error) {
+
+ eprint!("Error: {}\nUsage: ", err);
+
+ print_simple_usage(prefix, cli_cmd);
+}
+
+fn print_simple_usage(prefix: &str, cli_cmd: &CliCommand) {
+
+ let usage = generate_usage_str(prefix, cli_cmd, "");
+ eprintln!("{}", usage);
}
fn handle_simple_command(prefix: &str, cli_cmd: &CliCommand, args: Vec<String>) {
&args, &cli_cmd.arg_param, &cli_cmd.info.parameters) {
Ok((p, r)) => (p, r),
Err(err) => {
- print_simple_usage(prefix, cli_cmd, err.into());
+ print_simple_usage_error(prefix, cli_cmd, err.into());
std::process::exit(-1);
}
};
if !rest.is_empty() {
let err = format_err!("got additional arguments: {:?}", rest);
- print_simple_usage(prefix, cli_cmd, err);
+ print_simple_usage_error(prefix, cli_cmd, err);
std::process::exit(-1);
}
None
}
-fn print_nested_usage(prefix: &str, _def: &CliCommandMap, err: Error) {
+fn print_nested_usage_error(prefix: &str, def: &CliCommandMap, err: Error) {
+
+ eprintln!("Error: {}\n\nUsage:\n", err);
+
+ print_nested_usage(prefix, def);
+}
+
+fn print_nested_usage(prefix: &str, def: &CliCommandMap) {
- eprintln!("Error: {}", err);
- eprintln!("\nUsage: {} <TODO>", prefix);
+ let mut cmds: Vec<&String> = def.commands.keys().collect();
+ cmds.sort();
+
+ for cmd in cmds {
+ let new_prefix = format!("{} {}", prefix, cmd);
+
+ match def.commands.get(cmd).unwrap() {
+ CommandLineInterface::Simple(cli_cmd) => {
+ let usage = generate_usage_str(&new_prefix, cli_cmd, "");
+ eprintln!("{}", usage);
+ }
+ CommandLineInterface::Nested(map) => {
+ print_nested_usage(&new_prefix, map);
+ }
+ }
+ }
}
});
let err = format_err!("no command specified.\nPossible commands: {}", list);
- print_nested_usage(prefix, def, err);
+ print_nested_usage_error(prefix, def, err);
std::process::exit(-1);
}
Some(cmd) => cmd,
None => {
let err = format_err!("no such command '{}'", command);
- print_nested_usage(prefix, def, err);
+ print_nested_usage_error(prefix, def, err);
std::process::exit(-1);
}
};