-
-
Notifications
You must be signed in to change notification settings - Fork 78
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
switch from termcolor
to anstream
and anstyle
#737
Conversation
Linking #724 |
src/check_release.rs
Outdated
@@ -157,39 +158,35 @@ pub(super) fn run_check_release( | |||
let mut results_with_errors = vec![]; | |||
for (semver_query, time_to_decide, results) in all_results { | |||
config | |||
.log_verbose(|config| { | |||
.log_verbose(|_| { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the callbacks will need config anymore, so we could (1) make the methods log_*
take only &self
if we go with this architecture, (2) move the shell_print_*
methods to (associated) functions, and/or (3) remove the config
parameter from the closure argument
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be a good idea to let the config
variable carry explicit Box<dyn std::io::Write>
fields for stdout
and stderr
, and pass them here.
Imagine a user is using cargo-semver-checks
as a library. It's a bit strange if a library is printing to it's parent program's stdout/stderr, right? It would be nice if the parent program could configure where and how it wants the output printed, and then decide by itself whether to actually put it on stdout/stderr.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am a little bit lost. When someone uses cargo-semver-checks
as a library, they won't configure a separate stdout/stderr for logging, right? Do you mean running a child process?
@epage IIRC, anstyle
takes care of parallel printing, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Imagine a user is using
cargo-semver-checks
as a library. It's a bit strange if a library is printing to it's parent program's stdout/stderr, right? It would be nice if the parent program could configure where and how it wants the output printed, and then decide by itself whether to actually put it on stdout/stderr.
On main
branch, I don't think there's a mechanism to set the output streams programmatically. Is that something we want? I can add it in this PR, or a different one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
they won't configure a separate stdout/stderr for logging
Not configure separate stdout/stderr, just give them the option to redirect the cargo-semver-checks-as-library output to a buffer (or drop it altogether) instead of having it printed to their app's stdout/stderr.
I can add it in this PR, or a different one.
Not worth adding here, let's optimize this PR for being easy to review and merge. We can add that in the future, I just wanted to not remove that option from us. If this PR can make sure to print to the configured Box<dyn Write>
values (or whatever other representation is best), we can handle the rest later.
src/main.rs
Outdated
/// auto (based on whether output is a tty), and never | ||
/// | ||
/// Default is auto (use colors if output is a TTY, otherwise don't use colors) | ||
#[arg(value_enum, long = "color")] | ||
color_choice: Option<termcolor::ColorChoice>, | ||
color_choice: Option<ColorChoice>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For some reason, this breaks the tests now because the --color
arg is now incompatible with the check-release
subcommand, which is a little weird because it's basically the same enum, and I didn't change anything in the CheckRelease
struct besides that. I can sort out the issue later, but if something jumps out at you for why this doesn't work suddenly, I'd love to know.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have very little experience with the clap
crate, so I don't see anything obvious why this might be broken and I'm not sure I'd be much help on this.
Perhaps @pksunkara might have an idea though!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To me, it looks like the test failures are related to removal of CARGO_TERM_COLOR
logic unless I am mistaken.
src/rustdoc_cmd.rs
Outdated
cmd.arg("--color=always"); | ||
} | ||
|
||
// TODO |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We used to only add the --color=always
flag if stderr
was a tty, but we can respect the user's color choice more now if we want. I can also easily revert to the earlier behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since cargo
uses anstyle
too, I think you can just forward the color value instead of the match
here. @epage WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not that familiar with anstream
, anstyle
, or clap
, so I imagine @pksunkara's feedback will be more valuable here -- sorry!
let color_choice = match std::env::var("CARGO_TERM_COLOR").as_deref() { | ||
Ok("always") => Some(ColorChoice::Always), | ||
Ok("alwaysansi") => Some(ColorChoice::AlwaysAnsi), | ||
Ok("auto") => Some(ColorChoice::Auto), | ||
Ok("never") => Some(ColorChoice::Never), | ||
Ok(_) | Err(..) => None, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cargo
itself uses CARGO_TERM_COLOR
and the --color
flag: https://doc.rust-lang.org/cargo/reference/config.html#termcolor
As a cargo extension with plans to merge into cargo one day (#61), it would massively simplify things if we did the same thing. So I'd prefer to keep this mechanism available. (If there's no alwaysansi
option in the new crate, that can go since cargo doesn't use it either.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would ask @epage what he thinks about the CARGO_TERM_COLOR
support since he works on both cargo
and anstyle
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd be a bit surprised if anstyle
got first-party support for a cargo-specific way to configure color, but perhaps there's going to be an anstyle-cargo
crate :) But I'm sure epage is super busy, and I feel reasonably confident it's safe to keep CARGO_TERM_COLOR
support here unless he chimes in to say otherwise.
src/main.rs
Outdated
/// auto (based on whether output is a tty), and never | ||
/// | ||
/// Default is auto (use colors if output is a TTY, otherwise don't use colors) | ||
#[arg(value_enum, long = "color")] | ||
color_choice: Option<termcolor::ColorChoice>, | ||
color_choice: Option<ColorChoice>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have very little experience with the clap
crate, so I don't see anything obvious why this might be broken and I'm not sure I'd be much help on this.
Perhaps @pksunkara might have an idea though!
/// Set the termcolor [color choice](termcolor::ColorChoice). | ||
/// If `None`, the use of colors will be determined automatically by | ||
/// the `CARGO_TERM_COLOR` env var and tty type of output. | ||
pub fn with_color_choice(&mut self, choice: Option<termcolor::ColorChoice>) -> &mut Self { | ||
self.color_choice = choice; | ||
self | ||
} | ||
|
||
/// Get the current color choice. If `None`, the use of colors is determined | ||
/// by the `CARGO_TERM_COLOR` env var and whether the output is a tty | ||
#[inline] | ||
pub fn color_choice(&self) -> Option<&termcolor::ColorChoice> { | ||
self.color_choice.as_ref() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any particular reason why we aren't letting library users set the color choice programmatically anymore?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We give more preference to the color setting when someone runs a program. Even if someone uses this library, they would have their own color setting mechanism in their binary using anstyle
and this library would automatically respect it. Therefore, we don't need these settings anymore in the library.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if that third-party program doesn't use anstyle
for its own styling needs, though? Surely the answer can't be "use anstyle
or you can't set cargo-semver-checks
color options" right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use
anstyle
or you can't setcargo-semver-checks
color options
I might be completely off here, but I think that's intended and the main reason for anstyle
repo to exist. They can use ColorChoice::write_global
to control the colors in every library they use and do not have to call each individual library's with_color_choice()
.
And they won't be adding a new dependency, because they already depend on cargo-semver-checks
which in turn depends on colorchoice
anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are making a solid case for using anstyle
. If our downstream user is already directly using anstyle
, the ColorChoice::write_global()
approach is what we want them to be able to use.
But I don't see the case for removing the ability to set colors via with_color_choice()
. If our downstream user is not already directly depending on anstyle
, it feels wrong to tell them "if you want to control color output in cargo-semver-checks
then you better add a dependency and configure it there." Even if it isn't a new dependency in the sense of "was it already being compiled," it's still one more thing they have to maintain and keep in sync.
As an example of the burden of needing such a dependency, thus far I've had to deal with more than one case of major version mismatches between a dependency A
's dependency B
, and our directly-added version of B
that we solely added so we could properly interact with A
. Let's not impose the same maintenance burden on our users, and let's offer a smooth path for configuring colors even if they don't already use anstyle
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense. I didn't think of it like that. My bad.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No worries at all! It was a good discussion and cargo-semver-checks
is better off for it.
src/check_release.rs
Outdated
@@ -157,39 +158,35 @@ pub(super) fn run_check_release( | |||
let mut results_with_errors = vec![]; | |||
for (semver_query, time_to_decide, results) in all_results { | |||
config | |||
.log_verbose(|config| { | |||
.log_verbose(|_| { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be a good idea to let the config
variable carry explicit Box<dyn std::io::Write>
fields for stdout
and stderr
, and pass them here.
Imagine a user is using cargo-semver-checks
as a library. It's a bit strange if a library is printing to it's parent program's stdout/stderr, right? It would be nice if the parent program could configure where and how it wants the output printed, and then decide by itself whether to actually put it on stdout/stderr.
let color_choice = match std::env::var("CARGO_TERM_COLOR").as_deref() { | ||
Ok("always") => Some(ColorChoice::Always), | ||
Ok("alwaysansi") => Some(ColorChoice::AlwaysAnsi), | ||
Ok("auto") => Some(ColorChoice::Auto), | ||
Ok("never") => Some(ColorChoice::Never), | ||
Ok(_) | Err(..) => None, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would ask @epage what he thinks about the CARGO_TERM_COLOR
support since he works on both cargo
and anstyle
.
/// Set the termcolor [color choice](termcolor::ColorChoice). | ||
/// If `None`, the use of colors will be determined automatically by | ||
/// the `CARGO_TERM_COLOR` env var and tty type of output. | ||
pub fn with_color_choice(&mut self, choice: Option<termcolor::ColorChoice>) -> &mut Self { | ||
self.color_choice = choice; | ||
self | ||
} | ||
|
||
/// Get the current color choice. If `None`, the use of colors is determined | ||
/// by the `CARGO_TERM_COLOR` env var and whether the output is a tty | ||
#[inline] | ||
pub fn color_choice(&self) -> Option<&termcolor::ColorChoice> { | ||
self.color_choice.as_ref() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We give more preference to the color setting when someone runs a program. Even if someone uses this library, they would have their own color setting mechanism in their binary using anstyle
and this library would automatically respect it. Therefore, we don't need these settings anymore in the library.
src/main.rs
Outdated
@@ -112,6 +111,29 @@ fn exit_on_error<T>(log_errors: bool, inner: impl Fn() -> anyhow::Result<T>) -> | |||
} | |||
} | |||
|
|||
/// helper enum to derive [`clap::ValueEnum`] on [`anstream::ColorChoice`] | |||
#[derive(Copy, Clone, Debug, PartialEq, Eq)] | |||
pub(crate) struct ColorChoice(pub(crate) anstream::ColorChoice); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would recommend using https://github.com/rust-cli/anstyle/tree/main/crates/colorchoice-clap instead of writing your own.
src/main.rs
Outdated
if let Some(color_choice) = args.check_release.color_choice { | ||
color_choice.0.write_global(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If using colorchoice-clap
, this can be changed to something like:
if let Some(color_choice) = args.check_release.color_choice { | |
color_choice.0.write_global(); | |
} | |
args.check_release.color_choice.write_global(); |
src/rustdoc_cmd.rs
Outdated
cmd.arg("--color=always"); | ||
} | ||
|
||
// TODO |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since cargo
uses anstyle
too, I think you can just forward the color value instead of the match
here. @epage WDYT?
src/check_release.rs
Outdated
@@ -157,39 +158,35 @@ pub(super) fn run_check_release( | |||
let mut results_with_errors = vec![]; | |||
for (semver_query, time_to_decide, results) in all_results { | |||
config | |||
.log_verbose(|config| { | |||
.log_verbose(|_| { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am a little bit lost. When someone uses cargo-semver-checks
as a library, they won't configure a separate stdout/stderr for logging, right? Do you mean running a child process?
@epage IIRC, anstyle
takes care of parallel printing, right?
src/main.rs
Outdated
/// auto (based on whether output is a tty), and never | ||
/// | ||
/// Default is auto (use colors if output is a TTY, otherwise don't use colors) | ||
#[arg(value_enum, long = "color")] | ||
color_choice: Option<termcolor::ColorChoice>, | ||
color_choice: Option<ColorChoice>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To me, it looks like the test failures are related to removal of CARGO_TERM_COLOR
logic unless I am mistaken.
it still breaks tests, i think it's an issue with how we handle the `check-release` subcommand
src/main.rs
Outdated
@@ -291,12 +288,12 @@ struct CheckRelease { | |||
verbosity: clap_verbosity_flag::Verbosity<clap_verbosity_flag::InfoLevel>, | |||
|
|||
/// Whether to print colors to the terminal: | |||
/// always, alwaysansi (always use only ANSI color codes), | |||
/// always, always-ansi (always use only ANSI color codes), | |||
/// auto (based on whether output is a tty), and never | |||
/// | |||
/// Default is auto (use colors if output is a TTY, otherwise don't use colors) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can remove the docstring on this field.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting, why remove it? Will clap automatically display the --color
options in --help
if we do that?
The --color
options are non-obvious and I think it's important to have a help string in the CLI for them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The colorchoice_clap
has a docstring for the color
field that gets picked up by clap when used with flatten
. It looks something like the following:
--color <WHEN> Controls when to use color [default: auto] [possible values: auto, always, never]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah neat! This wasn't obvious to me from the colorchoice_clap
docs, so perhaps best to leave a regular (non-doc) comment next to the field indicating we expect the built-in --help
text there.
re @pksunkara: I switched to the |
I would recommend moving the color flag entirely to |
src/main.rs
Outdated
@@ -291,12 +288,12 @@ struct CheckRelease { | |||
verbosity: clap_verbosity_flag::Verbosity<clap_verbosity_flag::InfoLevel>, | |||
|
|||
/// Whether to print colors to the terminal: | |||
/// always, alwaysansi (always use only ANSI color codes), | |||
/// always, always-ansi (always use only ANSI color codes), | |||
/// auto (based on whether output is a tty), and never | |||
/// | |||
/// Default is auto (use colors if output is a TTY, otherwise don't use colors) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting, why remove it? Will clap automatically display the --color
options in --help
if we do that?
The --color
options are non-obvious and I think it's important to have a help string in the CLI for them.
src/main.rs
Outdated
/// Whether to print colors to the terminal: | ||
/// always, alwaysansi (always use only ANSI color codes), | ||
/// always, always-ansi (always use only ANSI color codes), | ||
/// auto (based on whether output is a tty), and never | ||
/// | ||
/// Default is auto (use colors if output is a TTY, otherwise don't use colors) | ||
#[arg(value_enum, long = "color")] | ||
color_choice: Option<termcolor::ColorChoice>, | ||
#[command(flatten)] | ||
color_choice: colorchoice_clap::Color, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might be confused here, but colorchoice_clap::Color
seems like it might not have alwaysansi
as an option, whereas anstream::ColorChoice
does. Do we want to use anstream::ColorChoice
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC, AlwaysAnsi
is skipped in clap
because Always
always resolves to it except when running on a Windows console. And when someone's using a Windows console, they wouldn't want to use AlwaysAnsi
option anyway.
Code for reference: https://github.com/rust-cli/anstyle/blob/ed1a598cc2c3b84483c6058a982d045f7f7aecfc/crates/anstream/src/auto.rs#L110-L126
src/main.rs
Outdated
@@ -291,12 +288,12 @@ struct CheckRelease { | |||
verbosity: clap_verbosity_flag::Verbosity<clap_verbosity_flag::InfoLevel>, | |||
|
|||
/// Whether to print colors to the terminal: | |||
/// always, alwaysansi (always use only ANSI color codes), | |||
/// always, always-ansi (always use only ANSI color codes), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make sure that the string shown here is an exact match for what the CLI accepts. So if we're making this change, --color=always-ansi
must work. I believe that previously, --color=alwaysansi
was required and always-ansi
was not accepted.
This commit moves |
src/config.rs
Outdated
/// in [`ColorChoice::write_global`] if you are using the `anstream` crate. | ||
/// | ||
/// See also [`GlobalConfig::set_out_color_choice`] and [`GlobalConfig::set_color_choice`] | ||
pub fn set_err_color_choice(&mut self, choice: ColorChoice) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pksunkara unless I'm missing something, there seems to be no way to change a specific stream's color choice after initialization. If this is true, we can either do what I did to set the colors, which is a little hacky, or we can take an owned self
and call the method like with_{out,err,}color_choice
.
src/config.rs
Outdated
/// Sets the stderr output stream | ||
/// | ||
/// Defaults to the global color choice setting in [`ColorChoice::global`]. | ||
/// Call [`GlobalConfig::set_err_color_choice`] to customize the color choice |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Sets the stderr output stream | |
/// | |
/// Defaults to the global color choice setting in [`ColorChoice::global`]. | |
/// Call [`GlobalConfig::set_err_color_choice`] to customize the color choice | |
/// Sets the stdout output stream | |
/// | |
/// Defaults to the global color choice setting in [`ColorChoice::global`]. | |
/// Call [`GlobalConfig::set_out_color_choice`] to customize the color choice |
a bit of copy-pasta here
Squashed commit of the following: commit 59a3a7f Author: m <[email protected]> Date: Fri Apr 12 15:15:42 2024 -0700 add some simple tests commit 03b2494 Author: m <[email protected]> Date: Fri Apr 12 14:16:55 2024 -0700 current work
Added some simple tests. Some things to consider:
|
also @obi1kenobi: do we want to read the |
Excellent highly-nuanced questions. I love the care with which you're approaching this!
You've clearly thought about this a fair bit. What do you think we should do?
I'm inclined to say on the binary side, not the library side. What do you think? My reasoning is that when we're running as a binary, we're a cargo extension. When we're running as a library, we're a part of some other program that has its own assumptions and responsibilities, and which may be surprised if |
- document that `ColorChoice::write_global` must be called before `GlobalConfig::new` or `set_std{err,out}` - add tests for `GlobalConfig` - add parsing for `CARGO_TERM_COLOR` env var in binary part of crate
Awesome! I think it makes a lot of sense to use bools to set color. Also, I realized that, unlike I also agree that it makes more sense to read the env var in the binary part of the crate, so I implemented that, and now the tests pass (though it seems like with rustdoc json v29, I still won't get passing CI 🙃 (this time though, it's not the fault of the PR)). Thanks for all your help, and let me know if you want something to change! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everything LGTM
The nightly step is blocked pending the release of a new version of an upstream crate that I'm not a maintainer of, but it's a non-required build step so we can merge without it being green. I'll go over the code one more time now -- thank you both for all the effort you've put in here! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks in pretty good shape, just some polish items left. Thanks for putting this together! I'm excited to merge it.
The change in how library consumers might set color options is relatively significant, and deserves to be noted in the release notes. Would you mind helping me out and writing up a small migration guide as a comment in this PR before we merge it? All it needs to show is a couple of code examples along the lines of "if you did X in the previous version, in the new version you'll need to do Y instead."
use std::{collections::BTreeMap, sync::Arc, time::Instant}; | ||
|
||
use anstyle::{AnsiColor, Color, Reset, Style}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/lib.rs
Outdated
pub fn check_release(&self) -> anyhow::Result<Report> { | ||
let mut config = GlobalConfig::new().set_level(self.log_level); | ||
// we don't want to set auto if the choice is not set because it would overwrite | ||
// the value if the CARGO_TERM_COLOR env var read in GlobalConfig::new() if it is set | ||
if let Some(choice) = self.color_choice { | ||
config = config.set_color_choice(choice); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the color-setting functionality now on GlobalConfig
instead of on this type, how would a user of the library go about configuring color settings?
Unless I'm missing something, it seems that the GlobalConfig
is created and then immediately used here without any opportunity for the consumer of the library to use its color-setting methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a bit of a big (and semver-breaking) change, but would you be opposed to taking a GlobalConfig
(or a &mut GlobalConfig
) as a parameter to the check_release
function? Otherwise, it's possible, but we would need to double our configuration API - have one call for Check
and one call for GlobalConfig
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, we can do that. Do you think taking it by value or by &mut
is better?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made it take &mut
to leave the option open for a library user to run multiple Check
s
src/main.rs
Outdated
cli_choice.write_global(); | ||
// if it is still auto (i.e., user passed `--color=auto` or omitted the flag entirely), | ||
// we check the env var. otherwise, the flag takes precedence over whatever the env var is |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a note here about what the expected value of cli_choice
is if the flag was not present in the CLI invocation?
This unconditional cli_choice.write_global()
call is tripping me up here a bit since I'm unfamiliar with the underlying API's assumptions. It's usually a good idea to leave an explanatory note for our future selves (or for other future maintainers) rather than relying on everyone to read and recall upstream libraries' docs each time.
src/rustdoc_cmd.rs
Outdated
// if config.is_stderr_tty() { | ||
// cmd.arg("--color=always"); | ||
// } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// if config.is_stderr_tty() { | |
// cmd.arg("--color=always"); | |
// } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated this so it reads the current stderr configuration. Let me know if the documentation isn't clear or if this is too "hacky". Right now, we don't have a way to read the current color choice in our config API, but I can add that if we want it. However, because we write the child process stderr (which has colors) to our AutoStream
that strips colors if we indicate our preference for that, we will get the correct color preferences here. I can add a test here for if you think that's a good idea.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you don't mind writing a test, I'd love to have one! AutoStream
's behavior is nice but a bit surprising, so it'd be nice to have a test we can point future readers of this code to (including me).
It would be especially useful if in the future we yet again switch libraries, and the next library's stream implementation doesn't do this kind of magically-automatic ANSI code stripping.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a little more nebulous than I thought - it works when RustdocCommand::silence
is true, but when it is false, since we just forward the rustdoc err stream to stderr (actual tty stderr, not GlobalConfig::stderr
), we're not currently using the configured stderr for the rustdoc progress stream. We can redirect it using Command::spawn
and a thread that acts as a pipe between the child process stderr and our stderr if we want. Do you think a library user would expect this behavior? That is, would they expect the rustdoc progress output to go through the cargo-semver-checks
' configured stderr. I'm leaning towards yes, but it will add more complexity to the function because we have to use threads.
By the way, thanks for all your patience and great feedback on this PR!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think definitely not in this PR, and possibly not at all. We'll have to solicit feedback from users, and I'm wary of taking on even more technical complexity when we aren't sure users want the feature it produces.
Maybe open an issue describing the concern and the nature of the decision point here, and we revisit it in the future. Otherwise this PR for switching to a different stream coloring library is going to end up being a giant revamp of everything, and it'll take forever to merge.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, thank you for all the care and skill you are investing into cargo-semver-checks! It's my pleasure to help as best I can, and it's lovely to work with someone as thoughtful and kind as you!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it, that makes a lot of sense. I just re-added the color flag on our rustdoc invocation to respect the color preferences. Do you still want a test for this? It's not using any of the anstream
magic anymore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we aren't materially changing the code here, it's fine as it was without a test.
But if you have a clever idea for how to elegantly write a test for something that previously wasn't tested, I wouldn't say no!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the generate_rustdoc
function is too long and does too much to be able to effectively test something like this. It might be worth breaking it up in the future so we can write tests that make these behaviors more visible and guaranteed. Since the behavior stays the same here, I don't know if it's worth writing the test in this already-big PR, but I'd be open to refactoring and writing it in the future.
Co-authored-by: Predrag Gruevski <[email protected]>
src/main.rs
Outdated
// if the --color flag is explicitly set to something other than `auto`, | ||
// this takes precedence over the environment variable, so we write that | ||
if cli_choice != ColorChoice::Auto { | ||
cli_choice.write_global(); | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't an explicitly passed --color=auto
CLI flag override whatever CARGO_TERM_COLOR
is set to? I find this note a bit surprising.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good point, and in playing around with cargo
, that's the behavior it does. The colorchoice_clap
crate doesn't currently distinguish between an explicitly-passed --color=auto
and no color flag entirely. I will try right now if it works with an Option<color_choice::Color>
but if that doesn't play nice with #[clap(flatten)]
, we might have to move back to the bespoke color configuration flag that I previously had.
Relevant tangent: In doing this, I discovered that the environment variable actually takes precedence over the CLI flag, unlike what we had previously done. It's only been a little while since I added the --color
flag in general; do we want to match cargo's behavior and read the environment variable over the flag?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh that's interesting! Yes, let's match cargo's behavior then -- and ideally, let's document this if at all possible, since I imagine other people might find this a bit unexpected as well.
If we don't document it, I'd be shocked if we don't get a "bug report" on that behavior in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, little bit of a false alarm - it looks like cargo help
checks the CARGO_TERM_COLOR
env var but not the --color
flag - may be a tiny bug in cargo itself. When I test with CARGO_TERM_COLOR=env cargo check --color=cli
, cli
overrides env
if it is set. However, you're right that we still need to distinguish an explicit --color=auto
from one that's not set - I'll work on that.
we had to make our own colorchoice clap handler because the mixin doesn't work with Option<_>
Migration GuideMajor changes
New features
Minor changes
Does this look good? Did I miss anything? |
this also cleans up lines that get unnecessarily changed in the diff
termcolor
to anstream
and anstyle
termcolor
to anstream
and anstyle
Looks great! I tweaked the Rust code formatting in the release notes a bit, to make it a bit easier to read without scrolling. Question on method naming: it seems like we now have a |
The |
Ah bummer, it must have snuck in. If you're open to fixing it up, separate PR would be best. Let's merge this one :) |
Thanks for all the work you did to make this happen! It wasn't the easiest PR to merge, and to be honest I was dreading doing the work a bit 😅 I really appreciate all the care and attention you put into making this happen -- it was very helpful! |
Of course, and thanks again for all your help. Glad to finally have a finished version of it! |
This is a draft PR to solicit feedback on the direction I'm going, what crates to use, and how we want the architecture to look like.
One of the biggest changes in moving to
anstream
is thatstdout
andstderr
are global, so we don't need to store them inGlobalConfig
; in fact, the library part of the crate doesn't need to be aware of the user's color choice, it just needs to use theanstream::print!
and related macros.Question: Is this a positive change for the crate? In the binary version, we configure our own color preference with
anstream::ColorChoice::write_global
, and another crate that uses thesemver-checks
library would do the same.There's also the question of how to style the colors. Right now, I'm using the basic
anstyle
crate, but a lot of people seem to be usingowo-colors
. These are both runtime-styling, and we could also opt for a compile-time styler withcolor-print
or maybe evenanstyle-termcolors
(but I haven't checked out that last one too much yet).This also changes our environment variable interface a little. Instead of using the
CARGO_TERM_COLOR
variable as we were previously,anstream
automatically sets colors based on theCCOLOR
,CCOLOR_FORCE
andNOCOLOR
environment variables in theanstyle-query
crate.Question: Do we want to also support the
CARGO_TERM_COLOR
variable, or is this enough?I haven't written a lot of new tests or documentation yet - I want to see how we feel about these changes.
I'm super open to feedback and changing direction at this point - I want to get input in this PR.