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 use std::io::Write as _;
93
94 let e = $err;
95 $crate::error::set_exit_code(e.code());
96 let _ = writeln!(std::io::stderr().lock(), "{}: {e}", $crate::util_name());
97 })
98);
99
100/// Display an error and set global exit code in error case.
101///
102/// Wraps around [`crate::show!`] and takes a [`crate::error::UResult`] instead of a
103/// [`crate::error::UError`] type. This macro invokes [`crate::show!`] if the
104/// [`crate::error::UResult`] is an `Err`-variant. This can be invoked directly
105/// on the result of a function call, like in the `install` utility:
106///
107/// ```ignore
108/// show_if_err!(copy(sourcepath, &targetpath, b));
109/// ```
110///
111/// # Examples
112///
113/// ```ignore
114/// # #[macro_use]
115/// # extern crate uucore;
116/// # use uucore::error::{UError, UIoError, UResult, USimpleError};
117///
118/// # fn main() {
119/// let is_ok = Ok(1);
120/// // This does nothing at all
121/// show_if_err!(is_ok);
122///
123/// let is_err = Err(USimpleError::new(1, "I'm an error").into());
124/// // Calls `show!` on the contained USimpleError
125/// show_if_err!(is_err);
126/// # }
127/// ```
128///
129///
130#[macro_export]
131macro_rules! show_if_err(
132 ($res:expr) => ({
133 if let Err(e) = $res {
134 $crate::show!(e);
135 }
136 })
137);
138
139/// Show an error to stderr in a similar style to GNU coreutils.
140///
141/// Takes a [`format!`]-like input and prints it to stderr. The output is
142/// prepended with the current utility's name.
143///
144/// # Examples
145///
146/// ```
147/// # #[macro_use]
148/// # extern crate uucore;
149/// # fn main() {
150/// show_error!("Couldn't apply {} to {}", "foo", "bar");
151/// # }
152/// ```
153#[macro_export]
154macro_rules! show_error(
155 ($($args:tt)+) => ({
156 use std::io::Write as _;
157 let mut error = std::io::stderr().lock();
158 let _ = write!(error, "{}: ", $crate::util_name());
159 let _ = writeln!(error, $($args)+);
160 })
161);
162
163/// Print a warning message to stderr.
164///
165/// Takes [`format!`]-compatible input and prepends it with the current
166/// utility's name and "warning: " before printing to stderr.
167///
168/// # Examples
169///
170/// ```
171/// # #[macro_use]
172/// # extern crate uucore;
173/// # fn main() {
174/// // outputs <name>: warning: Couldn't apply foo to bar
175/// show_warning!("Couldn't apply {} to {}", "foo", "bar");
176/// # }
177/// ```
178#[macro_export]
179macro_rules! show_warning(
180 ($($args:tt)+) => ({
181 use std::io::Write as _;
182 let mut error = std::io::stderr().lock();
183 let _ = write!(error, "{}: warning: ", $crate::util_name());
184 let _ = writeln!(error, $($args)+);
185 })
186);
187
188/// Print a warning message to stderr, prepending the utility name.
189#[macro_export]
190macro_rules! show_warning_caps(
191 ($($args:tt)+) => ({
192 use std::io::Write as _;
193 let mut error = std::io::stderr().lock();
194 let _ = write!(error, "{}: WARNING: ", $crate::util_name());
195 let _ = writeln!(error, $($args)+);
196 })
197);