From 02462150ca750bdc7012627d7e8d96379d494d7f Mon Sep 17 00:00:00 2001 From: Kevin K Date: Thu, 9 Apr 2015 17:46:24 -0400 Subject: [PATCH] feat(ArgMatches): add method to get default usage string --- src/app.rs | 52 +++++++++++++++++++++++++++++------------- src/args/argmatches.rs | 22 ++++++++++++++++-- 2 files changed, 56 insertions(+), 18 deletions(-) diff --git a/src/app.rs b/src/app.rs index a9963b94834..ef3138a2301 100644 --- a/src/app.rs +++ b/src/app.rs @@ -6,6 +6,7 @@ use std::path::Path; use std::vec::IntoIter; use std::borrow::ToOwned; use std::process; +use std::fmt::Write; use args::{ ArgMatches, Arg, SubCommand }; use args::{FlagArg, FlagBuilder}; @@ -60,6 +61,7 @@ pub struct App<'a, 'v, 'ab, 'u, 'ar> { long_list: HashSet<&'ar str>, blacklist: HashSet<&'ar str>, usage_str: Option<&'u str>, + usage: Option, bin_name: Option } @@ -96,6 +98,7 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{ short_list: HashSet::new(), long_list: HashSet::new(), usage_str: None, + usage: None, blacklist: HashSet::new(), bin_name: None, } @@ -399,11 +402,13 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{ self } - fn print_usage(&self, more_info: bool) { + fn create_usage(&self) -> String { let tab = " "; - println!("USAGE:"); + let mut usage = String::with_capacity(75); + usage.push_str("USAGE:\n"); + usage.push_str(tab); if let Some(u) = self.usage_str { - println!("{}{}",tab,u); + usage.push_str(u); } else { let flags = !self.flags.is_empty(); let pos = !self.positionals_idx.is_empty(); @@ -433,7 +438,7 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{ } } else { None - }) + } ) .fold(String::new(), |acc, ref name| acc + &format!("{} ", name)[..]); let mut num_req_opts = 0; let req_opts = self.opts.values().filter_map(|x| if x.required || self.matched_reqs.contains(x.name) { @@ -448,29 +453,43 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{ format!("{} ",o.short.unwrap()) },o.name)); - print!("{}{} {} {} {} {}",tab, self.bin_name.clone().unwrap_or(self.name.clone()), - if flags {"[FLAGS]"} else {""}, - if opts { + // usage.push_str(tab); + usage.push_str(&self.bin_name.clone().unwrap_or(self.name.clone())[..]); + // usage.push_str(tab); + if flags { + usage.push_str(" [FLAGS]"); + } + if opts { + write!(&mut usage," {}", if num_req_opts != self.opts.len() && !req_opts.is_empty() { format!("[OPTIONS] {}", &req_opts[..]) } else if req_opts.is_empty() { "[OPTIONS]".to_owned() } else { - req_opts - } - } else { "".to_owned() }, - if pos { + req_opts + }); + } + if pos { + write!(&mut usage, " {}", if num_req_pos != self.positionals_idx.len() && !req_pos.is_empty() { format!("[POSITIONAL] {}", &req_pos[..]) } else if req_pos.is_empty() { - "[POSITIONAL]".to_owned() + "[POSITIONAL]".to_owned() } else { - req_pos - } - } else {"".to_owned()}, - if subcmds {"[SUBCOMMANDS]"} else {""}); + req_pos + } ); + } + if subcmds { + usage.push_str(" [SUBCOMMANDS]"); + } } + usage.shrink_to_fit(); + usage + } + + fn print_usage(&self, more_info: bool) { + print!("{}",self.create_usage()); if more_info { println!("\nFor more information try --help"); } @@ -689,6 +708,7 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{ } } } + matches.usage = Some(self.create_usage()); self.get_matches_from(&mut matches, &mut it ); matches diff --git a/src/args/argmatches.rs b/src/args/argmatches.rs index 7ef523da3d6..70177c12e1c 100644 --- a/src/args/argmatches.rs +++ b/src/args/argmatches.rs @@ -64,7 +64,8 @@ pub struct ArgMatches<'a> { pub flags: HashMap<&'a str, FlagArg>, pub opts: HashMap<&'a str, OptArg>, pub positionals: HashMap<&'a str, PosArg>, - pub subcommand: Option>> + pub subcommand: Option>>, + pub usage: Option } impl<'a> ArgMatches<'a> { @@ -83,7 +84,8 @@ impl<'a> ArgMatches<'a> { flags: HashMap::new(), opts: HashMap::new(), positionals: HashMap::new(), - subcommand: None + subcommand: None, + usage: None } } @@ -264,4 +266,20 @@ impl<'a> ArgMatches<'a> { ("", None) } + /// Returns a slice of the default usage for the *top level parent App only* + /// + /// + /// # Example + /// + /// ```no_run + /// # use clap::{App, Arg, SubCommand}; + /// # let app_matches = App::new("myapp").subcommand(SubCommand::new("test")).get_matches(); + /// println!(matches.usage()); + /// ``` + pub fn usage(&self) -> Option<&str> { + if let Some( ref u ) = self.usage { + return Some(&u[..]); + } + None + } } \ No newline at end of file