Color the `dbg!()` macro

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.

7 Likes

Similar to this is pretty_assertions for assert_eq etc for tests. That too would be nice by default.

6 Likes

Another option (though potentially a breaking change) would be to do it for dbg!() itself:

  • Automatically detect if color is supported in the output (and/or use an environment variable to opt-in, for example RUST_DEBUG_COLOR=true)
  • Formatter::debug_* methods insert the required ansi escape codes
  • New method for outputting with color: Formatter::with_color(Color, ...), with enum Color {...}, which could also support bold and similar.

This way you wouldn't even have to change the macro used and the output would be consistent accross all calls of dbg!(), asserts and other uses of Debug::fmt, regardless of whether they are in a library.

2 Likes

I don't think tackling the following problems in the standard library makes sense:

  • light vs dark color schemes
  • poor color combinations (yellow on light, blue on dark)
  • 8 vs 256 vs rgb color support (nevermind detection)
  • older Windows terminals (which, IIRC, involve library calls to do color manip, not in-band signalling)
  • filtering ANSI codes from the stream where necessary

A fancy_dbg crate that shadows dbg! seems reasonable, but the standard library shouldn't touch it IMO.

5 Likes

Good point, but perhaps the stdlib could/should provide a way to customize the behavior of existing Debug impls, for example in a way that allows applications to use/configure a (project wide) modified Formatter implementation, which would allow this. Instead of requiring every crate you want to use to derive something else that is functionally equivalent to Debug::fmt, just with a different Formatter.

The main issue (I see) with something that has/needs its own #[derive(FancyDebug] is that it will not work for libraries that don't import that fancy_dbg crate (e.g. don't know about it), as due to orphan rules (and no specialization) you effectively cannot auto-implement FancyDebug for everything that is Debug, nor can you reuse the existing implementation because it uses a Formatter struct instead of being generic over a trait.

Though perhaps it would be better to do this once specialization is stable, as I think changing the Formatter in Debug would be a breaking change that affects a lot of people.

1 Like

The problems you said shouldn't be tackled in standard library, maybe we can start with environment variables that lets the user configure those things (similar to how RUST_LOG env is used with cargo run). Some envs could tackle granular details (like 8 vs 256 vs RGB color, etc), and other envs could offer abstractions (like choosing between popular themes like markdown or rust-analyzer in VSCode).

if you use a fancy_dbg crate (which already exists, see the links in the original post), you run into the problem where the colored dbg! works only for types in the standard library and types defined locally, but doesn't work for types imported from all 3rd party crates (due to orphan rule). It's unfeasible for the maintainer of the fancy_dbg (in this case dbg_pls) to create manual implementations for every single crate in crates.io. In order to make it work for all types where dbg! works, I think it needs to be done via the standard library.

or actually, I don't know if trait generics has been attempted via a 3rd party crate. Would be interesting to know if it works

The standard library has global hooks for printing panics. It could have a global hook for custom printing of dbg!.

6 Likes

I opened an RFC for this

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.