fix(help): Subcommand display order respects Command::next_display_order

Previous behavior:
- They'd be sorted by default
- They'd derive display order if `DeriveDisplayOrder` was set
  - This could be set recursively
- The initial display order value for subcommands was 0

New behavior:
- Sorted order is derived by default
- Sorting is turned on by `cmd.next_display_order(None)`
  - This is not recursive, it must be set on each level
- The display order incrementing is mixed with arguments
  - This does make it slightly more difficult to predict
This commit is contained in:
Ed Page 2022-07-22 14:58:27 -05:00
parent ce8ebe1ccc
commit 389ff4ff21
17 changed files with 117 additions and 106 deletions

View file

@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- `ErrorKind::EmptyValue` replaced with `ErrorKind::InvalidValue`
- `ErrorKind::UnrecognizedSubcommand` replaced with `ErrorKind::InvalidSubcommand`
- `arg!` now sets `ArgAction::SetTrue`, `ArgAction::Count`, `ArgAction::Set`, or `ArgAction::Append` as appropriate
- *(help)* Subcommand display order respects `Command::next_display_order` instead of `DeriveDisplayOrder` and using its own initial display order value
- *(env)* Parse `--help` and `--version` like any `ArgAction::SetTrue` flag
- *(derive)* `subcommand_required(true).arg_required_else_help(true)` is set instead of `SubcommandRequiredElseHelp`

View file

@ -112,8 +112,8 @@ OPTIONS:
SUBCOMMANDS:
add
help Print this message or the help of the given subcommand(s)
remove
help Print this message or the help of the given subcommand(s)
```

View file

@ -16,11 +16,11 @@ OPTIONS:
-h, --help Print help information
SUBCOMMANDS:
add adds things
clone Clones repos
help Print this message or the help of the given subcommand(s)
push pushes things
add adds things
stash
help Print this message or the help of the given subcommand(s)
$ git-derive help
git
@ -33,11 +33,11 @@ OPTIONS:
-h, --help Print help information
SUBCOMMANDS:
add adds things
clone Clones repos
help Print this message or the help of the given subcommand(s)
push pushes things
add adds things
stash
help Print this message or the help of the given subcommand(s)
$ git-derive help add
git-add
@ -89,10 +89,10 @@ OPTIONS:
-m, --message <MESSAGE>
SUBCOMMANDS:
push
pop
apply
help Print this message or the help of the given subcommand(s)
pop
push
$ git-derive stash push -h
git-stash-push

View file

@ -14,11 +14,11 @@ OPTIONS:
-h, --help Print help information
SUBCOMMANDS:
add adds things
clone Clones repos
help Print this message or the help of the given subcommand(s)
push pushes things
add adds things
stash
help Print this message or the help of the given subcommand(s)
$ git help
git
@ -31,11 +31,11 @@ OPTIONS:
-h, --help Print help information
SUBCOMMANDS:
add adds things
clone Clones repos
help Print this message or the help of the given subcommand(s)
push pushes things
add adds things
stash
help Print this message or the help of the given subcommand(s)
$ git help add
git-add
@ -87,10 +87,10 @@ OPTIONS:
-m, --message <MESSAGE>
SUBCOMMANDS:
push
pop
apply
help Print this message or the help of the given subcommand(s)
pop
push
$ git stash push -h
git-stash-push

View file

@ -35,8 +35,8 @@ OPTIONS:
--install <install> Install hardlinks for all subcommands in path
APPLETS:
true does nothing successfully
false does nothing unsuccessfully
help Print this message or the help of the given subcommand(s)
true does nothing successfully
```

View file

@ -47,9 +47,9 @@ OPTIONS:
-V, --version Print version information
SUBCOMMANDS:
help Print this message or the help of the given subcommand(s)
query -Q --query Query the package database.
sync -S --sync Synchronize packages.
help Print this message or the help of the given subcommand(s)
$ pacman -S -h
pacman-sync

View file

@ -16,8 +16,8 @@ OPTIONS:
-V, --version Print version information
SUBCOMMANDS:
help Print this message or the help of the given subcommand(s)
test does testing things
help Print this message or the help of the given subcommand(s)
```

View file

@ -16,8 +16,8 @@ OPTIONS:
-V, --version Print version information
SUBCOMMANDS:
help Print this message or the help of the given subcommand(s)
test does testing things
help Print this message or the help of the given subcommand(s)
```

