diff --git a/src/app/app.rs b/src/app/app.rs index ca94a3f9..060f939e 100644 --- a/src/app/app.rs +++ b/src/app/app.rs @@ -158,43 +158,66 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{ /// let app = App::from_yaml(yml); /// ``` #[cfg(feature = "yaml")] - pub fn from_yaml<'y>(doc: &'y Yaml) -> App<'y, 'y, 'y, 'y, 'y, 'y> { + pub fn from_yaml<'y>(mut yaml: &'y Yaml) -> App<'y, 'y, 'y, 'y, 'y, 'y> { // We WANT this to panic on error...so expect() is good. - let mut a = App::new(doc["name"].as_str().unwrap()); - if let Some(v) = doc["version"].as_str() { + let mut is_sc = None; + let mut a = if let Some(name) = yaml["name"].as_str() { + App::new(name) + } else { + let yaml_hash = yaml.as_hash().unwrap(); + let sc_key = yaml_hash.keys().nth(0).unwrap(); + is_sc = Some(yaml_hash.get(sc_key).unwrap()); + App::new(sc_key.as_str().unwrap()) + }; + yaml = if let Some(sc) = is_sc { + sc + } else { + yaml + }; + if let Some(v) = yaml["version"].as_str() { a = a.version(v); } - if let Some(v) = doc["author"].as_str() { + if let Some(v) = yaml["author"].as_str() { a = a.author(v); } - if let Some(v) = doc["bin_name"].as_str() { + if let Some(v) = yaml["bin_name"].as_str() { a = a.bin_name(v); } - if let Some(v) = doc["about"].as_str() { + if let Some(v) = yaml["about"].as_str() { a = a.about(v); } - if let Some(v) = doc["after_help"].as_str() { + if let Some(v) = yaml["after_help"].as_str() { a = a.after_help(v); } - if let Some(v) = doc["usage"].as_str() { + if let Some(v) = yaml["usage"].as_str() { a = a.usage(v); } - if let Some(v) = doc["help"].as_str() { + if let Some(v) = yaml["help"].as_str() { a = a.help(v); } - if let Some(v) = doc["help_short"].as_str() { + if let Some(v) = yaml["help_short"].as_str() { a = a.help_short(v); } - if let Some(v) = doc["version_short"].as_str() { + if let Some(v) = yaml["version_short"].as_str() { a = a.version_short(v); } - if let Some(v) = doc["settings"].as_vec() { + if let Some(v) = yaml["settings"].as_vec() { for ys in v { if let Some(s) = ys.as_str() { a = a.setting(s.parse().ok().expect("unknown AppSetting found in YAML file")); } } } + if let Some(v) = yaml["args"].as_vec() { + for arg_yaml in v { + a = a.arg(Arg::from_yaml(&arg_yaml.as_hash().unwrap())); + } + } + if let Some(v) = yaml["subcommands"].as_vec() { + for sc_yaml in v { + a = a.subcommand(SubCommand::from_yaml(&sc_yaml)); + } + } a } diff --git a/src/args/subcommand.rs b/src/args/subcommand.rs index 6fa468e5..36def9ed 100644 --- a/src/args/subcommand.rs +++ b/src/args/subcommand.rs @@ -1,3 +1,6 @@ +#[cfg(feature = "yaml")] +use yaml_rust::Yaml; + use App; use ArgMatches; @@ -42,4 +45,18 @@ impl<'n, 'a> SubCommand<'n, 'a> { pub fn with_name<'au, 'v, 'ab, 'u, 'h, 'ar>(name: &'ar str) -> App<'au, 'v, 'ab, 'u, 'h, 'ar> { App::new(name) } + + /// Creates a new instance of a subcommand from a YAML (.yml) document + /// + /// # Example + /// + /// ```ignore + /// # use clap::{App, Arg, SubCommand}; + /// let sc_yaml = load_yaml!("test_subcommand.yml"); + /// let sc = SubCommand::from_yaml(sc_yaml); + /// ``` + #[cfg(feature = "yaml")] + pub fn from_yaml<'y>(yaml: &'y Yaml) -> App<'y, 'y, 'y, 'y, 'y, 'y> { + App::from_yaml(yaml) + } }