How can I add colors to field names who implement the Debug
trait? And how to customize the indentation size for {:#?}
?
I think I can't use Display
, because it doesn't support nested indentation.
How can I add colors to field names who implement the Debug
trait? And how to customize the indentation size for {:#?}
?
I think I can't use Display
, because it doesn't support nested indentation.
You can't change the implementation of type you don't own. But you can use a newtype and implement Debug
on that yourself.
There's no way to use the std
derive to change the indentation or add colors. Moreover, the debug helpers don't have that sort of customization either. So you'd have to basically replicate their functionality.
In your implementation, you can tell if the #
flag was given, and what other flags were given, by using alternate
and the other methods on the Formatter
.
There's nothing preventing you from putting indentation in a Display
implementation. The Display
trait looks exactly like the Debug
trait, and the other fmt
traits.
If you don't want to do all that your self, I guess I'd start looking for a crate first. I'm not aware of any offhand.
Alternatively you could write a non-customized output to a buffer and then use text manipulation to add colors and modify indentation, but that would be quite inefficient and probably pretty hacky too.
Debug
doesn't uniquely “support” nested indentation either. All the indentation is produced by the helper functions like debug_struct()
, which you can use regardless of choice of formatting trait — but, also, they aren't internal magic either, and they work by adding a fmt::Write
adapter that inserts spaces whenever it sees a newline. You can write the same adapter in your own code.
you cannot replace the impl of the Debug
trait for types, you either create a wrapper, or you add the format in the parent struct. but either way, it cannot be derive
-ed, you must implement the trait manually.
for instance, you can create a wrapper that formats the inner type in red like this:
struct Red<T>(pub T);
impl<T: Debug> Debug for Red<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if f.alternate() {
write!(f, "\x1b[31m{:?}\x1b[0m", self.0)
} else {
write!(f, "\x1b[31m{:#?}\x1b[0m", self.0)
}
}
}
and then instead of use i32
as the type for the field, you use the wrapper Red<i32>
:
#[derive(Debug)]
struct Foo {
x: Red<i32>,
}
this make the use of the field a little inconvenient, since you now must write foo.x.0
.
alternative is you manually implement the Debug
directly for Foo
, you may take advantage of the Red
wrapper above, something like:
struct Foo {
x: i32,
}
impl Debug for Foo {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Foo").field("x", &Red(self.x)).finish()
}
}
Thank you for your help! I am trying to build a new ColoredDebug
proc-macro.
There's a few crates that allow you to customize Debug and Display, the most straightforwardly impressive I found being:
I didn't find one that allows customizing indent / colors straightforwardly, so what you're working on sounds pretty useful!
That appears to be what this crate does!
debug_struct
uses private fmt.wrap_buf
.
AFAIK in stable Rust it's not possible to create an instance of fmt::Formatter
, so you can't directly intercept calls to it to add indentation or colors. Maybe it'd be doable more indirectly via a newtype implementing fmt::Write
?
That's what I mean. The necessary part is replacing the Write
implementation that the formatting process uses, which is possible. You can't yet get exactly the same Formatter
, but it would be a very narrow situation where you need that and are also adding multiline indentation.