[
  {
    "path": ".github/FUNDING.yml",
    "content": "github: [mitsuhiko]\n"
  },
  {
    "path": ".github/workflows/clippy.yml",
    "content": "name: Clippy\n\non: [push]\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n\n    steps:\n      - uses: actions/checkout@v4\n      - uses: dtolnay/rust-toolchain@master\n        with:\n          toolchain: stable\n          components: clippy, rustfmt\n      - name: Run clippy\n        run: make lint\n"
  },
  {
    "path": ".github/workflows/rustfmt.yml",
    "content": "name: Rustfmt\n\non: [push]\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n\n    steps:\n      - uses: actions/checkout@v4\n      - uses: dtolnay/rust-toolchain@master\n        with:\n          toolchain: stable\n          components: clippy, rustfmt\n      - name: Run rustfmt\n        run: make format-check\n"
  },
  {
    "path": ".github/workflows/tests.yml",
    "content": "name: Tests\n\non: [push]\n\njobs:\n  test-latest:\n    name: Test on Latest\n    runs-on: ubuntu-latest\n\n    steps:\n      - uses: actions/checkout@v4\n      - uses: dtolnay/rust-toolchain@master\n        with:\n          toolchain: stable\n      - name: Test\n        run: make test\n\n  test-stable:\n    name: Test on 1.42.0\n    runs-on: ubuntu-latest\n\n    steps:\n      - uses: actions/checkout@v4\n      - uses: dtolnay/rust-toolchain@master\n        with:\n          toolchain: 1.42.0\n      - name: Test\n        run: make test\n"
  },
  {
    "path": ".gitignore",
    "content": "/target\n**/*.rs.bk\nCargo.lock\n"
  },
  {
    "path": ".vscode/settings.json",
    "content": "{\n    \"rust-analyzer.checkOnSave.command\": \"clippy\"\n}"
  },
  {
    "path": "Cargo.toml",
    "content": "[package]\nname = \"better-panic\"\nversion = \"0.3.0\"\nauthors = [\"Armin Ronacher <armin.ronacher@active-4.com>\", \"Joel Höner <athre0z@zyantific.com>\"]\nedition = \"2018\"\nlicense = \"MIT\"\nrepository = \"https://github.com/mitsuhiko/better-panic\"\ndescription = \"Pretty panic backtraces inspired by Python's tracebacks.\"\nreadme = \"README.md\"\nkeywords = [\n    \"panic\",\n    \"backtrace\",\n    \"stacktrace\",\n    \"color\",\n    \"pretty\",\n]\n\n[dependencies]\nbacktrace = \"0.3.37\"\nconsole = { version = \"0.15.0\", default-features = false }\nsyntect = { version = \"4.6.0\", optional = true }\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2019 Armin Ronacher, Joel Höner\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "Makefile",
    "content": "all: build test\n\nbuild:\n\t@cargo build\n\ncheck:\n\t@cargo check\n\ndoc:\n\t@cargo doc\n\ntest:\n\t@cargo test\n\nformat:\n\t@rustup component add rustfmt 2> /dev/null\n\t@cargo fmt --all\n\nformat-check:\n\t@rustup component add rustfmt 2> /dev/null\n\t@cargo fmt --all -- --check\n\nlint:\n\t@rustup component add clippy 2> /dev/null\n\t@cargo clippy\n\n.PHONY: all check doc test format format-check lint\n"
  },
  {
    "path": "README.md",
    "content": "# better-panic\n\n[![Build Status](https://github.com/mitsuhiko/better-panic/workflows/Tests/badge.svg?branch=master)](https://github.com/mitsuhiko/better-panic/actions?query=workflow%3ATests)\n[![Crates.io](https://img.shields.io/crates/d/better-panic.svg)](https://crates.io/crates/better-panic)\n[![License](https://img.shields.io/github/license/mitsuhiko/better-panic)](https://github.com/mitsuhiko/better-panic/blob/master/LICENSE)\n[![rustc 1.42.0](https://img.shields.io/badge/rust-1.42%2B-orange.svg)](https://img.shields.io/badge/rust-1.42%2B-orange.svg)\n[![Documentation](https://docs.rs/better-panic/badge.svg)](https://docs.rs/better-panic)\n\n`better-panic` gives you pretty backtraces for panics.\n\nIt is inspired by Python tracebacks and tries to replicate them as well\nas possible.  This is what it looks like:\n\n<img src=\"https://github.com/mitsuhiko/better-panic/raw/master/screenshot.png\">\n\nSome of the code is based on the\n[color-backtrace](https://crates.io/crates/color-backtrace) library.\n\n## Usage\n\nThe most common way to use it is to invoke the `install` function\nwhich installs a panic handler.  In debug builds the backtrace is shown\nautomatically, in release builds it's hidden by default.\n\n```rust\nbetter_panic::install();\n```\n\nFor more configuration see the `Settings` object.\n\n## Features\n\n- Colorize backtraces to be easier on the eyes\n- Show source snippets if source files are found on disk\n- Hide all the frames after the panic was already initiated\n\n## License and Links\n\n- [Documentation](https://docs.rs/better-panic/)\n- [Issue Tracker](https://github.com/mitsuhiko/better-panic/issues)\n- [Examples](https://github.com/mitsuhiko/better-panic/tree/master/examples)\n- License: [MIT](https://github.com/mitsuhiko/better-panic/blob/master/LICENSE)\n"
  },
  {
    "path": "examples/demo.rs",
    "content": "fn bar() {\n    vec![42u32][10];\n}\n\nfn foo() {\n    bar();\n}\n\nfn main() {\n    better_panic::Settings::debug()\n        .most_recent_first(false)\n        .lineno_suffix(true)\n        .install();\n    foo();\n}\n"
  },
  {
    "path": "src/lib.rs",
    "content": "//! `better-panic` gives you pretty backtraces for panics.\n//!\n//! It is inspired by Python tracebacks and tries to replicate them as well\n//! as possible.  This is what it looks like:\n//!\n//! <img src=\"https://github.com/mitsuhiko/better-panic/raw/master/screenshot.png\">\n//!\n//! Some of the code is based on the\n//! [color-backtrace](https://crates.io/crates/color-backtrace) library.\n//!\n//! ## Usage\n//!\n//! The most common way to use it is to invoke the `install` function\n//! which installs a panic handler.  In debug builds the backtrace is shown\n//! automatically, in release builds it's hidden by default.\n//!\n//! ```\n//! better_panic::install();\n//! ```\n//!\n//! For more configuration see the `Settings` object.\n//!\n//! ## Features\n//!\n//! - Colorize backtraces to be easier on the eyes\n//! - Show source snippets if source files are found on disk\n//! - Hide all the frames after the panic was already initiated\nuse console::style;\nuse std::borrow::Cow;\nuse std::fs::File;\nuse std::io::{self, BufRead, BufReader, ErrorKind, Write};\nuse std::panic::PanicInfo;\nuse std::path::{Path, PathBuf};\n\n/// Defines how verbose the backtrace is supposed to be.\n#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]\npub enum Verbosity {\n    /// Print a small message including the panic payload and the panic location.\n    Minimal,\n    /// Everything in `Minimal` and additionally print a backtrace.\n    Medium,\n    /// Everything in `Medium` plus source snippets for all backtrace locations.\n    Full,\n}\n\nimpl Verbosity {\n    /// Get the verbosity level from the `RUST_BACKTRACE` env variable.\n    pub fn from_env() -> Self {\n        match std::env::var(\"RUST_BACKTRACE\") {\n            Ok(ref x) if x == \"full\" => Verbosity::Full,\n            Ok(_) => Verbosity::Medium,\n            Err(_) => Verbosity::Minimal,\n        }\n    }\n\n    fn apply_to_process(self) {\n        let val = match self {\n            Verbosity::Full => \"full\",\n            Verbosity::Medium => \"1\",\n            Verbosity::Minimal => \"\",\n        };\n        if val.is_empty() {\n            std::env::remove_var(\"RUST_BACKTRACE\");\n        } else {\n            std::env::set_var(\"RUST_BACKTRACE\", val);\n        }\n    }\n}\n\n/// Installs the panic handler with `Settings::auto`.\npub fn install() {\n    Settings::auto().install()\n}\n\n/// Installs the panic handler with debug settings.\npub fn debug_install() {\n    Settings::debug().install()\n}\n\nstruct Frame {\n    name: Option<String>,\n    lineno: Option<u32>,\n    filename: Option<PathBuf>,\n}\n\nimpl Frame {\n    fn name_without_hash(&self) -> Option<&str> {\n        let name = self.name.as_ref()?;\n        let has_hash_suffix = name.len() > 19\n            && &name[name.len() - 19..name.len() - 16] == \"::h\"\n            && name[name.len() - 16..].chars().all(|x| x.is_digit(16));\n        if has_hash_suffix {\n            Some(&name[..name.len() - 19])\n        } else {\n            Some(name)\n        }\n    }\n\n    fn is_dependency_code(&self) -> bool {\n        const SYM_PREFIXES: &[&str] = &[\n            \"std::\",\n            \"core::\",\n            \"backtrace::backtrace::\",\n            \"_rust_begin_unwind\",\n            \"better_panic::\",\n            \"__rust_\",\n            \"___rust_\",\n            \"__pthread\",\n            \"_main\",\n            \"main\",\n            \"__scrt_common_main_seh\",\n            \"BaseThreadInitThunk\",\n            \"_start\",\n            \"__libc_start_main\",\n            \"start_thread\",\n        ];\n\n        // Inspect name.\n        if let Some(ref name) = self.name {\n            if SYM_PREFIXES.iter().any(|x| name.starts_with(x)) {\n                return true;\n            }\n        }\n\n        const FILE_PREFIXES: &[&str] = &[\n            \"rust:\",\n            \"/rustc/\",\n            \"src/libstd/\",\n            \"src/libpanic_unwind/\",\n            \"src/libtest/\",\n        ];\n\n        // Inspect filename.\n        if let Some(filename) = self.filename.as_ref().and_then(|x| x.to_str()) {\n            // some filenames are really weird from macro expansion.  consider\n            // them not to be part of the user code.\n            if filename.contains('<') {\n                return true;\n            }\n            if FILE_PREFIXES.iter().any(|x| filename.starts_with(x))\n                || filename.contains(\"/.cargo/registry/src/\")\n            {\n                return true;\n            }\n        }\n\n        false\n    }\n\n    // Heuristically determine whether a frame is likely to be a post panic\n    // frame.\n    //\n    // Post panic frames are frames of a functions called after the actual panic\n    // is already in progress and don't contain any useful information for a\n    // reader of the backtrace.\n    fn is_post_panic_code(&self) -> bool {\n        const SYM_PREFIXES: &[&str] = &[\n            \"_rust_begin_unwind\",\n            \"panic_bounds_check\",\n            \"core::result::unwrap_failed\",\n            \"core::panicking::panic_fmt\",\n            \"core::panicking::panic_bounds_check\",\n            \"color_backtrace::create_panic_handler\",\n            \"std::panicking::begin_panic\",\n            \"begin_panic_fmt\",\n            \"rust_begin_panic\",\n            \"panic_bounds_check\",\n            \"panic_fmt\",\n        ];\n\n        if let Some(filename) = self.filename.as_ref().and_then(|x| x.to_str()) {\n            if filename.contains(\"libcore/panicking.rs\") {\n                return true;\n            }\n        }\n\n        match self.name_without_hash() {\n            Some(name) => SYM_PREFIXES\n                .iter()\n                .any(|x| name.starts_with(x) || name.ends_with(\"__rust_end_short_backtrace\")),\n            None => false,\n        }\n    }\n\n    // Heuristically determine whether a frame is likely to be part of language\n    // runtime.\n    fn is_runtime_init_code(&self) -> bool {\n        const SYM_PREFIXES: &[&str] =\n            &[\"std::rt::lang_start::\", \"test::run_test::run_test_inner::\"];\n\n        let (name, file) = match (self.name_without_hash(), self.filename.as_ref()) {\n            (Some(name), Some(filename)) => (name, filename.to_string_lossy()),\n            _ => return false,\n        };\n\n        if SYM_PREFIXES\n            .iter()\n            .any(|x| name.starts_with(x) || name.ends_with(\"__rust_start_short_backtrace\"))\n        {\n            return true;\n        }\n\n        // For Linux, this is the best rule for skipping test init I found.\n        if name == \"{{closure}}\" && file == \"src/libtest/lib.rs\" {\n            return true;\n        }\n\n        false\n    }\n\n    /// Is this a call once frame?\n    fn is_call_once(&self) -> bool {\n        if let Some(name) = self.name_without_hash() {\n            name.ends_with(\"FnOnce::call_once\")\n        } else {\n            false\n        }\n    }\n\n    fn print_source(&self, s: &Settings) -> Result<(), io::Error> {\n        let (lineno, filename) = match (self.lineno, self.filename.as_ref()) {\n            (Some(a), Some(b)) => (a, b),\n            // Without a line number and file name, we can't sensibly proceed.\n            _ => return Ok(()),\n        };\n\n        print_source(filename, lineno, s)\n    }\n\n    fn print(&self, s: &Settings) -> Result<(), io::Error> {\n        let is_dependency_code = self.is_dependency_code();\n\n        let name = self.name_without_hash().unwrap_or(\"<unknown>\");\n\n        // Print function name.\n        let mut name_style = console::Style::new();\n        if is_dependency_code {\n            name_style = name_style.cyan();\n        } else {\n            name_style = name_style.green();\n        }\n\n        // Print source location, if known.\n        let file = match &self.filename {\n            Some(filename) => trim_filename(filename),\n            None => Cow::Borrowed(\"<unknown>\"),\n        };\n\n        if s.lineno_suffix {\n            writeln!(\n                &s.out,\n                \"  File \\\"{}:{}\\\", in {}\",\n                style(file).underlined(),\n                style(self.lineno.unwrap_or(0)).yellow(),\n                name_style.apply_to(name)\n            )?;\n        } else {\n            writeln!(\n                &s.out,\n                \"  File \\\"{}\\\", line {}, in {}\",\n                style(file).underlined(),\n                style(self.lineno.unwrap_or(0)).yellow(),\n                name_style.apply_to(name)\n            )?;\n        }\n\n        // Maybe print source.\n        if s.verbosity >= Verbosity::Full {\n            self.print_source(s)?;\n        }\n\n        Ok(())\n    }\n}\n\n/// Configuration for panic printing.\n#[derive(Debug, Clone)]\npub struct Settings {\n    message: String,\n    out: console::Term,\n    verbosity: Verbosity,\n    backtrace_first: bool,\n    most_recent_first: bool,\n    lineno_suffix: bool,\n}\n\nimpl Default for Settings {\n    fn default() -> Self {\n        Self {\n            verbosity: Verbosity::from_env(),\n            message: \"The application panicked (crashed).\".to_owned(),\n            out: console::Term::stderr(),\n            backtrace_first: true,\n            most_recent_first: true,\n            lineno_suffix: false,\n        }\n    }\n}\n\nimpl Settings {\n    /// Alias for `Settings::default`.\n    pub fn new() -> Self {\n        Self::default()\n    }\n\n    /// Common settings for debugging.\n    pub fn debug() -> Self {\n        Self::new().verbosity(Verbosity::Full)\n    }\n\n    /// In release builds this is `new`, in debug builds this is `debug`.\n    pub fn auto() -> Self {\n        #[cfg(debug_assertions)]\n        {\n            Self::debug()\n        }\n        #[cfg(not(debug_assertions))]\n        {\n            Self::new()\n        }\n    }\n\n    /// Controls the \"greeting\" message of the panic.\n    ///\n    /// Defaults to `\"The application panicked (crashed)\"`.\n    pub fn message(mut self, message: impl Into<String>) -> Self {\n        self.message = message.into();\n        self\n    }\n\n    /// Controls the verbosity level.\n    ///\n    /// Defaults to `Verbosity::get_env()`.\n    pub fn verbosity(mut self, v: Verbosity) -> Self {\n        self.verbosity = v;\n        self\n    }\n\n    /// Controls the backtrace position.\n    ///\n    /// Defaults to `true` which causes the backtrace to be printed above\n    /// the panic.\n    pub fn backtrace_first(mut self, value: bool) -> Self {\n        self.backtrace_first = value;\n        self\n    }\n\n    /// Controls the most-recent-first behavior.\n    ///\n    /// Defaults to `true` which causes the backtrace to be printed above\n    /// the panic.\n    pub fn most_recent_first(mut self, value: bool) -> Self {\n        self.most_recent_first = value;\n        self\n    }\n\n    /// Append the line number as suffix to the filename.\n    ///\n    /// Defaults to `false` which causes line numbers to be rendered separately.\n    /// Specifically this renders `File \"foo.rs:42\"` instead of\n    /// `File \"foo.rs\", line 42` which lets some terminals open the editor\n    /// at the right location on click.\n    pub fn lineno_suffix(mut self, value: bool) -> Self {\n        self.lineno_suffix = value;\n        self\n    }\n\n    /// Consumes the settings and creates a panic handler.\n    pub fn create_panic_handler(self) -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send> {\n        Box::new(move |pi| {\n            print_panic_and_backtrace(pi, &self).unwrap();\n        })\n    }\n\n    /// Installs the panic handler.\n    pub fn install(self) {\n        self.verbosity.apply_to_process();\n        std::panic::set_hook(self.create_panic_handler())\n    }\n}\n\nfn print_source(filename: &Path, lineno: u32, s: &Settings) -> Result<(), io::Error> {\n    let file = match File::open(filename) {\n        Ok(file) => file,\n        Err(ref e) if e.kind() == ErrorKind::NotFound => return Ok(()),\n        e @ Err(_) => e?,\n    };\n\n    let reader = BufReader::new(file);\n    let source_line = reader.lines().nth((lineno - 1) as usize);\n    if let Some(Ok(source_line)) = source_line {\n        writeln!(&s.out, \"    {}\", style(source_line.trim()).dim())?;\n    }\n\n    Ok(())\n}\n\nfn print_backtrace(bt: Option<&backtrace::Backtrace>, s: &Settings) -> Result<(), io::Error> {\n    if s.most_recent_first {\n        writeln!(\n            &s.out,\n            \"{}\",\n            style(\"Backtrace (most recent call first):\").bold()\n        )?;\n    } else {\n        writeln!(\n            &s.out,\n            \"{}\",\n            style(\"Backtrace (most recent call last):\").bold()\n        )?;\n    }\n\n    // Collect frame info.\n    let mut frames = Vec::new();\n    if let Some(bt) = bt {\n        for frame in bt.frames() {\n            for sym in frame.symbols() {\n                frames.push(Frame {\n                    name: sym.name().map(|x| x.to_string()),\n                    lineno: sym.lineno(),\n                    filename: sym.filename().map(|x| x.into()),\n                });\n            }\n        }\n    } else {\n        backtrace::trace(|x| {\n            // TODO: Don't just drop unresolvable frames.\n            backtrace::resolve(x.ip(), |sym| {\n                frames.push(Frame {\n                    name: sym.name().map(|x| x.to_string()),\n                    lineno: sym.lineno(),\n                    filename: sym.filename().map(|x| x.into()),\n                });\n            });\n\n            true\n        });\n    }\n\n    // Try to find where the interesting part starts...\n    let top_cutoff = frames\n        .iter()\n        .rposition(Frame::is_post_panic_code)\n        .map(|x| x + 1)\n        .unwrap_or(0);\n\n    // Try to find where language init frames start ...\n    let bottom_cutoff = frames\n        .iter()\n        .position(Frame::is_runtime_init_code)\n        .map(|x| x - 1)\n        .unwrap_or_else(|| frames.len());\n\n    // Turn them into `Frame` objects and print them.\n    let mut frames = &frames[top_cutoff..bottom_cutoff];\n\n    if !frames.is_empty() && frames[frames.len() - 1].is_call_once() {\n        frames = &frames[..frames.len() - 1];\n    }\n\n    if s.most_recent_first {\n        for frame in frames {\n            frame.print(s)?;\n        }\n    } else {\n        for frame in frames.iter().rev() {\n            frame.print(s)?;\n        }\n    }\n\n    Ok(())\n}\n\nfn print_panic_and_backtrace(pi: &PanicInfo, s: &Settings) -> Result<(), io::Error> {\n    if s.backtrace_first {\n        print_backtrace_info(s)?;\n        writeln!(&s.out)?;\n    }\n    print_panic_info(pi, s)?;\n    if !s.backtrace_first {\n        writeln!(&s.out)?;\n        print_backtrace_info(s)?;\n    }\n    Ok(())\n}\n\nfn trim_filename(file: &Path) -> Cow<'_, str> {\n    let filename = file.to_str().unwrap_or(\"<bad utf8>\");\n    if filename.starts_with(\"/rustc/\") {\n        if let Some(filename) = filename.get(48..) {\n            Cow::Owned(format!(\"rust:{}\", filename))\n        } else {\n            Cow::Borrowed(filename)\n        }\n    } else if let Some(basename) = file.file_name().and_then(|x| x.to_str()) {\n        if basename.starts_with('<') && basename.ends_with('>') {\n            Cow::Borrowed(basename)\n        } else {\n            Cow::Borrowed(filename)\n        }\n    } else {\n        Cow::Borrowed(filename)\n    }\n}\n\nfn print_panic_info(pi: &PanicInfo, s: &Settings) -> Result<(), io::Error> {\n    writeln!(&s.out, \"{}\", style(&s.message).bold())?;\n\n    let thread = std::thread::current();\n    let thread_name = thread.name().unwrap_or(\"<unnamed>\");\n\n    // Print panic message.\n    let payload = pi\n        .payload()\n        .downcast_ref::<String>()\n        .map(String::as_str)\n        .or_else(|| pi.payload().downcast_ref::<&str>().cloned())\n        .unwrap_or(\"Box<Any>\");\n\n    for line in payload.lines() {\n        writeln!(&s.out, \"  {}\", style(line).yellow())?;\n    }\n\n    // If known, print panic location.\n    write!(&s.out, \"in \")?;\n    if let Some(loc) = pi.location() {\n        if s.lineno_suffix {\n            writeln!(\n                &s.out,\n                \"{}:{}\",\n                style(trim_filename(Path::new(loc.file()))).underlined(),\n                style(loc.line()).yellow()\n            )?;\n        } else {\n            writeln!(\n                &s.out,\n                \"{}, line {}\",\n                style(trim_filename(Path::new(loc.file()))).underlined(),\n                style(loc.line()).yellow()\n            )?;\n        }\n    } else {\n        writeln!(&s.out, \"<unknown>\")?;\n    }\n    writeln!(&s.out, \"thread: {}\", style(thread_name).yellow())?;\n    Ok(())\n}\n\nfn print_backtrace_info(s: &Settings) -> Result<(), io::Error> {\n    // Print some info on how to increase verbosity.\n    if s.verbosity == Verbosity::Minimal {\n        writeln!(\n            &s.out,\n            \"\\nBacktrace omitted. Run with RUST_BACKTRACE=1 to display it.\"\n        )?;\n    }\n    if s.verbosity <= Verbosity::Medium {\n        if s.verbosity == Verbosity::Medium {\n            // If exactly medium, no newline was printed before.\n            writeln!(&s.out)?;\n        }\n\n        writeln!(\n            &s.out,\n            \"Run with RUST_BACKTRACE=full to include source snippets.\"\n        )?;\n    }\n\n    if s.verbosity >= Verbosity::Medium {\n        print_backtrace(None, s)?;\n    }\n\n    Ok(())\n}\n"
  }
]