I am trying to colorize a returned Error message but it looks like it doesn't work with ColoredString:
use colored::*;
use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
let err_msg = "This is an error message.";
let colored_msg = err_msg.red().bold();
return Err(colored_msg.into());
}
**error[E0277]****: the trait bound `ColoredString: std::error::Error` is not satisfied**
I'm not sure what you mean by that. Those escape sequences can only color the string if you print it to a terminal; you can't have colorized string literals or anything like that.
If you want to return a ColoredString as an error value in order to color-print it later, just define your own error type that implements Error and contains the ColoredString. That’s how errors usually work anyway; the fact that String implements Error is just a convenience for prototyping or simple programs.
The Termination trait was implemented for Result<T: Termination, E: Debug>, [1] and as such, the implementation can only print the Debug representation of your string -- and that happens to be an escaped version of the String.
You need to wrap your main and print using the Display implementation instead.
use std::error::Error;
use std::process::ExitCode;
fn main() -> ExitCode {
use std::io::{self, Write};
match real_main() {
Ok(_) => ExitCode::SUCCESS,
Err(e) => {
let stderr = io::stderr();
let _ = writeln!(&mut &stderr, "Error: {e}");
ExitCode::FAILURE
}
}
}
fn real_main() -> Result<(), Box<dyn Error>> {
let err_msg = "\u{1b}[1;31mThis is an error message.\u{1b}[0m";
Err(err_msg.into())
}
Alternatively you could create some wrapper that uses Display for it's Debug implementation.
use std::error::Error;
use std::fmt;
struct DisplayMe<D>(D);
impl<D: fmt::Display> fmt::Display for DisplayMe<D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl<D: fmt::Display> fmt::Debug for DisplayMe<D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl<D: fmt::Display> Error for DisplayMe<D> {}
fn main() -> Result<(), Box<dyn Error>> {
let err_msg = "\u{1b}[1;31mThis is an error message.\u{1b}[0m";
Err(DisplayMe(err_msg).into())
}
which was a big mistake IMO, should have been E: Display -- case in point ↩︎