uucore/macros.rs
1// This file is part of the uutils coreutils package.
2//
3// For the full copyright and license information, please view the LICENSE
4// file that was distributed with this source code.
5
6//! Macros for the uucore utilities.
7//!
8//! This module bundles all macros used across the uucore utilities. These
9//! include macros for reporting errors in various formats, aborting program
10//! execution and more.
11//!
12//! To make use of all macros in this module, they must be imported like so:
13//!
14//! ```ignore
15//! #[macro_use]
16//! extern crate uucore;
17//! ```
18//!
19//! Alternatively, you can import single macros by importing them through their
20//! fully qualified name like this:
21//!
22//! ```no_run
23//! use uucore::show;
24//! ```
25//!
26//! Here's an overview of the macros sorted by purpose
27//!
28//! - Print errors
29//! - From types implementing [`crate::error::UError`]: [`crate::show!`],
30//! [`crate::show_if_err!`]
31//! - From custom messages: [`crate::show_error!`]
32//! - Print warnings: [`crate::show_warning!`]
33
34// spell-checker:ignore sourcepath targetpath rustdoc
35
36use std::sync::atomic::AtomicBool;
37
38// This file is part of the uutils coreutils package.
39//
40// For the full copyright and license information, please view the LICENSE
41// file that was distributed with this source code.
42
43/// Whether we were called as a multicall binary (`coreutils <utility>`)
44pub static UTILITY_IS_SECOND_ARG: AtomicBool = AtomicBool::new(false);
45
46//====
47
48/// Display a [`crate::error::UError`] and set global exit code.
49///
50/// Prints the error message contained in an [`crate::error::UError`] to stderr
51/// and sets the exit code through [`crate::error::set_exit_code`]. The printed
52/// error message is prepended with the calling utility's name. A call to this
53/// macro will not finish program execution.
54///
55/// # Examples
56///
57/// The following example would print a message "Some error occurred" and set
58/// the utility's exit code to 2.
59///
60/// ```
61/// # #[macro_use]
62/// # extern crate uucore;
63///
64/// use uucore::error::{self, USimpleError};
65///
66/// fn main() {
67/// let err = USimpleError::new(2, "Some error occurred.");
68/// show!(err);
69/// assert_eq!(error::get_exit_code(), 2);
70/// }
71/// ```
72///
73/// If not using [`crate::error::UError`], one may achieve the same behavior
74/// like this:
75///
76/// ```
77/// # #[macro_use]
78/// # extern crate uucore;
79///
80/// use uucore::error::set_exit_code;
81///
82/// fn main() {
83/// set_exit_code(2);
84/// show_error!("Some error occurred.");
85/// }
86/// ```
87#[macro_export]
88macro_rules! show(
89 ($err:expr) => ({
90 #[allow(unused_imports)]
91 use $crate::error::UError;
92 let e = $err;
93 $crate::error::set_exit_code(e.code());
94 use std::io::Write as _;
95 let _ = writeln!(std::io::stderr().lock(), "{}: {e}", $crate::util_name());
96 })
97);
98
99/// Display an error and set global exit code in error case.
100///
101/// Wraps around [`crate::show!`] and takes a [`crate::error::UResult`] instead of a
102/// [`crate::error::UError`] type. This macro invokes [`crate::show!`] if the
103/// [`crate::error::UResult`] is an `Err`-variant. This can be invoked directly
104/// on the result of a function call, like in the `install` utility:
105///
106/// ```ignore
107/// show_if_err!(copy(sourcepath, &targetpath, b));
108/// ```
109///
110/// # Examples
111///
112/// ```ignore
113/// # #[macro_use]
114/// # extern crate uucore;
115/// # use uucore::error::{UError, UIoError, UResult, USimpleError};
116///
117/// # fn main() {
118/// let is_ok = Ok(1);
119/// // This does nothing at all
120/// show_if_err!(is_ok);
121///
122/// let is_err = Err(USimpleError::new(1, "I'm an error").into());
123/// // Calls `show!` on the contained USimpleError
124/// show_if_err!(is_err);
125/// # }
126/// ```
127///
128///
129#[macro_export]
130macro_rules! show_if_err(
131 ($res:expr) => ({
132 if let Err(e) = $res {
133 $crate::show!(e);
134 }
135 })
136);
137
138/// Show an error to stderr in a similar style to GNU coreutils.
139///
140/// Takes a [`format!`]-like input and prints it to stderr. The output is
141/// prepended with the current utility's name.
142///
143/// # Examples
144///
145/// ```
146/// # #[macro_use]
147/// # extern crate uucore;
148/// # fn main() {
149/// show_error!("Couldn't apply {} to {}", "foo", "bar");
150/// # }
151/// ```
152#[macro_export]
153macro_rules! show_error(
154 ($($args:tt)+) => ({
155 use std::io::Write as _;
156 let mut error = std::io::stderr().lock();
157 let _ = write!(error, "{}: ", $crate::util_name());
158 let _ = writeln!(error, $($args)+);
159 })
160);
161
162/// Print a warning message to stderr.
163///
164/// Takes [`format!`]-compatible input and prepends it with the current
165/// utility's name and "warning: " before printing to stderr.
166///
167/// # Examples
168///
169/// ```
170/// # #[macro_use]
171/// # extern crate uucore;
172/// # fn main() {
173/// // outputs <name>: warning: Couldn't apply foo to bar
174/// show_warning!("Couldn't apply {} to {}", "foo", "bar");
175/// # }
176/// ```
177#[macro_export]
178macro_rules! show_warning(
179 ($($args:tt)+) => ({
180 use std::io::Write as _;
181 let mut error = std::io::stderr().lock();
182 let _ = write!(error, "{}: warning: ", $crate::util_name());
183 let _ = writeln!(error, $($args)+);
184 })
185);
186
187/// Print a warning message to stderr, prepending the utility name.
188#[macro_export]
189macro_rules! show_warning_caps(
190 ($($args:tt)+) => ({
191 use std::io::Write as _;
192 let mut error = std::io::stderr().lock();
193 let _ = write!(error, "{}: WARNING: ", $crate::util_name());
194 let _ = writeln!(error, $($args)+);
195 })
196);