rust-lang / rfcs

RFCs for changes to Rust
https://rust-lang.github.io/rfcs/
Apache License 2.0
5.88k stars 1.56k forks source link

Color the `dbg!()` macro #3679

Open amab8901 opened 4 weeks ago

amab8901 commented 4 weeks ago

I found this cool crate that offers a colored version of dbg!() called color!().

Unfortunately, it doesn't integrate with all other crates because most people aren't aware of this crate so they haven't added an integration for it. And orphan rule doesn't let me easily create a custom impl for those crates.

Would be really nice if we had colored dbg!() output in the dbg!() macro (or perhaps create another macro for colored debug output, or via println!(), or something like that). It's especially helpful when dealing with complex nested structs by letting me find what I'm looking for more easily/conveniently.

This proposal received lots of positive feedback in the internals forum, so I'm copying it over to this RFC.

LunarLambda commented 4 weeks ago

This will probably not happen as dbg_pls' coloring has to ship an entire Rust syntax parser to do the highlighting, something that would be completely out of scope for std. You would need to propose a design for a highlighting scheme that builds on the Debug trait (which is difficult because DebugPls explicitly states that the output has to be a valid syn::Expr, and Debug can be anything) and avoids pulling in dependencies into std, or reimplementing vast amounts of highlighting/parsing code that will be a major maintenance burden.

The most plausible design I could see would be to add a format specifier for color (adding new macros would require adding _color versions of everything), and then having the debug_* methods of fmt::Formatter add coloring for derived Debug impls on most types, and maybe a few Debug impls made by std on primitive types like str as well. This would not work universally, but it would cover most of the common use cases with minimal code and no public API changes except for the format specifier.

An open question would be where to put the common logic of 'if stdout().is_terminal() { / color / } else { / no color / }, since it can't currently be handled byFormatter(it would need some new method of construction that can useIsTerminal`), or whether this would fall on the user to have format strings for the colored and uncolored variants.

Ultimately I don't think std wants to be doing any of this, colored output is platform specific and there's so many different ways to do it that no matter what std picks, inevitably people would find it insufficient in one way or another.

kornelski commented 4 weeks ago

I think this could be done without adding coloring to libstd. Instead, libstd could expose a hook for crates to postprocess dbg's output or hook into formatting it does.

For example:

std::fmt::set_dbg_hook(color_formatter_function)
amab8901 commented 3 weeks ago

I found that you can do cargo r -- --color. Perhaps we can add the colored dbg there? The user can then decide if they want the dbg to be colored or not, by the --color CLI option. How to decide which color to apply where? By formatting it as markup's color for Rust. I haven't looked into the source code of markdown but I do know that you can access it by writing like syntax like this in markdown files:

struct Struct {
    field1: String,
}

Perhaps one could dig into the source code of markdown and just impl it the same way? Or perhaps this crate may be used? (I haven't checked yet if they implemented this feature but they might have)

kornelski commented 3 weeks ago

@amab8901 The issue isn't how to add color to libstd, but that it's a burden for libstd to carry this functionality, for all platforms current and future, maintained forever, and adding overhead to every Rust executable. Additions to libstd are very costly.