zesterer / ariadne

A fancy diagnostics & error reporting crate
https://crates.io/crates/ariadne
MIT License
1.61k stars 72 forks source link

Recommended approach to handling colors #79

Closed max-sixty closed 1 year ago

max-sixty commented 1 year ago

Forgive me if this this a basic question, but I spent some time on this and struggling a bit, over at https://github.com/PRQL/prql/pull/2755

What's the recommended approach to handling whether to color output? I see two things:

Can I ask how these interact?

We want to generally "get out of the way" and let concolor pick reasonable defaults; but does leaving the Config::default of color=true mean that'll work? Or if the auto-color feature is enabled, then the color param does nothing?

zesterer commented 1 year ago

I assume since you commented on the concolor issue, you have a fairly good idea of the situation of things.

Right now, ariadne's colour support is... suboptimal. Because we have users provide stringly-typed label messages, we don't support colours through anything but in-band signalling (like ANSI escapes).

Ariadne doesn't "know" about coloured labels, it just passed the string through to the underlying impl Write verbatim. This becomes a problem with the underlying impl Write doesn't support ANSI escapes (String, or HTML on a web page, for example).

I'd like to fix this but I need to think about how labelling should work.

Right now it's very convenient to do something like format!("plain {} text", "coloured".fg(Color::Green)) to create a label message, but it gives ariadne no way to do anything intelligent. At best, it could pick through the string and pull out any ANSI escapes, but this isn't ideal and ties the crate to a technology more suited to 1973 than 2023.

The alternative is to abandon std's formatting machinery and recreate at least of some of it in a way that's tailored to Ariadne's internal needs by doing formatting out-of-band. This is a lot of work and would likely be jarring for users: ariadne would likely end up growing a macro that superficially looks and behaves like std::format! but works very differently internally.

Let me know if you happen to have thoughts/preferences on this.

does leaving the Config::default of color=true mean that'll work?

The color field of Config doesn't control the colour of labels or user-provided messages (it can't control the latter, unless it hackily strips out the ANSI escapes). It just controls whether the surrounding elements of the output have colour.

max-sixty commented 1 year ago

I very much agree with the dichotomy — standardize on ANSI vs. create a whole new world.

I don't have any great ideas unfortunately. It indeed feels archaic to standardize on ANSI — if we have to represent formatted text with only a string, maybe HTML/CSS might be better — but given most programs like this use terminals, the ecosystem goes towards ANSI.

FWIW, since I wrote up that issue, we've moved from concolor to anstyle / anstrem. That model always using escape codes, and then supplies a println! which strips them when appropriate. So they choose "standardize on ANSI" IIUC. We also strip them ourselves in snapshot tests etc.

I'll close this, thanks for the thoughtful response.