Version 0.2.0

This commit is contained in:
Travis Burtrum 2019-02-22 00:55:11 -05:00
parent 732a515996
commit 5b79867caa
5 changed files with 95 additions and 43 deletions

View File

@ -7,4 +7,3 @@ matrix:
script: script:
- cargo test - cargo test
- rustdoc --test README.md -L target

2
Cargo.lock generated
View File

@ -2,5 +2,5 @@
# It is not intended for manual editing. # It is not intended for manual editing.
[[package]] [[package]]
name = "die" name = "die"
version = "0.1.0" version = "0.2.0"

View File

@ -1,6 +1,6 @@
[package] [package]
name = "die" name = "die"
version = "0.1.0" version = "0.2.0"
authors = ["moparisthebest <admin@moparisthebest.com>"] authors = ["moparisthebest <admin@moparisthebest.com>"]
description = "Handle errors and exit in command line programs easily." description = "Handle errors and exit in command line programs easily."

View File

@ -11,7 +11,33 @@
```toml ```toml
# Cargo.toml # Cargo.toml
[dependencies] [dependencies]
die = "0.1" die = "0.2"
```
Example usage:
```rust
use die::Die;
// Result:
Ok(1).die("no number"); // unwraps to 1 successfully
Err("failure").die("strange error"); // prints `strange error` to stderr then exits with code 1
// Option:
Some(1).die("no number"); // unwraps to 1 successfully
None.die("none option"); // prints `none option` to stderr then exits with code 1
// custom error codes:
Err("failure").die_code("strange error", 4); // prints `strange error` to stderr then exits with code 4
None.die_code("none option", 5); // prints `none option` to stderr then exits with code 5
// die! macro:
die!("argument to -e must be numeric"); // prints message to stderr then exits with code 1
die!(2; "argument to -e must be numeric"); // prints message to stderr then exits with code 2
die!("argument to -e must be numeric"; 3); // prints message to stderr then exits with code 3
die!("argument {} must be {}", "-e", 1; 4); // prints `argument -e must be 1` to stderr then exits with code 4
die!("argument {} must be {}", "-e", 1); // prints `argument -e must be 1` to stderr then exits with code 1
die!(2); // prints nothing, only exits with code 3
die!(); // prints nothing, only exits with code 1
``` ```
# License # License

View File

