Skip to content

Add an env_prefix derive option for a consistent prefix for environment variables #3221

@gibfahn

Description

@gibfahn

Maintainer's notes

  • Proposed fix is to add a Command::next_env_prefix and Arg::env_prefix and is modeled after help_heading
    • Command::next_env_prefixapplies to all future Args and is set during .arg()
    • An explicit Arg::env_prefix takes precedence over Command::next_env_prefix
    • Derives will need to capture and restore state
    • Better than display_order and DeriveDisplayOrder argument positioning #1807 will allow derives to change the Command::next_env_prefix part-way through struct definition
    • Either we generate the env variables during _build (env will internally need to be a Cow), leaving help generation and env variable look up unchanged or we do it on lookup/display

Please complete the following tasks

  • I have searched the discussions
  • I have searched the existing issues

Clap Version

v3.0.0-rc.8

Describe your use case

This was previously discussed in TeXitoi/structopt#370.

Basically the request is to be able to allow a specific prefix to be appended to all #[clap(env)] derived environment variable names.

Describe the solution you'd like

Before:

#[derive(Parser)]
pub struct Opts {
    #[clap(long, env = "FOO_CONFIG_DIR")]
    pub config_dir: String,
    #[clap(long, env = "FOO_TEMP_DIR")]
    pub temp_dir: String,
    #[clap(long, env = "FOO_CACHE_DIR")]
    pub cache_dir: String,
    #[clap(long)]
    pub isolated: bool
}

After:

#[derive(Parser)]
#[clap(env_prefix)]
pub struct Opts {
    #[clap(long, env)]
    pub config_dir: String,
    #[clap(long, env)]
    pub temp_dir: String,
    #[clap(long, env)]
    pub cache_dir: String,
    #[clap(long)]
    pub isolated: bool
}

(where a custom prefix could be set by #[clap(env_prefix="foo")], but the default was the #[clap(name)])

Alternatives, if applicable

I don't think there's an alternative solution to manually setting the environment variable for every option that needs it.

There was a suggestion in the above issue about allowing this to be calculated via a function vs a string literal, but I can't think of a good use-case for it, so it seems unnecessary for this feature.

Additional Context

Examples from the above issue:

rust-analyzer looks for RA_LOG var, rustc looks for RUSC_LOG var, sccache looks for SCCACHE_ENDPOINT, SCCACHE_CACHE_SIZE, SCCACHE_REDIS and other....

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-deriveArea: #[derive]` macro APIC-enhancementCategory: Raise on the bar on expectationsE-mediumCall for participation: Experience needed to fix: Medium / intermediate

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions