feat(ArgMatches): add method to get default usage string

This commit is contained in:
Kevin K 2015-04-09 17:46:24 -04:00
parent 64e539280e
commit 02462150ca
2 changed files with 56 additions and 18 deletions

View file

@ -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<String>,
bin_name: Option<String>
}
@ -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

View file

@ -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<Box<SubCommand<'a>>>
pub subcommand: Option<Box<SubCommand<'a>>>,
pub usage: Option<String>
}
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
}
}