Make sure you completed the following tasks
Code
This is an example with AppSettings::ArgRequiredElseHelp. This also occurs with AppSettings::SubcommandRequiredElseHelp.
[package]
name = "fake"
[dependencies]
clap = "3.0.0-beta.1"
use clap::{Arg, App, AppSettings, Error};
fn main() -> Result<(), Error> {
let cli = App::new("myapp")
.setting(AppSettings::ArgRequiredElseHelp)
.arg(
Arg::new("info")
.about("Provides more info")
.short('i')
.long("info"),
);
let matches = match cli.try_get_matches() {
Ok(matches) => matches,
Err(e)
if e.kind == clap::ErrorKind::HelpDisplayed
|| e.kind == clap::ErrorKind::VersionDisplayed
|| e.kind == clap::ErrorKind::MissingArgumentOrSubcommand =>
{
println!("{:?}", e.kind);
return Ok(());
}
Err(e) => {
return Err(e);
}
};
// We can find out whether or not debugging was turned on
if matches.is_present("info") {
println!("This is more info");
}
return Ok(())
}
Steps to reproduce the issue
- Run
cargo run
Version
- Rust:
rustc 1.45.0-nightly (a74d1862d 2020-05-14)
- Clap:
3.0.0-beta.1
Actual Behavior Summary
When I use AppSettings::ArgRequiredElseHelp or AppSettings::SubcommandRequiredElseHelp and do not provide an argument or subcommand the matches call returns an error of kind clap::ErrorKind::MissingArgumentOrSubcommand which is not documented or intuitive.
It is not intuitive because the ElseHelp suggests the result will match that of if the help is being displayed, which would be the clap::ErrorKind::HelpDisplayed kind.
Also, the clap::ErrorKind::MissingArgumentOrSubcommand error kind is treated as a failure and does not use stderr, as pointed out by @kinnison in rust-lang/rustup#2427 (comment), which is inconsistent with clap::ErrorKind::HelpDisplayed.
|
pub fn use_stderr(&self) -> bool { |
|
match self.kind { |
|
ErrorKind::HelpDisplayed | ErrorKind::VersionDisplayed => false, |
|
_ => true, |
|
} |
|
} |
Expected Behavior Summary
I think there's a few ways this might be improved.
-
Have this situation result in clap::ErrorKind::HelpDisplayed. This is intuitive, although maybe not as flexible.
-
Rename the error kind to clap::ErrorKind::MissingArgumentOrSubcommandHelpDisplayed to indicate clearly that this error is being returned to display the help, but to retain the flexibility.
-
Add docs indicating that the existing error is returned like HelpDisplayed and VersionDisplayed, so it's not a surprise when this error shows up.
-
Do 3, plus treat the error not as a failure.
Additional context
This issue is related to a bug in the latest version of rustup: rust-lang/rustup#2425. There is a fix for that bug in rustup rust-lang/rustup#2427 but the rustup maintainers want to confirm if this is a bug in clap.
In rustup v2 of clap is being used but this issue is relevant to both v2 and v3, and looks like it has existed for about 5 years since the ElseHelp settings were added.
Debug output
Compile clap with debug feature:
[dependencies]
clap = { version = "*", features = ["debug"] }
The output may be very long, so feel free to link to a gist or attach a text file
Debug Output
[ clap::build::app] App::_do_parse
[ clap::build::app] App::_build
[ clap::build::app] App::_derive_display_order:myapp
[ clap::build::app] App::_create_help_and_version
[ clap::build::app] App::_create_help_and_version: Building --help
[ clap::build::app] App::_create_help_and_version: Building --version
[ clap::build::app] App::_debug_asserts
[ clap::build::arg] Arg::_debug_asserts:
[ clap::build::arg] Arg::_debug_asserts:help
[ clap::build::arg] Arg::_debug_asserts:version
[ clap::parse::parser] Parser::get_matches_with
[ clap::parse::parser] Parser::_build
[ clap::parse::parser] Parser::_verify_positionals
[ clap::parse::parser] Parser::remove_overrides
[ clap::parse::validator] Validator::validate
[ clap::parse::parser] Parser::add_defaults
[ clap::parse::parser] Parser::color_help
[ clap::output::fmt] is_a_tty: stderr=true
[ clap::output::help] Help::new
[ clap::output::help] Help::write_help
[ clap::output::help] Help::write_default_help
[ clap::output::help] Help::write_bin_name
[ clap::output::help] Help::write_version
[ clap::output::usage] Usage::create_usage_no_title
[ clap::output::usage] Usage::create_help_usage; incl_reqs=true
[ clap::output::usage] Usage::get_required_usage_from: incls=[], matcher=false, incl_last=false
[ clap::output::usage] Usage::get_required_usage_from: ret_val=[]
[ clap::output::usage] Usage::needs_flags_tag
[ clap::output::usage] Usage::needs_flags_tag:iter: f=
[ clap::output::usage] groups_for_arg: name=info
[ clap::output::usage] Usage::needs_flags_tag:iter: [FLAGS] required
[ clap::output::usage] Usage::create_help_usage: usage=fake [FLAGS]
[ clap::output::help] Help::write_all_args
[ clap::output::help] Help::write_args
[ clap::output::help] should_show_arg: use_long=false, arg=
[ clap::output::help] Help::write_args: Current Longest...2
[ clap::output::help] Help::write_args: New Longest...6
[ clap::output::help] should_show_arg: use_long=false, arg=help
[ clap::output::help] Help::write_args: Current Longest...6
[ clap::output::help] Help::write_args: New Longest...6
[ clap::output::help] should_show_arg: use_long=false, arg=version
[ clap::output::help] Help::write_args: Current Longest...6
[ clap::output::help] Help::write_args: New Longest...9
[ clap::output::help] Help::write_arg
[ clap::output::help] Help::short
[ clap::output::help] Help::long
[ clap::output::help] Help::val: arg=
[ clap::output::help] Help::spec_vals: a=--info
[ clap::output::help] Help::val: Has switch...
[ clap::output::help] Yes
[ clap::output::help] Help::val: force_next_line...false
[ clap::output::help] Help::val: nlh...false
[ clap::output::help] Help::val: taken...21
[ clap::output::help] val: help_width > (width - taken)...18 > (120 - 21)
[ clap::output::help] Help::val: longest...9
[ clap::output::help] Help::val: next_line...
[ clap::output::help] No
[ clap::output::help] Help::write_nspaces!: num=7
[ clap::output::help] Help::help
[ clap::output::help] Help::help: Next Line...false
[ clap::output::help] Help::help: Too long...
[ clap::output::help] No
[ clap::output::help] Help::write_arg
[ clap::output::help] Help::short
[ clap::output::help] Help::long
[ clap::output::help] Help::val: arg=help
[ clap::output::help] Help::spec_vals: a=--help
[ clap::output::help] Help::val: Has switch...
[ clap::output::help] Yes
[ clap::output::help] Help::val: force_next_line...false
[ clap::output::help] Help::val: nlh...false
[ clap::output::help] Help::val: taken...21
[ clap::output::help] val: help_width > (width - taken)...23 > (120 - 21)
[ clap::output::help] Help::val: longest...9
[ clap::output::help] Help::val: next_line...
[ clap::output::help] No
[ clap::output::help] Help::write_nspaces!: num=7
[ clap::output::help] Help::help
[ clap::output::help] Help::help: Next Line...false
[ clap::output::help] Help::help: Too long...
[ clap::output::help] No
[ clap::output::help] Help::write_arg
[ clap::output::help] Help::short
[ clap::output::help] Help::long
[ clap::output::help] Help::val: arg=version
[ clap::output::help] Help::spec_vals: a=--version
[ clap::output::help] Help::val: Has switch...
[ clap::output::help] Yes
[ clap::output::help] Help::val: force_next_line...false
[ clap::output::help] Help::val: nlh...false
[ clap::output::help] Help::val: taken...21
[ clap::output::help] val: help_width > (width - taken)...26 > (120 - 21)
[ clap::output::help] Help::val: longest...9
[ clap::output::help] Help::val: next_line...
[ clap::output::help] No
[ clap::output::help] Help::write_nspaces!: num=4
[ clap::output::help] Help::help
[ clap::output::help] Help::help: Next Line...false
[ clap::output::help] Help::help: Too long...
[ clap::output::help] No
MissingArgumentOrSubcommand
Make sure you completed the following tasks
Code
This is an example with
AppSettings::ArgRequiredElseHelp. This also occurs withAppSettings::SubcommandRequiredElseHelp.Steps to reproduce the issue
cargo runVersion
rustc 1.45.0-nightly (a74d1862d 2020-05-14)3.0.0-beta.1Actual Behavior Summary
When I use
AppSettings::ArgRequiredElseHelporAppSettings::SubcommandRequiredElseHelpand do not provide an argument or subcommand the matches call returns an error of kindclap::ErrorKind::MissingArgumentOrSubcommandwhich is not documented or intuitive.It is not intuitive because the
ElseHelpsuggests the result will match that of if the help is being displayed, which would be theclap::ErrorKind::HelpDisplayedkind.Also, the
clap::ErrorKind::MissingArgumentOrSubcommanderror kind is treated as a failure and does not use stderr, as pointed out by @kinnison in rust-lang/rustup#2427 (comment), which is inconsistent withclap::ErrorKind::HelpDisplayed.clap/src/errors.rs
Lines 387 to 392 in 7127653
Expected Behavior Summary
I think there's a few ways this might be improved.
Have this situation result in
clap::ErrorKind::HelpDisplayed. This is intuitive, although maybe not as flexible.Rename the error kind to
clap::ErrorKind::MissingArgumentOrSubcommandHelpDisplayedto indicate clearly that this error is being returned to display the help, but to retain the flexibility.Add docs indicating that the existing error is returned like HelpDisplayed and VersionDisplayed, so it's not a surprise when this error shows up.
Do 3, plus treat the error not as a failure.
Additional context
This issue is related to a bug in the latest version of rustup: rust-lang/rustup#2425. There is a fix for that bug in rustup rust-lang/rustup#2427 but the rustup maintainers want to confirm if this is a bug in clap.
In rustup v2 of clap is being used but this issue is relevant to both v2 and v3, and looks like it has existed for about 5 years since the ElseHelp settings were added.
Debug output
Compile clap with
debugfeature:The output may be very long, so feel free to link to a gist or attach a text file
Debug Output