miette icon indicating copy to clipboard operation
miette copied to clipboard

Multiple trailing newlines

Open PurpleBooth opened this issue 2 years ago • 3 comments

When you get a (very nice looking) miette error you get two trailing newlines, rather than just one. This is causing me some head scratching moments with testing error outputs in downstream applications

Demo

[package]
name = "miette-bug-demo"
version = "0.1.0"
edition = "2021"

[dependencies]
miette = { version = "3.0.0", features = [ "fancy" ] }
thiserror = "1.0.30"
use miette::Diagnostic;
use thiserror::Error;
use miette::{SourceSpan, Result};

fn main() -> Result<()> {
    Err(MyErrorType{
        src: "Demo".to_string(),
        err_span: (2, 3).into(),
        snip2: (1, 2)
    })?;
    
    return Ok(());
}

#[derive(Diagnostic, Debug, Error)]
#[error("oops")]
#[diagnostic(code(my_lib::random_error))]
pub struct MyErrorType {
    // The `Source` that miette will use.
    #[source_code]
    src: String,

    // This will underline/mark the specific code inside the larger
    // snippet context.
    #[label = "This is the highlight"]
    err_span: SourceSpan,

    // You can add as many labels as you want.
    // They'll be rendered sequentially.
    #[label("This is bad")]
    snip2: (usize, usize), // (usize, usize) is Into<SourceSpan>!
}

Outputs

    Finished dev [unoptimized + debuginfo] target(s) in 0.03s
     Running `target/debug/miette-bug-demo`
Error: oops
    Diagnostic severity: error
Begin snippet starting at line 1, column 1

snippet line 1: Demo
    label starting at line 1, column 1: This is bad
    label starting at line 1, column 1: This is the highlight
diagnostic code: my_lib::random_error


I would expect the output to be

    Finished dev [unoptimized + debuginfo] target(s) in 0.03s
     Running `target/debug/miette-bug-demo`
Error: oops
    Diagnostic severity: error
Begin snippet starting at line 1, column 1

snippet line 1: Demo
    label starting at line 1, column 1: This is bad
    label starting at line 1, column 1: This is the highlight
diagnostic code: my_lib::random_error

With the fancy formatter

    Finished dev [unoptimized + debuginfo] target(s) in 0.03s
     Running `target/debug/miette-bug-demo`
Error: my_lib::random_error

  × oops
   ╭────
 1 │ ╭─▶ Demo
   · ││ ─┬
   · ││  ╰── This is bad
   ╰────


and with the characters made visible (for my own sanity)

····Finished·dev·[unoptimized·+·debuginfo]·target(s)·in·0.03s¶
·····Running·`target/debug/miette-bug-demo`¶
Error:·oops¶
····Diagnostic·severity:·error¶
Begin·snippet·starting·at·line·1,·column·1¶
¶
snippet·line·1:·Demo¶
····label·starting·at·line·1,·column·1:·This·is·bad¶
····label·starting·at·line·1,·column·1:·This·is·the·highlight¶
diagnostic·code:·my_lib::random_error¶
¶

I am not 100% sure where this is coming from in the code, there are a lot of writeln's, so I suspect it's a writeln inside a writeln using Display. Maybe it would be possible to just trim that trailing newlines before printing to stderr?

PurpleBooth avatar Oct 09 '21 06:10 PurpleBooth

I believe I did this on purpose, but some terminals display it as a BIG space. Happy to change it, though.

zkat avatar Oct 09 '21 15:10 zkat

There are 2 new lines in your output:

  • the latest called writeln! in ReportHandler::debug impls
  • the eprintln! that actually outputs to stderr: https://github.com/rust-lang/rust/blob/bc8ad24020a160e1acd7ac9f7671947dcc01264c/library/std/src/process.rs#L2045

It's deceptively easy in the case of DebugReportHandler. Just remove the ln here: https://github.com/zkat/miette/blob/fe77d8c75478e9915a61613ec94b3de0a70e5e26/src/handlers/debug.rs#L57

The graphical and narratable paths are much harder. It's a lot more difficult to find the last line sent to the &mut fmt::Formatter. AFAIK it's not possible to go back and remove the last 1-2 char(s).

One solution would be to replace all the writeln!(A) ... write[ln]!(B) with something like write!(A)... writeln!(); write!(B).

On the other hand, the diffs are empty lines. It might be easier to just write a more robust output validator.

stanciuadrian avatar Oct 24 '21 19:10 stanciuadrian

That was the route I went down in the end, I sort of decided that miette's job was to make a nice error message output, and it does look better with the newline.

Feel free to close this, my problem is solved.

PurpleBooth avatar Oct 25 '21 06:10 PurpleBooth