Skip to content

Ability to control --help coloring using CLI args (e.g. --color) with derive syntax #6013

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

Open
2 tasks done
ivan-aksamentov opened this issue May 23, 2025 · 2 comments
Open
2 tasks done
Labels
A-help Area: documentation, including docs.rs, readme, examples, etc... C-enhancement Category: Raise on the bar on expectations S-waiting-on-design Status: Waiting on user-facing design to be resolved before implementing

Comments

@ivan-aksamentov
Copy link

Please complete the following tasks

Clap Version

4.4.2

Describe your use case

While clap can handle TTY and non-TTY outputs as well the environment variables co control color well, many applications also have additional CLI args for that, typically ``

Demonstrate --color has no effect on --help

use clap::{ArgEnum, Parser};

#[derive(Parser)]
struct Cli {
  #[clap(long, global = true, arg_enum)]
  color: Option<ColorOption>,
}

#[derive(Copy, Clone, ArgEnum)]
enum ColorOption {
  Auto,
  Always,
  Never,
}

fn main() {
  let args = Cli::parse(); // No way to account for color mode in `--help`
}

When running

cli --help --color=never

it prints color output, because clap does not know about my custom --color arg.

Describe the solution you'd like

It seems parsing and printing help should not be a monolithic function call. I'd like parsing and help (without re-implementing manually) to be distinct operations, such that I could insert color logic between them:

# Hypothetical code
let args = CLI::parse();
let is_colored = calculate_is_colored_based_on(&args, &env);
let style = if is_colored { Some(my_style) } else { None };
args.maybe_print_help(style); # need to handle subcommands too

I would also enjoy built-in --color=always|never|auto and --no-color (shortcut flag for --color=never), similarly to built-in --help. Clap already detects TTY and env vars, so half of the work is already done. Plus, the color args are virtually ubiquitous. Though not sure how the result would be exposed for usage (--help does not expose any result, because it does not have any).

Alternatives, if applicable

No response

Additional Context

No response

@ivan-aksamentov ivan-aksamentov added the C-enhancement Category: Raise on the bar on expectations label May 23, 2025
@epage epage added A-help Area: documentation, including docs.rs, readme, examples, etc... S-waiting-on-design Status: Waiting on user-facing design to be resolved before implementing labels May 26, 2025
@epage
Copy link
Member

epage commented May 26, 2025

Cargo's issue for this is rust-lang/cargo#9012

You can disable the built-in help and provide your own help flag (of type bool) and render the help directly. There are limitations and annoyances with this.

A more out-there approach could be

  1. Parse using try_parse
  2. If the error is "help", get a command-factory and re-parse with a custom help flag
  3. Check the --color flag and then decide how to render the error returned by try_parse

Overall, the some challenges for a more built-in way are:

  • Help is acted on immediately so we don't see any later flags
  • Help bypasses any other forms of validation
  • Help uses information from the parser for being rendered

Especially when it comes to the derive, the first two can mean that the derive can't populate the struct, preventing you from acting on it.

The last makes it more difficult to have this be a separate operation. There is also the convenience factor for users in having them combined. Splitting them might come at the risk of specialized APIs that might go counter to our efforts for shrinking and focusing the API for easier discoverability and better binary size.

@ivan-aksamentov
Copy link
Author

ivan-aksamentov commented May 26, 2025

You can disable the built-in help and provide your own help flag (of type bool) and render the help directly. There are limitations and annoyances with this.

In my particular case, I have many subcommands, and I am not sure how to handle help for all of them.

And I tried 2-step parsing, but this is where I got stuck:

Help is acted on immediately so we don't see any later flags

It seems if --help is present, --color is not being parsed.


There is also the convenience factor for users in having them combined.

Just to clarify, I am not proposing removing the combined function, but rather to expose some hooks to do things in userspace


might go counter to our efforts for shrinking and focusing the API

Fair enough


Thanks for detailed reply!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-help Area: documentation, including docs.rs, readme, examples, etc... C-enhancement Category: Raise on the bar on expectations S-waiting-on-design Status: Waiting on user-facing design to be resolved before implementing
Projects
None yet
Development

No branches or pull requests

2 participants