Repository: rust-cli/human-panic (language: rust)

Issue:
🙋 Suggestion: Start printing backtrace from panic's position
Looking at the way `human-panic` handles backtrace, I feel like it would be better to suggest to stop printing unnecessary frames we get from `backtrace` as it has own calls, and instead jump straight to user code. This is how I made for my lazy panic handlers when backtrace is on https://github.com/DoumanAsh/lazy-panic.rs/blob/master/src/formatter.rs#L189-L202

## Expected Behavior

Prints stacktrace from user code

## Current Behavior
Prints stacktrace from `human-panic` and its dependency `backtrace`

## Possible Solution
Calculate where user code's panic starts and start printing from this point (Not sure if it is platform dependent number, but both windows and linux had the same stack trace in my experiments)

## Context
I just feel it would improve usability for reports with backtrace



Discussion / hints:
Yea, this is a good idea. I just tagged this in for the 2.0 release, even though its not technically a breaking change.

Fix patch:
diff --git a/src/report.rs b/src/report.rs
index 03d5092..91f6461 100644
--- a/src/report.rs
+++ b/src/report.rs
@@ -9,6 +9,8 @@ use self::failure::Error;
 use self::uuid::Uuid;
 use backtrace::Backtrace;
 use std::borrow::Cow;
+use std::fmt::Write as FmtWrite;
+use std::mem;
 use std::{env, fs::File, io::Write, path::Path, path::PathBuf};
 
 /// Method of failure.
@@ -44,7 +46,67 @@ impl Report {
       format!("unix:{:?}", platform.os_type).into()
     };
 
-    let backtrace = format!("{:#?}", Backtrace::new());
+    //We skip 3 frames from backtrace library
+    //Then we skip 3 frames for our own library
+    //(including closure that we set as hook)
+    //Then we skip 2 functions from Rust's runtime
+    //that calls panic hook
+    const SKIP_FRAMES_NUM: usize = 8;
+    //We take padding for address and extra two letters
+    //to padd after index.
+    const HEX_WIDTH: usize = mem::size_of::<usize>() + 2;
+    //Padding for next lines after frame's address
+    const NEXT_SYMBOL_PADDING: usize = HEX_WIDTH + 6;
+
+    let mut backtrace = String::new();
+
+    //Here we iterate over backtrace frames
+    //(each corresponds to function's stack)
+    //We need to print its address
+    //and symbol(e.g. function name),
+    //if it is available
+    for (idx, frame) in Backtrace::new()
+      .frames()
+      .iter()
+      .skip(SKIP_FRAMES_NUM)
+      .enumerate()
+    {
+      let ip = frame.ip();
+      let _ = write!(backtrace, "\n{:4}: {:2$?}", idx, ip, HEX_WIDTH);
+
+      let symbols = frame.symbols();
+      if symbols.is_empty() {
+        let _ = write!(backtrace, " - <unresolved>");
+        continue;
+      }
+
+      for (idx, symbol) in symbols.iter().enumerate() {
+        //Print symbols from this address,
+        //if there are several addresses
+        //we need to put it on next line
+        if idx != 0 {
+          let _ = write!(backtrace, "\n{:1$}", "", NEXT_SYMBOL_PADDING);
+        }
+
+        if let Some(name) = symbol.name() {
+          let _ = write!(backtrace, " - {}", name);
+        } else {
+          let _ = write!(backtrace, " - <unknown>");
+        }
+
+        //See if there is debug information with file name and line
+        if let (Some(file), Some(line)) = (symbol.filename(), symbol.lineno()) {
+          let _ = write!(
+            backtrace,
+            "\n{:3$}at {}:{}",
+            "",
+            file.display(),
+            line,
+            NEXT_SYMBOL_PADDING
+          );
+        }
+      }
+    }
 
     Self {
       crate_version: version.into(),


Test patch: