mirror of
https://github.com/clap-rs/clap
synced 2025-01-18 23:53:54 +00:00
feat(Subcommands): adds support for custom ordering in help messages
Allows custom ordering of subcommands within the help message. Subcommands with a lower value will be displayed first in the help message. This is helpful when one would like to emphasise frequently used subcommands, or prioritize those towards the top of the list. Duplicate values **are** allowed. Subcommands with duplicate display orders will be displayed in alphabetical order. **NOTE:** The default is 999 for all subcommands. ```rust use clap::{App, SubCommand}; let m = App::new("cust-ord") .subcommand(SubCommand::with_name("alpha") // typically subcommands are grouped // alphabetically by name. Subcommands // without a display_order have a value of // 999 and are displayed alphabetically with // all other 999 subcommands .about("Some help and text")) .subcommand(SubCommand::with_name("beta") .display_order(1) // In order to force this subcommand to appear *first* // all we have to do is give it a value lower than 999. // Any other subcommands with a value of 1 will be displayed // alphabetically with this one...then 2 values, then 3, etc. .about("I should be first!")) .get_matches_from(vec![ "cust-ord", "--help" ]); ``` The above example displays the following help message ``` cust-ord USAGE: cust-ord [FLAGS] [OPTIONS] FLAGS: -h, --help Prints help information -V, --version Prints version information SUBCOMMANDS: beta I should be first! alpha Some help and text ``` Closes #442
This commit is contained in:
parent
9803b51e79
commit
7d2a2ed413
3 changed files with 72 additions and 16 deletions
|
@ -10,6 +10,7 @@ pub struct AppMeta<'b> {
|
|||
pub usage_str: Option<&'b str>,
|
||||
pub usage: Option<String>,
|
||||
pub help_str: Option<&'b str>,
|
||||
pub disp_ord: usize,
|
||||
}
|
||||
|
||||
impl<'b> Default for AppMeta<'b> {
|
||||
|
@ -24,6 +25,7 @@ impl<'b> Default for AppMeta<'b> {
|
|||
usage: None,
|
||||
bin_name: None,
|
||||
help_str: None,
|
||||
disp_ord: 999,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -545,6 +545,56 @@ impl<'a, 'b> App<'a, 'b> {
|
|||
self
|
||||
}
|
||||
|
||||
/// Allows custom ordering of subcommands within the help message. Subcommands with a lower
|
||||
/// value will be displayed first in the help message. This is helpful when one would like to
|
||||
/// emphasise frequently used subcommands, or prioritize those towards the top of the list.
|
||||
/// Duplicate values **are** allowed. Subcommands with duplicate display orders will be
|
||||
/// displayed in alphabetical order.
|
||||
///
|
||||
/// **NOTE:** The default is 999 for all subcommands.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, SubCommand};
|
||||
/// let m = App::new("cust-ord")
|
||||
/// .subcommand(SubCommand::with_name("alpha") // typically subcommands are grouped
|
||||
/// // alphabetically by name. Subcommands
|
||||
/// // without a display_order have a value of
|
||||
/// // 999 and are displayed alphabetically with
|
||||
/// // all other 999 subcommands
|
||||
/// .about("Some help and text"))
|
||||
/// .subcommand(SubCommand::with_name("beta")
|
||||
/// .display_order(1) // In order to force this subcommand to appear *first*
|
||||
/// // all we have to do is give it a value lower than 999.
|
||||
/// // Any other subcommands with a value of 1 will be displayed
|
||||
/// // alphabetically with this one...then 2 values, then 3, etc.
|
||||
/// .about("I should be first!"))
|
||||
/// .get_matches_from(vec![
|
||||
/// "cust-ord", "--help"
|
||||
/// ]);
|
||||
/// ```
|
||||
///
|
||||
/// The above example displays the following help message
|
||||
///
|
||||
/// ```ignore
|
||||
/// cust-ord
|
||||
///
|
||||
/// USAGE:
|
||||
/// cust-ord [FLAGS] [OPTIONS]
|
||||
///
|
||||
/// FLAGS:
|
||||
/// -h, --help Prints help information
|
||||
/// -V, --version Prints version information
|
||||
///
|
||||
/// SUBCOMMANDS:
|
||||
/// beta I should be first!
|
||||
/// alpha Some help and text
|
||||
/// ```
|
||||
pub fn display_order(mut self, ord: usize) -> Self {
|
||||
self.p.meta.disp_ord = ord;
|
||||
self
|
||||
}
|
||||
|
||||
/// Prints the full help message to `io::stdout()` using a `BufWriter`
|
||||
///
|
||||
|
|
|
@ -1500,26 +1500,30 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b {
|
|||
}
|
||||
}
|
||||
if subcmds {
|
||||
let mut ord_m = VecMap::new();
|
||||
try!(write!(w, "\nSUBCOMMANDS:\n"));
|
||||
for (name, sc) in self.subcommands.iter()
|
||||
.filter(|s| !s.p.is_set(AppSettings::Hidden))
|
||||
.map(|s| (&s.p.meta.name[..], s))
|
||||
.collect::<BTreeMap<_, _>>() {
|
||||
try!(write!(w, "{}{}", tab, name));
|
||||
write_spaces!((longest_sc + 4) - (name.len()), w);
|
||||
if let Some(a) = sc.p.meta.about {
|
||||
if a.contains("{n}") {
|
||||
let mut ab = a.split("{n}");
|
||||
while let Some(part) = ab.next() {
|
||||
try!(write!(w, "{}\n", part));
|
||||
write_spaces!(longest_sc + 8, w);
|
||||
try!(write!(w, "{}", ab.next().unwrap_or("")));
|
||||
for sc in self.subcommands.iter().filter(|s| !s.p.is_set(AppSettings::Hidden)) {
|
||||
let btm = ord_m.entry(sc.p.meta.disp_ord).or_insert(BTreeMap::new());
|
||||
btm.insert(sc.p.meta.name.clone(), sc);
|
||||
}
|
||||
for (_, btm) in ord_m.into_iter() {
|
||||
for (name, sc) in btm.into_iter() {
|
||||
try!(write!(w, "{}{}", tab, name));
|
||||
write_spaces!((longest_sc + 4) - (name.len()), w);
|
||||
if let Some(a) = sc.p.meta.about {
|
||||
if a.contains("{n}") {
|
||||
let mut ab = a.split("{n}");
|
||||
while let Some(part) = ab.next() {
|
||||
try!(write!(w, "{}\n", part));
|
||||
write_spaces!(longest_sc + 8, w);
|
||||
try!(write!(w, "{}", ab.next().unwrap_or("")));
|
||||
}
|
||||
} else {
|
||||
try!(write!(w, "{}", a));
|
||||
}
|
||||
} else {
|
||||
try!(write!(w, "{}", a));
|
||||
}
|
||||
try!(write!(w, "\n"));
|
||||
}
|
||||
try!(write!(w, "\n"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue