1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-29 12:07:46 +00:00

Merge pull request #2586 from Funky185540/docs/document-macros

macros: Add documentation with examples to macros
This commit is contained in:
Sylvestre Ledru 2021-11-19 21:50:38 +01:00 committed by GitHub
commit 6c6e047453
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1,3 +1,37 @@
//! Macros for the uucore utilities.
//!
//! This module bundles all macros used across the uucore utilities. These
//! include macros for reporting errors in various formats, aborting program
//! execution and more.
//!
//! To make use of all macros in this module, they must be imported like so:
//!
//! ```ignore
//! #[macro_use]
//! extern crate uucore;
//! ```
//!
//! Alternatively, you can import single macros by importing them through their
//! fully qualified name like this:
//!
//! ```no_run
//! use uucore::{show, crash};
//! ```
//!
//! Here's an overview of the macros sorted by purpose
//!
//! - Print errors
//! - From types implementing [`crate::error::UError`]: [`show!`],
//! [`show_if_err!`]
//! - From custom messages: [`show_error!`], [`show_usage_error!`]
//! - Print warnings: [`show_warning!`]
//! - Terminate util execution
//! - Terminate regularly: [`exit!`], [`return_if_err!`]
//! - Crash program: [`crash!`], [`crash_if_err!`], [`safe_unwrap!`]
//! - Unwrapping result types: [`safe_unwrap!`]
// spell-checker:ignore sourcepath targetpath
use std::sync::atomic::AtomicBool;
// This file is part of the uutils coreutils package.
@ -12,6 +46,45 @@ pub static UTILITY_IS_SECOND_ARG: AtomicBool = AtomicBool::new(false);
//====
/// Display a [`crate::error::UError`] and set global exit code.
///
/// Prints the error message contained in an [`crate::error::UError`] to stderr
/// and sets the exit code through [`crate::error::set_exit_code`]. The printed
/// error message is prepended with the calling utility's name. A call to this
/// macro will not finish program execution.
///
/// # Examples
///
/// The following example would print a message "Some error occurred" and set
/// the utility's exit code to 2.
///
/// ```
/// # #[macro_use]
/// # extern crate uucore;
///
/// use uucore::error::{self, USimpleError};
///
/// fn main() {
/// let err = USimpleError::new(2, "Some error occurred.");
/// show!(err);
/// assert_eq!(error::get_exit_code(), 2);
/// }
/// ```
///
/// If not using [`crate::error::UError`], one may achieve the same behavior
/// like this:
///
/// ```
/// # #[macro_use]
/// # extern crate uucore;
///
/// use uucore::error::set_exit_code;
///
/// fn main() {
/// set_exit_code(2);
/// show_error!("Some error occurred.");
/// }
/// ```
#[macro_export]
macro_rules! show(
($err:expr) => ({
@ -21,6 +94,36 @@ macro_rules! show(
})
);
/// Display an error and set global exit code in error case.
///
/// Wraps around [`show!`] and takes a [`crate::error::UResult`] instead of a
/// [`crate::error::UError`] type. This macro invokes [`show!`] if the
/// [`crate::error::UResult`] is an `Err`-variant. This can be invoked directly
/// on the result of a function call, like in the `install` utility:
///
/// ```ignore
/// show_if_err!(copy(sourcepath, &targetpath, b));
/// ```
///
/// # Examples
///
/// ```ignore
/// # #[macro_use]
/// # extern crate uucore;
/// # use uucore::error::{UError, UIoError, UResult, USimpleError};
///
/// # fn main() {
/// let is_ok = Ok(1);
/// // This does nothing at all
/// show_if_err!(is_ok);
///
/// let is_err = Err(USimpleError::new(1, "I'm an error").into());
/// // Calls `show!` on the contained USimpleError
/// show_if_err!(is_err);
/// # }
/// ```
///
///
#[macro_export]
macro_rules! show_if_err(
($res:expr) => ({
@ -31,6 +134,19 @@ macro_rules! show_if_err(
);
/// Show an error to stderr in a similar style to GNU coreutils.
///
/// Takes a [`format!`]-like input and prints it to stderr. The output is
/// prepended with the current utility's name.
///
/// # Examples
///
/// ```
/// # #[macro_use]
/// # extern crate uucore;
/// # fn main() {
/// show_error!("Couldn't apply {} to {}", "foo", "bar");
/// # }
/// ```
#[macro_export]
macro_rules! show_error(
($($args:tt)+) => ({
@ -40,6 +156,17 @@ macro_rules! show_error(
);
/// Show a warning to stderr in a similar style to GNU coreutils.
///
/// Is this really required? Used in the following locations:
///
/// ./src/uu/head/src/head.rs:12
/// ./src/uu/head/src/head.rs:424
/// ./src/uu/head/src/head.rs:427
/// ./src/uu/head/src/head.rs:430
/// ./src/uu/head/src/head.rs:453
/// ./src/uu/du/src/du.rs:339
/// ./src/uu/wc/src/wc.rs:270
/// ./src/uu/wc/src/wc.rs:273
#[macro_export]
macro_rules! show_error_custom_description (
($err:expr,$($args:tt)+) => ({
@ -48,6 +175,21 @@ macro_rules! show_error_custom_description (
})
);
/// Print a warning message to stderr.
///
/// Takes [`format!`]-compatible input and prepends it with the current
/// utility's name and "warning: " before printing to stderr.
///
/// # Examples
///
/// ```
/// # #[macro_use]
/// # extern crate uucore;
/// # fn main() {
/// // outputs <name>: warning: Couldn't apply foo to bar
/// show_warning!("Couldn't apply {} to {}", "foo", "bar");
/// # }
/// ```
#[macro_export]
macro_rules! show_warning(
($($args:tt)+) => ({
@ -57,6 +199,21 @@ macro_rules! show_warning(
);
/// Show a bad invocation help message in a similar style to GNU coreutils.
///
/// Takes a [`format!`]-compatible input and prepends it with the current
/// utility's name before printing to stderr.
///
/// # Examples
///
/// ```
/// # #[macro_use]
/// # extern crate uucore;
/// # fn main() {
/// // outputs <name>: Couldn't apply foo to bar
/// // Try '<name> --help' for more information.
/// show_usage_error!("Couldn't apply {} to {}", "foo", "bar");
/// # }
/// ```
#[macro_export]
macro_rules! show_usage_error(
($($args:tt)+) => ({
@ -68,7 +225,9 @@ macro_rules! show_usage_error(
//====
/// Calls `exit()` with the provided exit code.
/// Calls [`std::process::exit`] with the provided exit code.
///
/// Why not call exit directly?
#[macro_export]
macro_rules! exit(
($exit_code:expr) => ({
@ -76,7 +235,22 @@ macro_rules! exit(
})
);
/// Display the provided error message, then `exit()` with the provided exit code
/// Display an error and [`exit!`]
///
/// Displays the provided error message using [`show_error!`], then invokes
/// [`exit!`] with the provided exit code.
///
/// # Examples
///
/// ```should_panic
/// # #[macro_use]
/// # extern crate uucore;
/// # fn main() {
/// // outputs <name>: Couldn't apply foo to bar
/// // and terminates execution
/// crash!(1, "Couldn't apply {} to {}", "foo", "bar");
/// # }
/// ```
#[macro_export]
macro_rules! crash(
($exit_code:expr, $($args:tt)+) => ({
@ -85,8 +259,26 @@ macro_rules! crash(
})
);
/// Unwraps the Result. Instead of panicking, it exists the program with the
/// provided exit code.
/// Unwrap a [`std::result::Result`], crashing instead of panicking.
///
/// If the result is an `Ok`-variant, returns the value contained inside. If it
/// is an `Err`-variant, invokes [`crash!`] with the formatted error instead.
///
/// # Examples
///
/// ```should_panic
/// # #[macro_use]
/// # extern crate uucore;
/// # fn main() {
/// let is_ok: Result<u32, &str> = Ok(1);
/// // Does nothing
/// crash_if_err!(1, is_ok);
///
/// let is_err: Result<u32, &str> = Err("This didn't work...");
/// // Calls `crash!`
/// crash_if_err!(1, is_err);
/// # }
/// ```
#[macro_export]
macro_rules! crash_if_err(
($exit_code:expr, $exp:expr) => (
@ -97,18 +289,42 @@ macro_rules! crash_if_err(
)
);
//====
/// Unwrap some Result, crashing instead of panicking.
///
/// Drop this in favor of `crash_if_err!`
#[macro_export]
macro_rules! safe_write(
($fd:expr, $($args:tt)+) => (
match write!($fd, $($args)+) {
Ok(_) => {}
Err(f) => panic!("{}", f)
macro_rules! safe_unwrap(
($exp:expr) => (
match $exp {
Ok(m) => m,
Err(f) => $crate::crash!(1, "{}", f.to_string())
}
)
);
//====
/// Unwraps the Result. Instead of panicking, it shows the error and then
/// returns from the function with the provided exit code.
/// Assumes the current function returns an i32 value.
///
/// Replace with `crash_if_err`?
#[macro_export]
macro_rules! return_if_err(
($exit_code:expr, $exp:expr) => (
match $exp {
Ok(m) => m,
Err(f) => {
$crate::show_error!("{}", f);
return $exit_code;
}
}
)
);
//====
/// This is used exclusively by du...
#[macro_export]
macro_rules! safe_writeln(
($fd:expr, $($args:tt)+) => (
@ -123,6 +339,7 @@ macro_rules! safe_writeln(
//-- message templates : (join utility sub-macros)
// used only by "cut"
#[macro_export]
macro_rules! snippet_list_join_oxford_comma {
($conjunction:expr, $valOne:expr, $valTwo:expr) => (
@ -133,6 +350,7 @@ macro_rules! snippet_list_join_oxford_comma {
);
}
// used only by "cut"
#[macro_export]
macro_rules! snippet_list_join {
($conjunction:expr, $valOne:expr, $valTwo:expr) => (
@ -167,6 +385,7 @@ macro_rules! msg_invalid_opt_use {
};
}
// Only used by "cut"
#[macro_export]
macro_rules! msg_opt_only_usable_if {
($clause:expr, $flag:expr) => {
@ -181,6 +400,7 @@ macro_rules! msg_opt_only_usable_if {
};
}
// Used only by "cut"
#[macro_export]
macro_rules! msg_opt_invalid_should_be {
($expects:expr, $received:expr, $flag:expr) => {
@ -200,6 +420,7 @@ macro_rules! msg_opt_invalid_should_be {
// -- message templates : invalid input : input combinations
// UNUSED!
#[macro_export]
macro_rules! msg_expects_one_of {
($valOne:expr $(, $remaining_values:expr)*) => (
@ -207,6 +428,7 @@ macro_rules! msg_expects_one_of {
);
}
// Used only by "cut"
#[macro_export]
macro_rules! msg_expects_no_more_than_one_of {
($valOne:expr $(, $remaining_values:expr)*) => (