@ -6,55 +6,60 @@
use std::process; use std::process;
/// const of 1
pub const DEFAULT_EXIT_CODE: i32 = 1; pub const DEFAULT_EXIT_CODE: i32 = 1;
/// Prints a message to stderr and terminates the current process with the specified exit code /// Prints a message to [`stderr`] and terminates the current process with the specified exit code
/// or 1 if no exit code is specified, by calling eprintln!() on all arguments followed by /// or 1 if no exit code is specified, by calling [`eprintln`]!() on all arguments followed by
/// process::exit(exit_code) /// [process::exit(exit_code)][exit]
///
/// [`eprintln`]: https://doc.rust-lang.org/std/macro.eprintln.html
/// [`stderr`]: https://doc.rust-lang.org/std/io/fn.stderr.html
/// [exit]: https://doc.rust-lang.org/std/process/fn.exit.html
/// ///
/// # Examples /// # Examples
/// ///
/// Basic usage: /// Basic usage:
/// ///
/// ```{.should_panic} /// ```{.should_panic}
/// use die::die; /// # use die::die;
/// die!("argument to -e must be numeric"); // prints message to stderr then exits with code 1 /// die!("argument to -e must be numeric"); // prints message to stderr then exits with code 1
/// ``` /// ```
/// With custom error code: /// With custom error code:
/// ```{.should_panic} /// ```{.should_panic}
/// use die::die; /// # use die::die;
/// die!(2; "argument to -e must be numeric"); // prints message to stderr then exits with code 2 /// die!(2; "argument to -e must be numeric"); // prints message to stderr then exits with code 2
/// ``` /// ```
/// error code can go at the beginning or end, just separate with colon: /// error code can go at the beginning or end, just separate with colon:
/// ```{.should_panic} /// ```{.should_panic}
/// use die::die; /// # use die::die;
/// die!("argument to -e must be numeric"; 3); // prints message to stderr then exits with code 3 /// die!("argument to -e must be numeric"; 3); // prints message to stderr then exits with code 3
/// ``` /// ```
/// supports all the formatting eprintln! does: /// supports all the formatting eprintln! does:
/// ```{.should_panic} /// ```{.should_panic}
/// use die::die; /// # use die::die;
/// die!("argument {} must be {}", "-e", 1; 4); // prints `argument -e must be 1` to stderr then exits with code 4 /// die!("argument {} must be {}", "-e", 1; 4); // prints `argument -e must be 1` to stderr then exits with code 4
/// ``` /// ```
/// supports all the formatting eprintln! does without exit code too: /// supports all the formatting eprintln! does without exit code too:
/// ```{.should_panic} /// ```{.should_panic}
/// use die::die; /// # use die::die;
/// die!("argument {} must be {}", "-e", 1); // prints `argument -e must be 1` to stderr then exits with code 1 /// die!("argument {} must be {}", "-e", 1); // prints `argument -e must be 1` to stderr then exits with code 1
/// ``` /// ```
/// just exit with a code alone: /// just exit with a code alone:
/// ```{.should_panic} /// ```{.should_panic}
/// use die::die; /// # use die::die;
/// die!(2); // prints nothing, only exits with code 3 /// die!(2); // prints nothing, only exits with code 3
/// ``` /// ```
/// just exit: /// just exit:
/// ```{.should_panic} /// ```{.should_panic}
/// use die::die; /// # use die::die;
/// die!(); // prints nothing, only exits with code 1 /// die!(); // prints nothing, only exits with code 1
/// ``` /// ```
#[macro_export] #[macro_export]
macro_rules! die { macro_rules! die {
() => (::std::process::exit(::die::DEFAULT_EXIT_CODE)); () => (::std::process::exit(::die::DEFAULT_EXIT_CODE));
($x:expr) => (::die::PrintExit::process(&$x)); ($x:expr) => (::die::PrintExit::print_exit(&$x));
($x:expr; $y:expr) => (::die::PrintExit::process(&($x, $y))); ($x:expr; $y:expr) => (::die::PrintExit::print_exit(&($x, $y)));
($x:expr; $($y:expr),+) => ({ ($x:expr; $($y:expr),+) => ({
eprintln!($($y),+); eprintln!($($y),+);
::std::process::exit($x) ::std::process::exit($x)
@ -69,50 +74,72 @@ macro_rules! die {
}); });
} }
/// `Die` is a trait implemented on [`Result`] and [`Option`] to make exiting with messages and codes easy
///
/// [`Result`]: https://doc.rust-lang.org/std/result/enum.Result.html
/// [`Option`]: https://doc.rust-lang.org/std/option/enum.Option.html
pub trait Die<T> { pub trait Die<T> {
/// Unwraps a result/option, yielding the content of an [`Ok`] or [`Some`]. /// Unwraps a [`Result`] or [`Option`], yielding the content of an [`Ok`] or [`Some`].
/// ///
/// # Exits /// # Exits
/// ///
/// Calls process::exit(1) if the value is an [`Err`]/[`None`], after printing the /// Calls [process::exit(1)][exit] if the value is an [`Err`] or [`None`], after printing the
/// passed message to stderr. /// passed message to [`stderr`].
/// ///
/// [`Ok`]: enum.Result.html#variant.Ok /// [`stderr`]: https://doc.rust-lang.org/std/io/fn.stderr.html
/// [`Err`]: enum.Result.html#variant.Err /// [exit]: https://doc.rust-lang.org/std/process/fn.exit.html
/// [`Some`]: enum.Option.html#variant.Some /// [`Result`]: https://doc.rust-lang.org/std/result/enum.Result.html
/// [`None`]: enum.Option.html#variant.None /// [`Option`]: https://doc.rust-lang.org/std/option/enum.Option.html
/// [`Ok`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Ok
/// [`Err`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err
/// [`Some`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.Some
/// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None
/// ///
/// # Examples /// # Examples
/// ///
/// Basic usage: /// Basic usage:
/// ///
/// ```{.should_panic} /// ```{.should_panic}
/// use die::Die; /// # use die::Die;
/// let x: Result<u32, &str> = Err("emergency failure"); /// let x: Result<u32, &str> = Err("emergency failure");
/// x.die("strange error"); // prints `strange error` to stderr then exits with code 1 /// x.die("strange error"); // prints `strange error` to stderr then exits with code 1
/// ``` /// ```
/// ```{.should_panic}
/// # use die::Die;
/// let x: Option<u32> = None;
/// x.die("strange error"); // prints `strange error` to stderr then exits with code 1
/// ```
fn die(self, msg: &str) -> T; fn die(self, msg: &str) -> T;
/// Unwraps a result/option, yielding the content of an [`Ok`] or [`Some`]. /// Unwraps a [`Result`] or [`Option`], yielding the content of an [`Ok`] or [`Some`].
/// ///
/// # Exits /// # Exits
/// ///
/// Calls process::exit(exit_code) if the value is an [`Err`]/[`None`], after printing the /// Calls [process::exit(exit_code)][exit] if the value is an [`Err`] or [`None`], after printing the
/// passed message to stderr. /// passed message to [`stderr`].
/// ///
/// [`Ok`]: enum.Result.html#variant.Ok /// [`stderr`]: https://doc.rust-lang.org/std/io/fn.stderr.html
/// [`Err`]: enum.Result.html#variant.Err /// [exit]: https://doc.rust-lang.org/std/process/fn.exit.html
/// [`Some`]: enum.Option.html#variant.Some /// [`Result`]: https://doc.rust-lang.org/std/result/enum.Result.html
/// [`None`]: enum.Option.html#variant.None /// [`Option`]: https://doc.rust-lang.org/std/option/enum.Option.html
/// [`Ok`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Ok
/// [`Err`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err
/// [`Some`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.Some
/// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None
/// ///
/// # Examples /// # Examples
/// ///
/// Basic usage: /// Basic usage:
/// ///
/// ```{.should_panic} /// ```{.should_panic}
/// use die::Die; /// # use die::Die;
/// let x: Result<u32, &str> = Err("emergency failure"); /// let x: Result<u32, &str> = Err("emergency failure");
/// x.die_code("strange error", 3); // prints `strange error` to stderr then exits with code 3 /// x.die_code("strange", 3); // prints `strange` to stderr then exits with code 3
/// ```
/// ```{.should_panic}
/// # use die::Die;
/// let x: Option<u32> = None;
/// x.die_code("strange", 3); // prints `strange` to stderr then exits with code 3
/// ``` /// ```
fn die_code(self, msg: &str, exit_code: i32) -> T; fn die_code(self, msg: &str, exit_code: i32) -> T;
} }
@ -126,7 +153,7 @@ impl<T, E> Die<T> for Result<T, E> {
fn die_code(self, msg: &str, exit_code: i32) -> T { fn die_code(self, msg: &str, exit_code: i32) -> T {
match self { match self {
Ok(t) => t, Ok(t) => t,
Err(_) => PrintExit::process(&(exit_code, msg)), Err(_) => PrintExit::print_exit(&(exit_code, msg)),
} }
} }
} }
@ -140,26 +167,26 @@ impl<T> Die<T> for Option<T> {
fn die_code(self, msg: &str, exit_code: i32) -> T { fn die_code(self, msg: &str, exit_code: i32) -> T {
match self { match self {
Some(t) => t, Some(t) => t,
None => PrintExit::process(&(exit_code, msg)), None => PrintExit::print_exit(&(exit_code, msg)),
} }
} }
} }
pub trait PrintExit { pub trait PrintExit {
#[inline] #[inline]
fn process(&self) -> !; fn print_exit(&self) -> !;
} }
impl PrintExit for i32 { impl PrintExit for i32 {
#[inline] #[inline]
fn process(&self) -> ! { fn print_exit(&self) -> ! {
process::exit(*self) process::exit(*self)
} }
} }
impl PrintExit for &str { impl PrintExit for &str {
#[inline] #[inline]
fn process(&self) -> ! { fn print_exit(&self) -> ! {
eprintln!("{}", self); eprintln!("{}", self);
process::exit(DEFAULT_EXIT_CODE) process::exit(DEFAULT_EXIT_CODE)
} }
@ -167,7 +194,7 @@ impl PrintExit for &str {
impl PrintExit for String { impl PrintExit for String {
#[inline] #[inline]
fn process(&self) -> ! { fn print_exit(&self) -> ! {
eprintln!("{}", self); eprintln!("{}", self);
process::exit(DEFAULT_EXIT_CODE) process::exit(DEFAULT_EXIT_CODE)
} }
@ -175,7 +202,7 @@ impl PrintExit for String {
impl PrintExit for (i32, &str) { impl PrintExit for (i32, &str) {
#[inline] #[inline]
fn process(&self) -> ! { fn print_exit(&self) -> ! {
eprintln!("{}", self.1); eprintln!("{}", self.1);
process::exit(self.0) process::exit(self.0)
} }
@ -183,7 +210,7 @@ impl PrintExit for (i32, &str) {
impl PrintExit for (i32, String) { impl PrintExit for (i32, String) {
#[inline] #[inline]
fn process(&self) -> ! { fn print_exit(&self) -> ! {
eprintln!("{}", self.1); eprintln!("{}", self.1);
process::exit(self.0) process::exit(self.0)
} }
@ -191,7 +218,7 @@ impl PrintExit for (i32, String) {
impl PrintExit for (&str, i32) { impl PrintExit for (&str, i32) {
#[inline] #[inline]
fn process(&self) -> ! { fn print_exit(&self) -> ! {
eprintln!("{}", self.0); eprintln!("{}", self.0);
process::exit(self.1) process::exit(self.1)
} }
@ -199,7 +226,7 @@ impl PrintExit for (&str, i32) {
impl PrintExit for (String, i32) { impl PrintExit for (String, i32) {
#[inline] #[inline]
fn process(&self) -> ! { fn print_exit(&self) -> ! {
eprintln!("{}", self.0); eprintln!("{}", self.0);
process::exit(self.1) process::exit(self.1)
} }