Closed tzakharko closed 2 years ago
@tzakharko hi thanks for the issue, would you be willing to send us a pr that makes this change? thanks
@Dylan-DPC I am afraid I am neither familiar enough with the Clap codebase nor with Rust to figure out the best way of doing it at the moment. I suppose one would hav etc decouple the output settings from the Error
struct, so it's probably not trivial.
I have opened the issue mainly because @pksunkara asked me to do so in a discussion thread. I understand this might be lower priority.
@tzakharko that's fine we will mentor you if needed. It's a good way to learn rust :D
@Dylan-DPC fair enough :) I will have a look, but I won't be able to allocate any time for this short term. I will put it on my agenda and let's keep the issue open for now.
I imagine this would be much trickier to implement, but how do folks feel about allowing arbitrary Write
targets for this? Instead of naming bespoke outputs, users could instead provide an impl Write
. This would still support selecting stdout
or stderr
via std::io::stdout
and std::io::stderr
, which both emit impl Write
types.
I've been working on a CLI tool that incorporates paging by conditionally targeting a paging child process or the configured terminal. bat
does something similar. AFAICT, it is not possible to use clap
's generated help text, options, and subcommands with such a paging mechanism and the only alternative would be to define help options and subcommands manually and use App::print{_long}_help
by hand. For example, you'll notice that both nym
and bat
automatically page their output except for help text, which is written to stdout
by clap
.
@tzakharko I believe clap is only reporting --help
and --version
to stdout. Those are explicit user actions. What would be the use case of passing those flags but still programmatically processing the output so you don't want it on stdout?
@olson-sean-k some quick thoughts on this
I am leaning towards rejecting this until we have a use case that explains why output going to stdout for explicit user interactions is interfering with an applications behavior (especially since there are cases where people want their -V
to be parseable).
This isn't to make a statement of whether we want this or not but because we are specifically looking at finding ways to trim the API of clap which also raises the bar for changes that expand the API.
An example use case is if a command is leveraging shell hooks to cd
when certain subcommands are used. The shell hook is only capable of capturing stdout
, due to limitations of the shell language, but the program otherwise tries to behave like a normal shell command with subcommands and flags.
I've not dealt with shell hooks to cd
. Could you elaborate more on the relationhip between the command and the hook and how a call to --help
or --version
wouldn't be processed correctly?
The shell hook is the main interface to the program, so the user would be expected to run prog --help
.
The shell hook passes all arguments through to the program and captures the contents of stdout
. (There is no way to swap stdout
and stderr
).
The automatic --help
and --version
flags print to stdout
, which is incorrectly interpreted as a directory to attempt to change to, and as a result are not shown to the user in the intended way.
function prog() {
result="$(prog_bin $@)" # Run `prog_bin` with the supplied arguments, capturing stdout but leaving stderr to the tty
[[ -n $result ]] && cd $result # If anything was printed to stdout, `cd` to it.
}
@epage Sorry for replying late and thanks for following this through. I have to be quite honest that I do not remember what was the actual problem that made me open this issue, it was two years ago and couldn't find any relevant notes. I think it had to do with the fact that some outputs did not pipe correctly when uses as part of a complex unix command sequence, but we are not currently using these tools so I guess that's all I can say.
At any rate, I would be fine with this being closed, as it is not a critical issue for us at the moment. But I gather from the comments that some other folks are running into real-world issues, so maybe they will have a better motivating example.
It seems that version 4.0
of clap
is on the horizon, so I wanted to bump this again in hopes that some of the dust has settled since this issue was first opened.
I am leaning towards rejecting this until we have a use case that explains why output going to stdout for explicit user interactions is interfering with an applications behavior
I believe the use case described in my previous comment has precedent and falls into this category. It is not possible to (comprehensively) implement cli --pager=target
if clap
cannot be configured to write to (more) arbitrary targets. Redirecting standard I/O streams does not completely solve I/O routing for a CLI application.
We wouldn't be able to detect coloring support. ... the user can do it and tell us what coloring to do
I feel that clap
should probably allow users to configure styled (colored) output in all cases. Arbitrary outputs could interact with the styling APIs, with something like a RenderTarget
that provides styling information as well as the impl Write
target.
Regarding styling, perhaps detection and styles could be feature gated. When the styling feature is enabled, RenderTarget::default
could try to detect styling support and use it where available while simply disabling it when the feature is not enabled. In both of these cases the default impl Write
target could be std::io::stdout
.
Any thoughts on something like this post-4.0
? Thanks for taking a look!
I believe the use case described in https://github.com/clap-rs/clap/issues/1788#issuecomment-845496010 has precedent and falls into this category. It is not possible to (comprehensively) implement cli --pager=target if clap cannot be configured to write to (more) arbitrary targets. Redirecting standard I/O streams does not completely solve I/O routing for a CLI application.
Requiring clap to take on lifetimes again to pass around the streams would be a no-go.
For you printing everything yourself, my hope is that with the new styling API I plan to focus on for 4.x, we'll be able to provide you a render_help
function that returns a type that will output ANSI escape codes (currently, we only allow access to output stripped of escape codes)
Regarding styling, perhaps detection and styles could be feature gated.
Any thoughts on something like this post-4.0? Thanks for taking a look!
My priority is going to be on the issues currently targeting 4.x. People are free to come up with a design for additional APIs but the further from my priorities, the less attention it will get. There will also be a high bar for impact on all users.
Describe your use case
Some command line tools are used exclusively as components within larger configurations and their
stdout
might be piped into other tools.Clap
is currently hard-coded inError::use_stderr()
to print certain messages (e.g. the help block) tostdout
, which might lead to surprising behavior.Describe the solution you'd like
It would be nice to have an option in configuring the behavior of
Error:: use_stderr()
. maybe a configuration option inApp
that would override the default behavior, e.g.:Alternatives, if applicable
I am currently intercepting all
clap
messages and printing them manually like this:but it feels a bit hacky to me.