#dbg #pretty-print #macro #file-line #line-column #programming

pretty_dbg

pretty_dbg! 是dbg!的副本,只是将:#?改为:#以便进行格式化打印。format_dbg!与eprintln!类似,增加了文件、行和列信息

4个稳定版本

1.0.54 2024年2月22日
1.0.49 2024年2月2日

#137调试

每月 下载 35

MIT 许可证

16KB

Rust宏 pretty_dbg!()

pretty_dbg! 是dbg!的副本,只是将:#?改为:#以便进行格式化打印。format_dbg!与eprintln!类似,增加了文件、行和列信息
版本:1.0.54 日期:2024-02-22 作者: bestia.dev 仓库: GitHub

maintained ready_for_use

crates.io Documentation crev reviews RustActions

latest doc License pretty_dbg

Lines in Rust code Lines in Doc comments Lines in Comments Lines in examples Lines in tests

标签:#rustlang #教程
我的GitHub项目更像是教程而不是成品: bestia-dev教程.

动机

我喜欢在Rust中使用宏dbg!()。它是编程和调试时在屏幕上临时打印值的简单方法。
当不再需要时,可以很容易地搜索所有的dbg!并将其删除或注释掉。
在我上一个项目中,我有一些JSON数据。标准库中的宏打印出一个难以阅读的长字符串。这太不美观了!即使是多行字符串也被打印成一行,使其难以阅读。

rust playground中运行此代码

fn main() {
    let json_str = r#"
{
    owner: 'bestia-dev',
    repository_details: {
        general: {
        description: 'testing the creation of a github repo',
        },
    },
}
"#;
    dbg!(json_str);
}

这是字符串的不可读输出

[src/main.rs:12] json_str = "\n   {\n    owner: 'bestia-dev',\n    repository_details: {\n      general: {\n        description: 'testing the creation of a github repo',\n      },\n    },\n  }\n"

现在让我们尝试使用serde_json::Value

rust playground中运行此代码

use serde_json;
use anyhow::Result;

fn main() -> Result<(), anyhow::Error>{
       let response_text =
r#"{
    "id": 1296269,
    "homepage": "https://github.com"
}"#;
    let parsed_json_value: serde_json::Value = serde_json::from_str(response_text)?;
    dbg!(&parsed_json_value);
    
    Ok(())
}

这也返回了一个不可读的输出

[src/main.rs:11] &parsed_json_value = Object {
    "homepage": String("https://github.com"),
    "id": Number(1296269),
}

我知道在底层,dbg! 只是一个简单的 eprintln!("{:#?}, json")。我还知道,我可以用 eprintln!("{:#}, json") 打印格式化的 JSON,但这样就不能清晰地表达我的意图去使用 dbg!,而且我也失去了搜索 dbg! 的可能性。

我发现了一个库,它可以给 dbg! 输出添加颜色,看起来非常漂亮:dbg-pls。这可能对我这个小小的项目来说有点过头了。

新的 pretty_dbg! 宏

所以我决定复制原始的宏 dbg!,稍作修改,并给它命名为 pretty_dbg!

rust playground 中运行此代码

/// copy of the macro dbg!, just modified :#? to :# for pretty print
#[macro_export]
macro_rules! pretty_dbg {
    () => {
        std::eprintln!("[{}:{}:{}]", std::file!(), std::line!(), std::column!())
    };
    ($val:expr $(,)?) => {
        match $val {
            tmp => {
                std::eprintln!("[{}:{}:{}] {} = {:#}",
                    std::file!(), std::line!(), std::column!(), std::stringify!($val), &tmp);
                tmp
            }
        }
    };
    ($($val:expr),+ $(,)?) => {
        ($(std::pretty_dbg!($val)),+,)
    };
}

fn main() {
    let json_str = r#"
   {
    owner: 'bestia-dev',
    repository_details: {
      general: {
        description: 'testing the creation of a github repo',
      },
    },
  }
"#;
    pretty_dbg!(json_str);
}

输出现在非常漂亮

[src/main.rs:32] json_str = 
   {
    owner: 'bestia-dev',
    repository_details: {
      general: {
        description: 'testing the creation of a github repo',
      },
    },
  }

现在让我们尝试使用serde_json::Value

rust playground 中运行此代码

use serde_json;
use anyhow::Result;

/// copy of the macro dbg!, just modified :#? to :# for pretty print
#[macro_export]
macro_rules! pretty_dbg {
    () => {
        std::eprintln!("[{}:{}:{}]", std::file!(), std::line!(), std::column!())
    };
    ($val:expr $(,)?) => {
        match $val {
            tmp => {
                std::eprintln!("[{}:{}:{}] {} = {:#}",
                    std::file!(), std::line!(), std::column!(), std::stringify!($val), &tmp);
                tmp
            }
        }
    };
    ($($val:expr),+ $(,)?) => {
        ($(std::pretty_dbg!($val)),+,)
    };
}

