Values from environment variables #814
I suggest an option to
Here's how it would look like (simplified):
Arg::with_name("redis-url") .long("redis-url") .value_name("URL") .help("The URL to the Redis server to use.") // .default_from_env("REDIS_URL") .default_from_env_or("REDIS_URL", "redis://localhost:6379/0") .required(true); // --redis-url=URL The URL to the Redis server to use. // Defaults to the value of the REDIS_URL environment variable, or "redis://localhost:6379/0". // Without hardcoded default: // --redis-url=URL The URL to the Redis server to use. // Defaults to the value of the REDIS_URL environment variable.
If we had a
Note how I'm not advocating automatically determining environment variables to use, or loading any
With the advent of 12-factor apps that are commonly configured using environment variables, there's a lot of patterns and support for setting environment variables outside of a process and then reading them inside the program.
I've always felt that command line options are more discoverable and more usable from workstations, so I usually want them as well. Having to hook environment variables up with the command-line argument parser means a lot of work.
By adding this feature, it'll be much easier to have apps that can be configured with both environment variables and from the command line with just a single source of truth and parsing. I don't need to validate values in two different places, and I can model required values and conflicting values in one place.
This would motivate people to add a list of environment variables to their
It'll now be trivial to load a
There's #712, which seems to be the same suggestion, but larger in that it'll automatically determine and format certain things. Maybe I'm misunderstanding that issue's description. I apologize in that case.
One can also manually deal with this by reading the values and assigning them as defaults at runtime. Help messages can also be manually enhanced with such references. This still complicates the argument definitions a lot, however.
I'm a Rust beginner, but I'd be willing to come up with a proof of concept PR if that would be welcome.
The text was updated successfully, but these errors were encountered:
I love the detailed write up! You're correct, this relates to #712 (env vars) and also to #748 (config files). #712 is proposing allowing use env vars to act as an external argv where
I don't see any reason why your proposal shouldn't land, as it's a simple addition and something I've been wanting to add anyways. I do have a few questions first though.
How so? I could potentially see,
I don't think I'd want to add
Oh, thank you. ❤️
I wrote an example of how it could look like in the issue description:
I'm not interested in bike shedding this, but your suggestion with just
Isn't that just like it is today, when the value isn't provided? (
I'm not very experienced in this library yet, so I think I might've misunderstood the different options.
Maybe this should be a different approach, then. Just like with
Arg::with_name("redis-url") .long("redis-url") .value_name("URL") .help("The URL to the Redis server to use.") .env_fallback("REDIS_URL") // Read this env variable when not provided in ARGV .default_value("redis://localhost:6379/0") // Then use this default value if no env variable is set .required(true); Arg::with_name("email") .long("email") .value_name("EMAIL") .help("The author's email. Skip if you want to stay anonymous.") .env_fallback("USER_EMAIL") .required(false); // Not required, no default value. If it's not set in ARGV or ENV, it's just not set. // I'm not sure this can be more contrived now... // This just adds an option to "opt-out" of the ENV reading of --email, so to speak. Arg::with_name("no-email") .long("anonymous") .help("Force anonymous authorship.") .overrides_with("email");
[EDIT: I see now that I might've misunderstood
Some important comments from #1057
I made the appropriate comments in #1057 but I'll copy them here too, so everyone is tracking:
How would this work with derive approach? I'm looking at the docs but there is nothing there regarding derive https://docs.rs/clap/2.32.0/clap/struct.Arg.html#method.env
@doivosevic please use discussions for getting support when using the API.
btw you linked to the clap 2 documentation which only works with structopt. To use the built-in derive API that replaced structopt, be sure to look at the clap 3 documentation.
In the clap 3 derive reference it describes raw attributes which is what you want to read for how to use this. There has been a lot of confusion over this, so we have a discussion trying to find ways to improve the situation