Colorized Err return

Hi,

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**

Is there an alternative way to make this work?

Thanks again.

ColoredString is Display, so you can call .to_string() on it.

Hi @H2CO3
I've tried .to_string() before but it wouldn't give me the error message with color and rather give it back like the following:

Error: "\u{1b}[1;31mThis is an error message.\u{1b}[0m"

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.

1 Like

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())
}

  1. which was a big mistake IMO, should have been E: Display -- case in point ↩︎

2 Likes

Thank you. This was very helpful.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.