-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
using global env var arg produces different help output #5673
Comments
The template wanted actual code and not a repo pointer, but in case it's useful, here's a repo that reproduces it: |
I'm able to reproduce the main behavior you mentioned #!/usr/bin/env nargo
---
[dependencies]
clap = { version = "4", features = ["derive", "env"] }
---
use clap::Args;
use clap::Parser;
use clap::Subcommand;
#[derive(Debug, Clone, Parser)]
struct Cli {
#[command(subcommand)]
command: MyCommands,
}
#[derive(Debug, Clone, Subcommand)]
enum MyCommands {
One(OneSubcommands),
}
#[derive(Debug, Clone, Args)]
struct OneSubcommands {
#[clap(env = "MY_ARG", global = true)]
my_arg: Option<String>,
#[command(subcommand)]
command: MySubcommand,
}
#[derive(Debug, Clone, Subcommand)]
enum MySubcommand {
Two,
}
fn main() {
let cli = Cli::parse();
eprintln!("{:?}", cli);
} $ MY_ARG= ./clap-5673.rs one
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.08s
Running `/home/epage/src/personal/cargo/target/debug/cargo -Zscript -Zmsrv-policy ./clap-5673.rs one`
warning: `package.edition` is unspecified, defaulting to `2021`
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.07s
Running `/home/epage/.cargo/target/1b/a671870fa36384/debug/clap-5673 one`
error: 'clap-5673 one' requires a subcommand but one was not provided
[subcommands: two, help]
Usage: clap-5673 one [MY_ARG] <COMMAND>
For more information, try '--help'. but I can't reproduce
#!/usr/bin/env nargo
---
[dependencies]
clap = { version = "4", features = ["derive", "env"] }
---
use clap::Args;
use clap::Parser;
use clap::Subcommand;
#[derive(Debug, Clone, Parser)]
struct Cli {
#[command(subcommand)]
command: MyCommands,
}
#[derive(Debug, Clone, Subcommand)]
enum MyCommands {
One(OneSubcommands),
}
#[derive(Debug, Clone, Args)]
struct OneSubcommands {
#[clap(env = "MY_ARG")]
my_arg: Option<String>,
#[command(subcommand)]
command: MySubcommand,
}
#[derive(Debug, Clone, Subcommand)]
enum MySubcommand {
Two,
}
fn main() {
let cli = Cli::parse();
eprintln!("{:?}", cli);
} $ MY_ARG= ./clap-5673.rs one
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.09s
Running `/home/epage/src/personal/cargo/target/debug/cargo -Zscript -Zmsrv-policy ./clap-5673.rs one`
warning: `package.edition` is unspecified, defaulting to `2021`
Compiling clap-5673 v0.0.0 (/home/epage/src/personal/dump)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.31s
Running `/home/epage/.cargo/target/1b/a671870fa36384/debug/clap-5673 one`
error: 'clap-5673 one' requires a subcommand but one was not provided
[subcommands: two, help]
Usage: clap-5673 one [MY_ARG] <COMMAND>
For more information, try '--help'. |
The help output comes from Assuming |
Sorry, I had confused a few variations that I had tried. If the argument is at the top level and global, as in: use clap::Args;
use clap::Parser;
use clap::Subcommand;
#[derive(Debug, Clone, Parser)]
struct Cli {
#[clap(env = "MY_ARG", global = true)]
my_arg: Option<String>,
#[command(subcommand)]
command: MyCommands,
}
#[derive(Debug, Clone, Subcommand)]
enum MyCommands {
One(OneSubcommands),
}
#[derive(Debug, Clone, Args)]
struct OneSubcommands {
#[command(subcommand)]
command: MySubcommand,
}
#[derive(Debug, Clone, Subcommand)]
enum MySubcommand {
Two,
}
fn main() {
let cli = Cli::parse();
eprintln!("{:?}", cli);
} Then I see:
and:
If I then make the argument non-global, like: use clap::Args;
use clap::Parser;
use clap::Subcommand;
#[derive(Debug, Clone, Parser)]
struct Cli {
#[clap(env = "MY_ARG")]
my_arg: Option<String>,
#[command(subcommand)]
command: MyCommands,
}
#[derive(Debug, Clone, Subcommand)]
enum MyCommands {
One(OneSubcommands),
}
#[derive(Debug, Clone, Args)]
struct OneSubcommands {
#[command(subcommand)]
command: MySubcommand,
}
#[derive(Debug, Clone, Subcommand)]
enum MySubcommand {
Two,
}
fn main() {
let cli = Cli::parse();
eprintln!("{:?}", cli);
} then I get the same behavior (full help output) regardless of whether the variable was specified:
I think I can see the series of decisions that results in this behavior (though I'm not sure what user errors you're talking about masking if it didn't do this). But I think it remains pretty surprising. |
Looks like we have #3572 covering this case (had mislabeled it so I missed it in my search), closing in favor of that.
Take $ cargo run -- one my_value
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.03s
Running `target/debug/clap-message one my_value`
error: 'clap-message one' requires a subcommand but one was not provided
[subcommands: two, help]
Usage: clap-message one [MY_ARG] <COMMAND>
For more information, try '--help'. If we showed help, we leave the user guessing as to what went wrong that caused the help to show up. This is one reason why the old which leaves us with whether the user explicitly setting an environment variable is more like |
Thanks for diving in!
👍 (but this one is currently still open, FYI)
Concretely, the help output would look like:
To me that's pretty clear:
I didn't know about this one and just looked it up. The docs only say that applies to a command with no arguments present. Are you saying it would apply here, too? Is it the default behavior or something that could be used to work around this? |
|
Please complete the following tasks
Rust Version
rustc 1.80.1 (3f5fd8dd4 2024-08-06)
Clap Version
4.5.15
Minimal reproducible code
Steps to reproduce the bug with the above code
MY_ARG= cargo run -- one
Actual Behaviour
It produces an explicit "error" message and no additional help output.
Expected Behaviour
This is what happens if you don't provide
MY_ARG
:Here you get more detailed help output.
Additional Context
If you make the environment variable non-global, you get the same behavior as if the env var wasn't specified.
If you don't provide an env var, but do provide the argument on the command line, you get the same behavior as if you'd provided the env var:
This behavior was particularly confusing because for the program where I found this, the env variable is an optional override that basically says which instance of a server you want the program to talk to. It's something that people might set in their environment and forget about and would think it would have no impact on how the program reports usage messages that don't have anything to do with that env var.
Debug Output
The text was updated successfully, but these errors were encountered: