mirror of
https://github.com/clap-rs/clap
synced 2024-12-14 23:02:31 +00:00
feat(apps): add ability to display additional help info after auto-gen'ed help msg
This commit is contained in:
parent
e9e774558e
commit
65cc259e45
2 changed files with 40 additions and 15 deletions
53
src/app.rs
53
src/app.rs
|
@ -38,7 +38,7 @@ use args::{ FlagBuilder, OptBuilder, PosBuilder};
|
||||||
///
|
///
|
||||||
/// // Your pogram logic starts here...
|
/// // Your pogram logic starts here...
|
||||||
/// ```
|
/// ```
|
||||||
pub struct App<'a, 'v, 'ab, 'u, 'ar> {
|
pub struct App<'a, 'v, 'ab, 'u, 'h, 'ar> {
|
||||||
// The name displayed to the user when showing version and help/usage information
|
// The name displayed to the user when showing version and help/usage information
|
||||||
name: String,
|
name: String,
|
||||||
// A string of author(s) if desired. Displayed when showing help/usage information
|
// A string of author(s) if desired. Displayed when showing help/usage information
|
||||||
|
@ -47,6 +47,8 @@ pub struct App<'a, 'v, 'ab, 'u, 'ar> {
|
||||||
version: Option<&'v str>,
|
version: Option<&'v str>,
|
||||||
// A brief explaination of the program that gets displayed to the user when shown help/usage information
|
// A brief explaination of the program that gets displayed to the user when shown help/usage information
|
||||||
about: Option<&'ab str>,
|
about: Option<&'ab str>,
|
||||||
|
// Additional help information
|
||||||
|
more_help: Option<&'h str>,
|
||||||
// A list of possible flags
|
// A list of possible flags
|
||||||
flags: BTreeMap<&'ar str, FlagBuilder<'ar>>,
|
flags: BTreeMap<&'ar str, FlagBuilder<'ar>>,
|
||||||
// A list of possible options
|
// A list of possible options
|
||||||
|
@ -54,7 +56,7 @@ pub struct App<'a, 'v, 'ab, 'u, 'ar> {
|
||||||
// A list of positional arguments
|
// A list of positional arguments
|
||||||
positionals_idx: BTreeMap<u8, PosBuilder<'ar>>,
|
positionals_idx: BTreeMap<u8, PosBuilder<'ar>>,
|
||||||
// A list of subcommands
|
// A list of subcommands
|
||||||
subcommands: BTreeMap<String, App<'a, 'v, 'ab, 'u, 'ar>>,
|
subcommands: BTreeMap<String, App<'a, 'v, 'ab, 'u, 'h, 'ar>>,
|
||||||
needs_long_help: bool,
|
needs_long_help: bool,
|
||||||
needs_long_version: bool,
|
needs_long_version: bool,
|
||||||
needs_short_help: bool,
|
needs_short_help: bool,
|
||||||
|
@ -71,7 +73,7 @@ pub struct App<'a, 'v, 'ab, 'u, 'ar> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
|
impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
||||||
/// Creates a new instance of an application requiring a name (such as the binary). The name
|
/// Creates a new instance of an application requiring a name (such as the binary). The name
|
||||||
/// will be displayed to the user when they request to print version or help and usage
|
/// will be displayed to the user when they request to print version or help and usage
|
||||||
/// information. The name should not contain spaces (hyphens '-' are ok).
|
/// information. The name should not contain spaces (hyphens '-' are ok).
|
||||||
|
@ -84,11 +86,12 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
|
||||||
/// let prog = App::new("myprog")
|
/// let prog = App::new("myprog")
|
||||||
/// # .get_matches();
|
/// # .get_matches();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn new<'n>(n: &'n str) -> App<'a, 'v, 'ab, 'u, 'ar> {
|
pub fn new<'n>(n: &'n str) -> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
|
||||||
App {
|
App {
|
||||||
name: n.to_owned(),
|
name: n.to_owned(),
|
||||||
author: None,
|
author: None,
|
||||||
about: None,
|
about: None,
|
||||||
|
more_help: None,
|
||||||
version: None,
|
version: None,
|
||||||
flags: BTreeMap::new(),
|
flags: BTreeMap::new(),
|
||||||
opts: BTreeMap::new(),
|
opts: BTreeMap::new(),
|
||||||
|
@ -121,7 +124,7 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
|
||||||
/// .author("Kevin <kbknapp@gmail.com>")
|
/// .author("Kevin <kbknapp@gmail.com>")
|
||||||
/// # .get_matches();
|
/// # .get_matches();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn author(mut self, a: &'a str) -> App<'a, 'v, 'ab, 'u, 'ar> {
|
pub fn author(mut self, a: &'a str) -> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
|
||||||
self.author = Some(a);
|
self.author = Some(a);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -137,11 +140,28 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
|
||||||
/// .about("Does really amazing things to great people")
|
/// .about("Does really amazing things to great people")
|
||||||
/// # .get_matches();
|
/// # .get_matches();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn about(mut self, a: &'ab str) -> App<'a, 'v, 'ab, 'u, 'ar> {
|
pub fn about(mut self, a: &'ab str) -> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
|
||||||
self.about = Some(a);
|
self.about = Some(a);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adds additional help information to be displayed in addition to auto-generated help. This
|
||||||
|
/// information is displayed **after** the auto-generated help information. This additional
|
||||||
|
/// help is often used to describe how to use the arguments, or caveats to be noted.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// # use clap::App;
|
||||||
|
/// # let app = App::new("myprog")
|
||||||
|
/// .more_help("Does really amazing things to great people")
|
||||||
|
/// # .get_matches();
|
||||||
|
/// ```
|
||||||
|
pub fn more_help(mut self, h: &'h str) -> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
|
||||||
|
self.more_help = Some(h);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Sets a string of the version number to be displayed when displaying version or help
|
/// Sets a string of the version number to be displayed when displaying version or help
|
||||||
/// information.
|
/// information.
|
||||||
///
|
///
|
||||||
|
@ -153,7 +173,7 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
|
||||||
/// .version("v0.1.24")
|
/// .version("v0.1.24")
|
||||||
/// # .get_matches();
|
/// # .get_matches();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn version(mut self, v: &'v str) -> App<'a, 'v, 'ab, 'u, 'ar> {
|
pub fn version(mut self, v: &'v str) -> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
|
||||||
self.version = Some(v);
|
self.version = Some(v);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -178,7 +198,7 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
|
||||||
/// .usage("myapp [-clDas] <some_file>")
|
/// .usage("myapp [-clDas] <some_file>")
|
||||||
/// # .get_matches();
|
/// # .get_matches();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn usage(mut self, u: &'u str) -> App<'a, 'v, 'ab, 'u, 'ar> {
|
pub fn usage(mut self, u: &'u str) -> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
|
||||||
self.usage_str = Some(u);
|
self.usage_str = Some(u);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -205,7 +225,7 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
|
||||||
/// .arg(Arg::from_usage("-c --config=[CONFIG] 'Optionally sets a configuration file to use'"))
|
/// .arg(Arg::from_usage("-c --config=[CONFIG] 'Optionally sets a configuration file to use'"))
|
||||||
/// # .get_matches();
|
/// # .get_matches();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn arg<'l, 'h, 'b, 'r>(mut self, a: Arg<'ar, 'ar, 'ar, 'ar, 'ar, 'ar>) -> App<'a, 'v, 'ab, 'u, 'ar> {
|
pub fn arg(mut self, a: Arg<'ar, 'ar, 'ar, 'ar, 'ar, 'ar>) -> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
|
||||||
if self.arg_list.contains(a.name) {
|
if self.arg_list.contains(a.name) {
|
||||||
panic!("Argument name must be unique, \"{}\" is already in use", a.name);
|
panic!("Argument name must be unique, \"{}\" is already in use", a.name);
|
||||||
} else {
|
} else {
|
||||||
|
@ -378,7 +398,7 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
|
||||||
/// Arg::with_name("input").index(1).help("the input file to use")])
|
/// Arg::with_name("input").index(1).help("the input file to use")])
|
||||||
/// # .get_matches();
|
/// # .get_matches();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn args(mut self, args: Vec<Arg<'ar, 'ar, 'ar, 'ar, 'ar, 'ar>>) -> App<'a, 'v, 'ab, 'u, 'ar> {
|
pub fn args(mut self, args: Vec<Arg<'ar, 'ar, 'ar, 'ar, 'ar, 'ar>>) -> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
|
||||||
for arg in args.into_iter() {
|
for arg in args.into_iter() {
|
||||||
self = self.arg(arg);
|
self = self.arg(arg);
|
||||||
}
|
}
|
||||||
|
@ -400,7 +420,7 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
|
||||||
/// .arg_from_usage("-c --conf=<config> 'Sets a configuration file to use'")
|
/// .arg_from_usage("-c --conf=<config> 'Sets a configuration file to use'")
|
||||||
/// # .get_matches();
|
/// # .get_matches();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn arg_from_usage(mut self, usage: &'ar str) -> App<'a, 'v, 'ab, 'u, 'ar> {
|
pub fn arg_from_usage(mut self, usage: &'ar str) -> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
|
||||||
self = self.arg(Arg::from_usage(usage));
|
self = self.arg(Arg::from_usage(usage));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -424,7 +444,7 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
|
||||||
/// <input> 'The input file to use'")
|
/// <input> 'The input file to use'")
|
||||||
/// # .get_matches();
|
/// # .get_matches();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn args_from_usage(mut self, usage: &'ar str) -> App<'a, 'v, 'ab, 'u, 'ar> {
|
pub fn args_from_usage(mut self, usage: &'ar str) -> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
|
||||||
for l in usage.lines() {
|
for l in usage.lines() {
|
||||||
self = self.arg(Arg::from_usage(l.trim()));
|
self = self.arg(Arg::from_usage(l.trim()));
|
||||||
}
|
}
|
||||||
|
@ -448,7 +468,7 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
|
||||||
/// // Additional subcommand configuration goes here, such as other arguments...
|
/// // Additional subcommand configuration goes here, such as other arguments...
|
||||||
/// # .get_matches();
|
/// # .get_matches();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn subcommand(mut self, subcmd: App<'a, 'v, 'ab, 'u, 'ar>) -> App<'a, 'v, 'ab, 'u, 'ar> {
|
pub fn subcommand(mut self, subcmd: App<'a, 'v, 'ab, 'u, 'h, 'ar>) -> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
|
||||||
if subcmd.name == "help" { self.needs_subcmd_help = false; }
|
if subcmd.name == "help" { self.needs_subcmd_help = false; }
|
||||||
self.subcommands.insert(subcmd.name.clone(), subcmd);
|
self.subcommands.insert(subcmd.name.clone(), subcmd);
|
||||||
self
|
self
|
||||||
|
@ -467,7 +487,7 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
|
||||||
/// SubCommand::new("debug").about("Controls debug functionality")])
|
/// SubCommand::new("debug").about("Controls debug functionality")])
|
||||||
/// # .get_matches();
|
/// # .get_matches();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn subcommands(mut self, subcmds: Vec<App<'a, 'v, 'ab, 'u, 'ar>>) -> App<'a, 'v, 'ab, 'u, 'ar> {
|
pub fn subcommands(mut self, subcmds: Vec<App<'a, 'v, 'ab, 'u, 'h, 'ar>>) -> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
|
||||||
for subcmd in subcmds.into_iter() {
|
for subcmd in subcmds.into_iter() {
|
||||||
self = self.subcommand(subcmd);
|
self = self.subcommand(subcmd);
|
||||||
}
|
}
|
||||||
|
@ -695,6 +715,11 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(h) = self.more_help {
|
||||||
|
println!("");
|
||||||
|
println!("{}", h);
|
||||||
|
}
|
||||||
|
|
||||||
self.exit(0);
|
self.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ impl<'a> SubCommand<'a> {
|
||||||
/// SubCommand::new("config")
|
/// SubCommand::new("config")
|
||||||
/// # ).get_matches();
|
/// # ).get_matches();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn new<'n, 'au, 'v, 'ab, 'u, 'ar>(name: &'n str) -> App<'au, 'v, 'ab, 'u, 'ar> {
|
pub fn new<'n, 'au, 'v, 'ab, 'u, 'h, 'ar>(name: &'n str) -> App<'au, 'v, 'ab, 'u, 'h, 'ar> {
|
||||||
App::new(name)
|
App::new(name)
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue