zkat / miette

Fancy extension for std::error::Error with pretty, detailed diagnostic printing.
https://docs.rs/miette
Apache License 2.0
2.01k stars 114 forks source link

Render diagnostics without exiting? #384

Open zmitchell opened 4 months ago

zmitchell commented 4 months ago

Say I have a user editing a file and if it doesn’t parse to the correct format I want to display the error and ask if they’d like to try again. Essentially we have an edit loop that runs until they get it right or quit. How do I get miette to render the error on each loop iteration?

I’ve tried just using println!, but only the error(…) annotation is displayed (no snippet, etc). I’ve checked that the span and source code are as expected. I checked which type of report handler is being used, and it’s not the graphical handler, though it also seems like I don’t have a way to force one to be used.

Any advice?

zkat commented 4 months ago

Try eprintln!("{:?}", err.into_diagnostic()), iirc

zmitchell commented 4 months ago

That doesn't seem to do the trick. Just to be concrete, let's say I have this type:

#[derive(Debug, Error, Diagnostic)]
#[error("Invalid manifest")]
#[diagnostic(
    code("manifest::parse"),
    url("http://example.com"),
    help("Please check the documentation for the correct format.")
)]
pub struct InvalidManifest {
    #[source_code]
    pub manifest_contents: String,

    #[label = "here"]
    pub span: SourceSpan,
}

If I construct that manually and try printing it with

let err = InvalidManifest {...};
eprintln!("{:?}", err);

I get the debug representation of the InvalidManifest struct. If I print it as

eprintln!("{}", err);

I only see Invalid manifest.

I can also call read_span manually to verify that the span is picking up the correct location of the error.

zkat commented 4 months ago

@zmitchell you're not calling .into_diagnostic(). The graphical printer is on Report's Debug impl, so you first need to turn your error into a Report.

zmitchell commented 4 months ago

I see, I guess I was confused why I needed to call into_diagnostic on something that already impls Diagnostic

zkat commented 4 months ago

Yeah I guess the naming is weird. What it actually does it get you a Report :)

ryanpeach commented 2 days ago

I also found this exceptionally hard to find. I also got a lot of .into_diagnostic() does not exist errors, even when importing IntoDiagnostic. This being on structs and enums which derive Diagnostic already.

I eventually resorted to:

eprintln!("{:?}", Report::from(error));

That worked.