-
-
Notifications
You must be signed in to change notification settings - Fork 98
make it harder to emit any ANSI colors when color is set to off #161
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
base: main
Are you sure you want to change the base?
Conversation
5376b23 to
61b1f8d
Compare
|
This doesn't actually solve the same problem as the original solution. The reason that toggling colour is hard is because users will insert ANSI escape codes into things like error messages and label text, because that's what the crate encourages them to do. This change doesn't strip ANSI codes from the labels, and so most users will still see unintuitive results. This is why I think that a proper solution requires work at the level of the formatting API as mentioned in #160. |
|
I think if we go with what we taljked about in #160 the issue of inline ANSI codes would still persists it would just be an anti pattern at that case. like other than manually parsing there is simply nothing we can do to avoid a user putting an ANSI charchter into the stream. but other than that edge case I think the crate should not be adding them. so basically we would require users to not manually insert ansi colors ever. basically it seems there are 2 independent issues
but if the hope is to solve both on the same PR i can do that as well. i had some ideas for styling |
Yes, but I don't think that's a problem. If the user is explicitly choosing to shoot themselves in the foot, there's not all that much that we can do about it, especially if we're providing steel-capped boots.
Yep, that's the goal. And I think it's possible! Consider: struct Styled<T> { inner: T, style: &'static str }
// Arbitrary, extremely unlikely to appear in any real strings
const STYLE_START: &'static str = "\x1B\x0E";
const ELEM_START: &'static str = "\x1B\x17";
const STYLE_END &'static str = "\x1B\x0F";
impl<T: fmt::Display> fmt::Display for Styled<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{STYLE_START}{}{ELEM_START}{}{STYLE_END}", self.style, self.inner)
}
}When the user does, say, When rendering a diagnostic, Ariadne will search for these escape sequences. When it finds one, it looks up the style name in the 'stylesheet' provided for the relevant backend (like the ANSI CLI one) and apply the relevant ANSI escape sequences to the text. This has a few advantages:
|
|
@zesterer I think this would be best implemented in a way that doesn’t clash with It would also be nice if So instead of just having one big chunk of text, we would have something like: Vec<(Str: Display, S:ReportStyle)>Then later, somewhere in our code, we could do something like: for (text, style) in message {
let color = style
.get_color(&self.config)
.filter(|_| self.color);
write!("{}", text.fg(color))?;
}We would simply iterate and apply the styles. This is probably a performance regression compared to what currently exists, but I honestly can’t find a way to support styles that doesn’t require at least some amount of extra work. There is also a nice trick we can do here for multiple backends. So we could have ofc ErrorStyle would be implemented for markdown with something like bold. |
|
I can see your reasons, but I don't think it's the way to go for a few reasons:
There's no reason for this to be the case! Let's imagine a slight modification to the API: macro_rules! text {
($($toks:tt)*) => { Text(format_args!($($toks)*)) };
}
pub struct Text(fmt::Arguments);
impl Text {
fn fmt_inner(&self, f: &mut fmt::Formatter, with_style: bool) -> fmt::Result {
if with_style {
// Styles are included in-band, used for diagnostic rendering
} else {
// Styles are stripped from the output
}
}
}
impl fmt::Display for Text {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// The `Display` impl doesn't include styling information
self.fmt_inner(f, false)
}
}
// Usage
Label::new(span)
.with_msg(text!("Hello, {}!", "world".style("error")))Here, the |
|
Yes so the second method was more.in the direction of what I was thinking. It might even be MORE performent than existing things because it does not force rendering into a string like we previously did. There might be some middle ground here so basically imagine text! Would be using closures of some sort thus ($($toks:tt)*) => { Text(|config| format_args!($($toks.apply(config)*)))};
struct Text(FnOnce(config)->Arguments)Its the same idea as earlier but we have it delay evaluation of that format until the config is actually applied. In terms of the api its exactly the same but we don't need to parse the text for special bytes now. This solves the issue of accidentaly adding config options before the message while keeping things mostly the same. There is like the additional heap allocation that may need to go there which kinda sucks. So its not a perfect solution. |
085864b to
576b5e8
Compare
|
@zesterer fairly happy with how styling came out like it would be nice for either aproch. I also got it to stay backwards compatible with the same trick of default value and after some tinkering none of the tests needed to be rewritten for the new style. its not done yet the 3 things that are needed are:
but thought I would ask for feedback now since the general shape of the code is fairly clear already |
|
Unfortunately, I think that the changes are extremely far from what I'm proposing and still largely exhibit all of the disadvantages that I listed before. I'm going to sketch something up tonight. |
2f36bc2 to
4b3807c
Compare
as discussed in #160 adding a switch specifically for ansi colors is not ideal as it adds a dependency and slows down the usual path.
what this PR does is verify that its impossible to emit ansi colors under any config with color=false without manually inserting the ansi codes into the strings.
this is because:
if I am reading correctly the old add_labels code this PR does introduce a breaking API change.
since previously setting the config after adding labels would make for those labels being colored.
I suspect this is not intuitive or desired behavior so I am considering this a bug fix.
I think this is much nicer since now users can be confident that setting color to off before printing would always generate output without ansi signs.