View file

@ -402,7 +402,13 @@ impl<'help> Command<'help> {
#[inline]
#[must_use]
pub fn subcommand<S: Into<Self>>(mut self, subcmd: S) -> Self {
self.subcommands.push(subcmd.into());
let mut subcmd = subcmd.into();
if let Some(current_disp_ord) = self.current_disp_ord.as_mut() {
let current = *current_disp_ord;
subcmd.disp_ord.get_or_insert(current);
*current_disp_ord = current + 1;
}
self.subcommands.push(subcmd);
self
}
@ -426,8 +432,12 @@ impl<'help> Command<'help> {
I: IntoIterator<Item = T>,
T: Into<Self>,
{
for subcmd in subcmds.into_iter() {
self.subcommands.push(subcmd.into());
let subcmds = subcmds.into_iter();
let (lower, _) = subcmds.size_hint();
self.subcommands.reserve(lower);
for subcmd in subcmds {
self = self.subcommand(subcmd);
}
self
}
@ -4378,9 +4388,6 @@ To change `help`s short, call `cmd.arg(Arg::new(\"help\")...)`.",
{
a.disp_ord.make_explicit();
}
for (i, sc) in &mut self.subcommands.iter_mut().enumerate() {
sc.disp_ord.get_or_insert(i);
}
}
for sc in &mut self.subcommands {
sc._derive_display_order();

View file

@ -291,3 +291,74 @@ fn prefer_user_help_in_subcommand_with_derive_order() {
false,
);
}
#[test]
fn subcommand_sorted_display_order() {
static SUBCMD_ALPHA_ORDER: &str = "test 1
USAGE:
test [SUBCOMMAND]
OPTIONS:
-h, --help Print help information
-V, --version Print version information
SUBCOMMANDS:
a1 blah a1
b1 blah b1
help Print this message or the help of the given subcommand(s)
";
let app_subcmd_alpha_order = Command::new("test")
.version("1")
.next_display_order(None)
.subcommands(vec![
Command::new("b1")
.about("blah b1")
.arg(Arg::new("test").short('t')),
Command::new("a1")
.about("blah a1")
.arg(Arg::new("roster").short('r')),
]);
utils::assert_output(
app_subcmd_alpha_order,
"test --help",
SUBCMD_ALPHA_ORDER,
false,
);
}
#[test]
fn subcommand_derived_display_order() {
static SUBCMD_DECL_ORDER: &str = "test 1
USAGE:
test [SUBCOMMAND]
OPTIONS:
-h, --help Print help information
-V, --version Print version information
SUBCOMMANDS:
b1 blah b1
a1 blah a1
help Print this message or the help of the given subcommand(s)
";
let app_subcmd_decl_order = Command::new("test").version("1").subcommands(vec![
Command::new("b1")
.about("blah b1")
.arg(Arg::new("test").short('t')),
Command::new("a1")
.about("blah a1")
.arg(Arg::new("roster").short('r')),
]);
utils::assert_output(
app_subcmd_decl_order,
"test --help",
SUBCMD_DECL_ORDER,
false,
);
}

View file

@ -43,8 +43,8 @@ OPTIONS:
-V, --version Print version information
SUBCOMMANDS:
help Print this message or the help of the given subcommand(s)
subcmd tests subcommands
help Print this message or the help of the given subcommand(s)
";
static SC_NEGATES_REQS: &str = "prog 1.0
@ -62,8 +62,8 @@ OPTIONS:
-V, --version Print version information
SUBCOMMANDS:
help Print this message or the help of the given subcommand(s)
test
help Print this message or the help of the given subcommand(s)
";
static ARGS_NEGATE_SC: &str = "prog 1.0
@ -82,8 +82,8 @@ OPTIONS:
-V, --version Print version information
SUBCOMMANDS:
help Print this message or the help of the given subcommand(s)
test
help Print this message or the help of the given subcommand(s)
";
static AFTER_HELP: &str = "some text that comes before the help
@ -410,8 +410,8 @@ OPTIONS:
-V, --version Print version information
SUBCOMMANDS:
help Print this message or the help of the given subcommand(s)
test some
help Print this message or the help of the given subcommand(s)
";
static LAST_ARG_REQ: &str = "last 0.1
@ -445,8 +445,8 @@ OPTIONS:
-V, --version Print version information
SUBCOMMANDS:
help Print this message or the help of the given subcommand(s)
test some
help Print this message or the help of the given subcommand(s)
";
static HIDE_DEFAULT_VAL: &str = "default 0.1
@ -602,8 +602,8 @@ OPTIONS:
-h, --help Print help information
SUBCOMMANDS:
help Print this message or the help of the given subcommand(s)
sub short about sub
help Print this message or the help of the given subcommand(s)
";
fn setup() -> Command<'static> {

View file

@ -12,8 +12,8 @@ OPTIONS:
-V, --version Print version information
SUBCOMMANDS:
help Print this message or the help of the given subcommand(s)
test Some help [aliases: dongle, done]
help Print this message or the help of the given subcommand(s)
";
static INVISIBLE_ALIAS_HELP: &str = "clap-test 2.6
@ -26,37 +26,7 @@ OPTIONS:
-V, --version Print version information
SUBCOMMANDS:
help Print this message or the help of the given subcommand(s)
test Some help
";
static SUBCMD_ALPHA_ORDER: &str = "test 1
USAGE:
test [SUBCOMMAND]
OPTIONS:
-h, --help Print help information
-V, --version Print version information
SUBCOMMANDS:
a1 blah a1
b1 blah b1
help Print this message or the help of the given subcommand(s)
";
static SUBCMD_DECL_ORDER: &str = "test 1
USAGE:
test [SUBCOMMAND]
OPTIONS:
-h, --help Print help information
-V, --version Print version information
SUBCOMMANDS:
b1 blah b1
a1 blah a1
help Print this message or the help of the given subcommand(s)
";
@ -169,44 +139,6 @@ fn subcommand_multiple() {
);
}
#[test]
fn subcommand_display_order() {
let app_subcmd_alpha_order = Command::new("test").version("1").subcommands(vec![
Command::new("b1")
.about("blah b1")
.arg(Arg::new("test").short('t')),
Command::new("a1")
.about("blah a1")
.arg(Arg::new("roster").short('r')),
]);
utils::assert_output(
app_subcmd_alpha_order,
"test --help",
SUBCMD_ALPHA_ORDER,
false,
);
let app_subcmd_decl_order = Command::new("test")
.version("1")
.setting(clap::AppSettings::DeriveDisplayOrder)
.subcommands(vec![
Command::new("b1")
.about("blah b1")
.arg(Arg::new("test").short('t')),
Command::new("a1")
.about("blah a1")
.arg(Arg::new("roster").short('r')),
]);
utils::assert_output(
app_subcmd_decl_order,
"test --help",
SUBCMD_DECL_ORDER,
false,
);
}
#[test]
fn single_alias() {
let m = Command::new("myprog")

View file

@ -40,8 +40,8 @@ OPTIONS:
ARGS:
<output> Sets an optional output file
SUBCOMMANDS:
help Print this message or the help of the given subcommand(s)
test does testing things
help Print this message or the help of the given subcommand(s)
";
static SIMPLE_TEMPLATE: &str = "MyApp 1.0
@ -61,8 +61,8 @@ OPTIONS:
-V, --version Print version information
SUBCOMMANDS:
help Print this message or the help of the given subcommand(s)
test does testing things
help Print this message or the help of the given subcommand(s)
";
#[test]

View file

@ -14,6 +14,6 @@ OPTIONS:
--verbose log
SUBCOMMANDS:
help Print this message or the help of the given subcommand(s)
more
help Print this message or the help of the given subcommand(s)
"""

View file

@ -13,7 +13,7 @@ OPTIONS:
--verbose log
SUBCOMMANDS:
help Print this message or the help of the given subcommand(s)
more
help Print this message or the help of the given subcommand(s)
"""
stderr = ""

View file

@ -18,9 +18,9 @@ OPTIONS:
more log
SUBCOMMANDS:
help
Print this message or the help of the given subcommand(s)
more
help
Print this message or the help of the given subcommand(s)
"""
stderr = ""

View file

@ -18,9 +18,9 @@ OPTIONS:
more log
SUBCOMMANDS:
help
Print this message or the help of the given subcommand(s)
more
help
Print this message or the help of the given subcommand(s)
"""
stderr = ""