fn main() -> Result<(), anyhow::Error>{
       let response_text =
r#"{
    "id": 1296269,
    "homepage": "https://github.com"
}"#;
    let parsed_json_value: serde_json::Value = serde_json::from_str(response_text)?;
    pretty_dbg!(&parsed_json_value);
    
    Ok(())
}

输出现在很漂亮

[src/main.rs:31] &parsed_json_value = {
  "homepage": "https://github.com",
  "id": 1296269
}

新的 format_dbg! 宏

有时在调试时,我想将一些字符串写入输出,而不仅仅是变量。
dbg! 宏以及随之而来的 pretty_dbg! 宏并不是完成这个任务的正确工具。

我再次可以使用简单的 eprintln!,但这样就不容易找到和移除这段调试代码。
让我们再创建一个宏 format_dbg!。它只是一个更简单的 dbg!,只是改了个名字。

rust playground 中运行此代码

fn main() {
/// copy of the macro dbg!, just modified :#? to :# for pretty print
#[macro_export]
macro_rules! pretty_dbg {
    () => {
        std::eprintln!("[{}:{}:{}]", std::file!(), std::line!(), std::column!())
    };
    ($val:expr $(,)?) => {
        match $val {
            tmp => {
                std::eprintln!("[{}:{}:{}] {} = {:#}",
                    std::file!(), std::line!(), std::column!(), std::stringify!($val), &tmp);
                tmp
            }
        }
    };
    ($($val:expr),+ $(,)?) => {
        ($(std::pretty_dbg!($val)),+,)
    };
}

/// format_dbg! is a version of dbg! that uses the formatting rules from the macro eprintln!
/// Just like dbg!, it prefixes the stderr output with file!, line! and column!
#[macro_export]
macro_rules! format_dbg {
    ($($arg:tt)*) => {{
        std::eprint!("[{}:{}:{}] ", std::file!(), std::line!(), std::column!());
        std::eprintln!($($arg)*);
    }};
}
    let val="123456789";

    dbg!("using the dbg! macro : {val}");
    pretty_dbg!("using the pretty_dbg! macro : {val}");
    format_dbg!("using the format_dbg! macro : {val}");
}

在 crates.io 中创建新的 crate 或不创建

我认为这也许太小,不足以创建一个新的 crate。
它只是一个简单的宏。
目前,我只是在需要它的项目中添加这个宏的代码。

我改变了主意。我将发布一个微 crate,并使其成为典范,因为它非常小巧。
我将添加测试、示例、playground 代码、文档等我能做的。

在 Rust Playground 中玩耍

在 Rust playground 中尝试短小的 Rust 代码真是太棒了!它既快又简单。它只需要一个浏览器即可工作。展示真实代码的例子,而不仅仅是假设的代码,真是太棒了。
我首先为我的代码示例创建了 Github Gists。每个示例都必须在单独的 Gist 中。然后我将 Gist 的识别号复制到 playground 链接中,如下所示:https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=d5d5e264b9143f4fde16594eaea1fa09,它就可以正常工作。太棒了!

我不想在我的示例中使用 unwrap()。Unwrap 是一个坏习惯。相反,我将使用 crate anyhow 以及它的类型 ResultError 直接在 main() 函数中。这样我就可以在代码中使用错误传播符号 ?,就像专业人士一样。

错误/标准输出集成测试

默认情况下,集成测试会捕获标准输出并并行运行。但在我这里,这正是我不希望看到的。
我需要捕获错误/标准输出,因为这正是 pretty_dbg! 宏工作原理的全部要点。在处理标准输出/错误时,代码不能并行运行,因为这会混合来自不同代码的输出,使其变得像乱炖蛋。
修改我的自动化任务中的代码和调用参数以以这种方式运行测试花了一些时间。
我发现了一个可以捕获错误/标准输出的crate gag,并为我的集成测试使用了宏。这对于CLI应用的大量测试将非常有用。

开发细节

在单独的md文件中阅读开发细节
DEVELOPMENT.md

发布变更日志

在单独的md文件中阅读变更日志
RELEASES.md

待办事项

近期内没有大事。

开源且免费如啤酒

我的开源项目免费如啤酒(MIT许可证)。
我简直热爱编程。
但我也需要喝酒。如果您觉得我的项目和教程有帮助,请通过向我捐赠来买我一杯啤酒PayPal
您知道您当地酒吧啤酒的价格;-)
所以我可以为您喝一杯免费啤酒,祝您健康 :-)
Na zdravje! Alla salute! Prost! Nazdravlje! 🍻

//bestia.dev
//github.com/bestia-dev
//bestiadev.substack.com
//youtube.com/@bestia-dev-tutorials

无运行时依赖