Expand description
§Environment Variables
Like Clap, an option or positional argument can fall back to an environment variable when it is absent from the command line.
Add env = "NAME" to its #[arg(...)] attribute, or a bare env to use the upper-cased field name (workers → WORKERS):
use getargs_derive::GetArgs;
#[derive(GetArgs)]
struct Server<'a> {
#[arg(long, env = "SERVER_HOST", default_value = "127.0.0.1")]
host: &'a str,
#[arg(short, long, env = "SERVER_PORT")]
port: u16,
#[arg(long, env)]
workers: Option<u32>,
}
let vars = [("SERVER_PORT", "8080"), ("SERVER_HOST", "0.0.0.0")];
let lookup = |name: &str| vars.iter().find(|(key, _)| *key == name).map(|(_, value)| *value);
let server = Server::from_args_with_env(["--host", "localhost"].into_iter(), lookup)?;
assert_eq!(server.host, "localhost");
assert_eq!(server.port, 8080);
assert_eq!(server.workers, None);The value is taken from the command line first, then from the environment variable, then from the default.
An Option<T> field is None only when it is absent from both the command line and the environment, and a field without a default is reported as missing only when the variable is not set either.
The variable is only read when the argument is absent from the command line, and its value is used as-is for &str fields, parsed with ValueEnum::from_value for value_enum fields, and otherwise parsed with FromStr, with the same value validation as command-line values.
If it does not parse, parse returns Error::InvalidValue with the argument name followed by the variable, e.g. "--port <PORT> [env: SERVER_PORT]".
env is not supported on flags. This is a Clap-inspired subset: Clap’s hide_env, hide_env_values and boolean parsing of environment values for flags are not supported.
§Reading the Process Environment
A struct with at least one env field, or that flattens other structs, gets two more methods, parse_with_env and from_args_with_env, taking a lookup function FnMut(&str) -> Option<&'a str> called with a variable name.
They work in no_std builds: the lookup can read a configuration block, a bootloader command line, or a test fixture.
With the std feature of this crate, parse and from_args read the process environment with std::env::var:
[dependencies]
getargs-derive = { version = "0.1", features = ["std"] }use getargs_derive::GetArgs;
#[derive(GetArgs)]
struct Server {
#[arg(short, long, env = "GETARGS_DERIVE_GUIDE_PORT", default_value_t = 80)]
port: u16,
}
let server = Server::from_args(["-p", "8080"].into_iter())?;
assert_eq!(server.port, 8080);Without the std feature, calling parse or from_args on such a struct is a compile error naming the feature; use parse_with_env or from_args_with_env instead.
Structs without env fields are not affected by the feature.
The process environment holds owned strings, while parsed arguments borrow for the lifetime 'a of the command line.
To keep &'a str fields and the value in Error::InvalidValue working without copying the command line, parse and from_args leak each environment value they read
(Box::leak), once per variable read, and only when the argument is absent from the command line.
This is negligible when parsing once at startup; when parsing repeatedly, prefer parse_with_env with your own lookup.
Variables whose value is not valid Unicode are treated as unset.
In the generated help, the variable is shown as [env: NAME=], before the default, as in Clap. The value is not shown, as the help is a compile-time constant. See Generated Help.
§Compile-Time Diagnostics
The macro reports a compile error, pointing at the offending attribute or field, for:
envvalues that are not a string literal, are empty, or contain=or NUL characters, andenvgiven more than once on the same field;envon a flag;- calling
parseorfrom_argson a struct withenvfields without thestdfeature.