16 个稳定版本
1.2.8 | 2020 年 5 月 14 日 |
---|---|
1.2.7 | 2020 年 5 月 2 日 |
1.2.4 | 2020 年 4 月 29 日 |
1.1.0 | 2019 年 12 月 1 日 |
1.0.1 | 2019 年 6 月 25 日 |
#1 in #error-chain
每月 709 次下载
用于 11 个 crate(6 个直接使用)
37KB
397 行
UserFacingError
为你的 CLI 应用程序提供美观的错误打印。
此仓库包含
- 一个新的特性,UFE,你可以将其实现在你自己的错误类型上以打印它们
- 一个新的类型,UserFacingError,你可以用它来构建美观的 CLI 错误消息
- 可以将你的错误类型转换为 UserFacingError
UserFacingError 是一个错误类型或特性,它帮助你为 CLI 应用的用户提供格式化和打印美观的错误消息。这些错误旨在供人类消费,而不是你的程序。它们分为三个部分:摘要、原因和帮助文本。
摘要: 表示你的错误单行描述的 String。摘要强制,并以粗体红色打印。
原因: 一个 String 向量,更详细地解释了错误发生的 原因。原因是可选的,如果终端支持颜色,则项目符号('-')将被着色为黄色。每个原因将单独打印。
帮助文本: 一个 String,解释了额外的信息,包括用户可以做什么来处理错误,或者在哪里提交错误报告。帮助文本是可选的,如果终端支持颜色,它将以暗淡的方式打印。
use user_error::UserFacingError;
fn main() {
UserFacingError::new("Failed to build project")
.reason("Database could not be parsed")
.reason("File \"main.db\" not found")
.help("Try: touch main.db")
.print()
}
这会打印
Error: Failed to build project
- Database could not be parsed
- File "main.db" not found
Try: touch main.db
如果用户在终端上启用了颜色,它可能看起来像这样:
目录
背景
UserFacingError 可以轻松地将错误以合理、美观的格式打印到命令行应用程序的用户。我喜欢 Rust 的 Result 类型,以及使用枚举进行匹配和 &str 进行错误消息。这对开发来说很棒,但不太适合 CLI 应用程序的用户。为此,我创建了一个 UserFacingError
,它可以快速构建一个美观的错误消息,适当地通知用户出了什么问题以及他们可以做什么。
安装
将以下内容添加到您的 Cargo.toml 中
[dependencies]
user-error = "1.2.8"
使用方法
UFE 特性
您可以通过实现 UFE 特征来轻松地在自定义错误类型上实现 UFE 特征,允许您将它们以美观的格式打印到 stderr。UFE 特征要求您的类型也实现 Error 特征。
use user_error::{UserFacingError, UFE};
// Custom Error Type
#[derive(Debug)]
struct MyError { mssg: String, src: Option<Box<dyn Error>> }
impl Display for MyError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.mssg.to_string())
}
}
impl Error for MyError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
self.src.as_deref()
}
}
impl UFE for MyError {}
fn main() {
let me = MyError {
mssg: "Program Failed".into(),
src: Some(Box::new(MyError {
mssg: "Reason 1".into(),
src: Some(Box::new(MyError {
mssg: "Reason 2".into(),
src: None,
})),
})),
};
me.print();
}
这会打印
Error: Program Failed
- Reason 1
- Reason 2
默认实现
您可以可选地实现以下三个函数
.summary() -> String
- 返回用作错误摘要的字符串.reasons() -> Option<Vec<String>>
- 可选地返回表示错误原因的字符串 Vec.helptext() -> Option<String>
- 可选地返回表示如何解决错误的字符串
摘要
默认情况下,错误摘要是通过调用 .to_string()
在错误上获得的字符串,并在前面加上 "Error: "。
原因
默认情况下,通过递归调用 .source()
创建原因列表,并为链中的每个错误前加上一个项目符号。
帮助文本
默认情况下,不会向实现 UFE 的自定义类型添加 helptext。您将不得不提供自己的实现,或者调用 .into_ufe()
将您的错误类型转换为 UserFacingError,并使用提供的 .help(&str)
函数添加一个。
特性方法
UFE 提供了三个有用的方法
.print()
- 美观地打印错误.print_and_exit()
- 美观地打印错误并终止进程.into_ufe()
- 消费自定义 Error 类型并返回 UserFacingError
您可以重写这些方法,但使用此包就没有多少意义了 :p
这会打印
Error: Program Failed!
- Bad luck
打印
将 UserFacingError 美观地打印到 stderr。
use user_error::UserFacingError;
fn main() {
UserFacingError::new("Failed to build project")
.reason("Database config could not be parsed")
.reason("`db.config` not found")
.help("Try: touch db.config")
.print_and_exit();
}
这会打印
Error: Failed to build project
- Database config could not be parsed
- `db.config` not found
Try: touch db.config
打印并退出
由于构建此错误可能是您的程序要做的最后一件事,因此您还可以调用 .print_and_exit()
来打印错误,然后使用状态代码 1 终止进程,以提供便利。
use user_error::UserFacingError;
fn main() {
UserFacingError::new("Failed to build project")
.reason("Database config could not be parsed")
.print_and_exit();
}
这会打印
Error: Failed to build project
- Database config could not be parsed
转换为 UFE
消耗自定义错误类型并返回 UserFacingError。在退出程序之前,如果要修改摘要、原因列表或帮助文本,则很有用。
use user_error::{UserFacingError, UFE}
fn main() {
let me = MyError { ... };
me.into_ufe().help("Added helptext").print();
}
这会打印
Error: Failed to build project
- Database config could not be parsed
UserFacingError 类型
构造
创建新的 UserFacingError 有两种方式
- 使用构建器模式
- 从其他 std Errors
构建器模式
use user_error::UserFacingError;
fn main() {
UserFacingError::new("Failed to build project")
.reason("Database could not be parsed")
.reason("File \"main.db\" not found")
.help("Try: touch main.db")
.print()
}
这会打印
Error: Failed to build project
- Database could not be parsed
- File "main.db" not found
Try: touch main.db
如果用户在终端上启用了颜色,它可能看起来像这样:
从其他错误类型
您还可以从实现 std::error::Error 的其他类型创建 UserFacingError。
摘要将是 error.to_string() 的结果,而原因列表将是通过递归调用 .source() 构造的错误链中的任何错误。
use user_error::UserFacingError;
use std::io::(Error, ErrorKind);
fn main() {
/* Lose the type */
fn dyn_error() -> Box<dyn Error> {
let ioe = Error::new(ErrorKind::Other, "MyError");
Box::new(ioe)
}
/* Convert to UFE */
let ufe: UserFacingError = dyn_error().into();
}
方法
UserFacingError 有 6 个非构建器方法
.update(&str)
- 更改错误摘要.push(&str)
- 更改错误摘要,将以前的摘要添加到原因列表中.clear_reasons()
- 删除所有原因.clear_help()
- 删除帮助文本.print()
- 美化打印错误(使用默认 UFE 实现).print_and_exit()
- 美化打印错误并终止进程(使用默认 UFE 实现)
更新
您可以在 UserFacingError 上调用 .update(&str)
来更改错误摘要。
use user_error::UserFacingError;
fn do_thing() -> Result<(), UserFacingError> {
Err(UserFacingError::new("Didn't do the thing!")
.reason("Just didn't happen"))
}
fn main() {
match do_thing() {
Ok(_) => println!("Success!"),
Err(E) => {
e.update("Program Failed!").print()
}
}
}
这会打印
Error: Program Failed!
- Just didn't happen
推送
您可以在 UserFacingError 上调用 .push(&str)
来更改错误摘要并将旧错误摘要添加到原因列表中。它将摘要添加到原因列表的前面。
use user_error::UserFacingError;
fn do_thing() -> Result<(), UserFacingError> {
Err(UserFacingError::new("Didn't do the thing!")
.reason("Just didn't happen"))
}
fn main() {
match do_thing() {
Ok(_) => println!("Success!"),
Err(E) => {
e.update("Program Failed!").print()
}
}
}
这会打印
Error: Program Failed!
- Didn't do the thing!
- Just didn't happen
清除原因
调用此方法将删除 UserFacingError 中的所有原因。
use user_error::UserFacingError;
fn main() {
let ufe = UserFacingError::new("Program Failed!")
.reason("Program internal error message");
/* --- */
ufe.clear_reasons();
ufe.print_and_exit();
}
这会打印
Error: Program Failed!
清除帮助文本
调用此方法将删除 UserFacingError 中的帮助文本。
use user_error::UserFacingError;
fn main() {
let ufe = UserFacingError::new("Program Failed!")
.reason("Bad luck")
.help("Try running it again?");
/* --- */
ufe.clear_help();
ufe.print_and_exit();
}
这会打印
Error: Program Failed!
- Bad luck
维护者
- Amy Jie @xvrqt
贡献
请随意深入了解! 打开问题 或提交 PRs。
贡献者
- Amy Jie @xvrqt
许可证
MIT © Amy Jie