UserError

UserError is an error type that helps you format and print good looking error messages for users of your CLI application. These errors are intended for consumption by a human, not your program. They are divided into 3 parts: summary, reasons and subtleties.

Summary: A String representing a one-line description of your error. A summary is mandatory and is printed boldly in red.

Reasons: A vector of Strings explaining in more detail why this error occured. Reasons are optional and if the terminal supports color, the bullet point ('-') will be colored yellow. Each reason will be printed on its own line.

Sublteties: A vector of Strings explaining additional information, including what the user can do about the error, or where to file a bug. Sublteties are optionals and if the terminal supports color, subtleties will be printed dimly. Each subtly will be printed on its own line

Coercion

std::io::Error, Err(String) and Err(&str) can all be coerced into a UserError. See the docs for examples.

Docs

The docs are really good for this crate. In addition to reading this README you can find tons of examples in the documentation generated by Cargo.

Quickstart

Add the following to your Cargo.toml: yaml [dependencies] user-error = "1.0.0"

Add the following to your main.rs/lib.rs: ```rust use user_error::UserError;

fn main() { let e = UserError::hardcoded("Failed to build project", &[ "Database could not be parsed", "File \"main.db\" not found"], &[ "Try: touch main.db", "This command will create and empty database file the program can use"]); eprintln!("{}", e); } This prints: text Error: Failed to build project - Database could not be parsed - File "main.db" not found Try: touch main.db This command will create and empty database file the program can use ``` If the user has colors enabled on their terminal, it may look something like this: Quickstart example of user-error library for Rust

Examples

Creating Errors

If you're a flawless being like me, you are probably wondering how one makes a UserError, here are examples of the different ways:

Simple Error

Creates an error with only a summary. ```rust use user_error::UserError;

fn main() { let e = UserError::simple("Failed to build project"); eprintln!("{}", e); } ```

This prints: text Error: Failed to build project

Static Error

Creates an error from hardcoded &str's ```rust use user_error::UserError;

fn main() { let e = UserError::hardcoded("Failed to build project", &[ "Database could not be parsed", "File \"main.db\" not found"], &[ "Try: touch main.db", "This command will create and empty database file the program can use"]); eprintln!("{}", e); } This prints: text Error: Failed to build project - Database could not be parsed - File "main.db" not found Try: touch main.db This command will create and empty database file the program can use ```

Dynamic Error

Creates an error using heap allocated structures. ```rust use user_error::UserError;

fn main() { let errorsummary = String::from("Failed to build project"); let errorreasons = vec![String::from("Database could not be parsed"), String::from("File \"main.db\" not found")]; let errorsubtleties = vec![String::from("Try: touch main.db"), String::from("This command will create and empty database file the program can use ")]; let e = UserError::new(errorsummary, errorreasons, errorsubtleties); eprintln!("{}", e); } This prints: text Error: Failed to build project - Database could not be parsed - File "main.db" not found Try: touch main.db This command will create and empty database file the program can use ```

From Other Errors

Certain types of errors will be automagically coerced into a UserError - and will preserve a pointer to the original error (should you need it) Creates an error using heap allocated structures. ```rust use std::fs::File; use user_error::UserError;

// A really redundant way to open a file fn open_file(path: &str) -> Result { let f = File::open(path)?; // std::io::Error is coerced into a UserError here Ok(f) }

fn main() { match openfile("doesnotexist.txt") { Err(e) => eprintln!("{}", e), Ok() => () } } This prints: text Error: No such file or directory (os error 2) ```

Convenience Methods

These methods could save you some boilerplate in the same way unwrap() does.

Print

If for some reason you don't want to follow the format!() convention, you can call print() on a UserError and it will pretty print itself to stderr ```rust use user_error::UserError;

fn main() { let e = UserError::simple("Critical Failure!"); e.print(); } This prints: text Error: Critical Failure! ```

Print and Exit

Since this error is likely the last thing your program will run you can use this shortcut to print the error and exit the process in an immediate, albeit ungraceful manner. Returns error code 1 to the OS. ```rust use user_error::UserError;

fn main() { let e = UserError::simple("Critical Failure!"); e.printandexit(); eprintln("I am never printed!"); } This prints: text Error: Critical Failure! ```

Modifying the Error

There are a few methods for modifying the UserError after it has been made:

Additional information can be found in the documentation.

Future Work