# proxit — Unix-style error messages in Rust `proxit` is a super simple Rust library that allows you to have consistent, UNIX-style error messages with a little bit less boilerplate by implementing the `Termination` trait for you. ## Why? All UNIX commandline utilities have displayed their errors in more-or-less the exact same way since the beginning of time: : and sometimes: Usage: # or usage: For example: $ grep -fakeflags grep: akeflags: No such file or directory $ mandoc bash: mandoc: command not found $ doas usage: doas [-Lns] [-C config] [-u user] command [args] So how did the genius Rust team decide to do it? Let’s check the code: ```rust impl Termination for Result { fn report(self) -> ExitCode { match self { Ok(val) => val.report(), Err(err) => { io::attempt_print_to_stderr(format_args_nl!("Error: {err:?}")); ExitCode::FAILURE } } } } ``` Wait… did I see that right? ```rust … format_args_nl!("Error: {err:?}")); ``` Bruh. ## How Proxit Works Using `proxit` is super simple: ```rust use proxit::MainResult; fn main() -> MainResult<(), Error> { work().into(); } fn work() -> Result<(), Error> { /* … */ } ``` A `MainResult` is just a wrapper around a `Result` where `T` implements `Termination`, and `E` implements `Display`. In practice, `T` will basically always be `()` which does implement `Termination`. When the `main` function returns, if the `Result` within the `MainResult` is an `Ok` variant, then the `.report()` method of `T` is invoked. Otherwise, `E` is printed out to standard error (this is why you need to implement `Display`) prefixed by the string `"{argv0}: "` where `argv0` is the program name. What if you want to print a usage string though? Well… because simpler and simpler is **always** better, just call `eprintln!()` and `process::exit()`. Printing the usage string yourself also gives you the flexibility to decide between GNU- and FreeBSD-style usage strings (`"Usage: {s}"`) and OpenBSD-style usage strings (`"usage: {s}"`). ```rust use std::process; use proxit::{self, MainResult, Usage}; fn main() -> MainResult<(), Error> { work.into(); } fn work() -> Result<(), Error> { if usage_wrong() { eprintln!("Usage: [-abc] required_arg"); process::exit(1); } } ``` ## Additional Note When a process using this library is spawned, the parent process calling `exec()` could potentially not provide the program name in `argv[0]`. In this case, we default to using the Rust style of `"Error: {s}"`.