1 | /// Prints to [`stdout`][crate::stdout]. |
2 | /// |
3 | /// Equivalent to the [`println!`] macro except that a newline is not printed at |
4 | /// the end of the message. |
5 | /// |
6 | /// Note that stdout is frequently line-buffered by default so it may be |
7 | /// necessary to use [`std::io::Write::flush()`] to ensure the output is emitted |
8 | /// immediately. |
9 | /// |
10 | /// **NOTE:** The `print!` macro will lock the standard output on each call. If you call |
11 | /// `print!` within a hot loop, this behavior may be the bottleneck of the loop. |
12 | /// To avoid this, lock stdout with [`AutoStream::lock`][crate::AutoStream::lock]: |
13 | /// ``` |
14 | /// # #[cfg (feature = "auto" )] { |
15 | /// use std::io::Write as _; |
16 | /// |
17 | /// let mut lock = anstream::stdout().lock(); |
18 | /// write!(lock, "hello world" ).unwrap(); |
19 | /// # } |
20 | /// ``` |
21 | /// |
22 | /// Use `print!` only for the primary output of your program. Use |
23 | /// [`eprint!`] instead to print error and progress messages. |
24 | /// |
25 | /// **NOTE:** Not all `print!` calls will be captured in tests like [`std::print!`] |
26 | /// - Capturing will automatically be activated in test binaries |
27 | /// - Otherwise, only when the `test` feature is enabled |
28 | /// |
29 | /// # Panics |
30 | /// |
31 | /// Panics if writing to `stdout` fails for any reason **except** broken pipe. |
32 | /// |
33 | /// Writing to non-blocking stdout can cause an error, which will lead |
34 | /// this macro to panic. |
35 | /// |
36 | /// # Examples |
37 | /// |
38 | /// ``` |
39 | /// # #[cfg (feature = "auto" )] { |
40 | /// use std::io::Write as _; |
41 | /// use anstream::print; |
42 | /// use anstream::stdout; |
43 | /// |
44 | /// print!("this " ); |
45 | /// print!("will " ); |
46 | /// print!("be " ); |
47 | /// print!("on " ); |
48 | /// print!("the " ); |
49 | /// print!("same " ); |
50 | /// print!("line " ); |
51 | /// |
52 | /// stdout().flush().unwrap(); |
53 | /// |
54 | /// print!("this string has a newline, why not choose println! instead? \n" ); |
55 | /// |
56 | /// stdout().flush().unwrap(); |
57 | /// # } |
58 | /// ``` |
59 | #[cfg (feature = "auto" )] |
60 | #[macro_export ] |
61 | macro_rules! print { |
62 | ($($arg:tt)*) => {{ |
63 | if cfg!(test) || $crate::_macros::FEATURE_TEST_ACTIVATED { |
64 | let target_stream = std::io::stdout(); |
65 | let buffer = $crate::_macros::to_adapted_string(&format_args!($($arg)*), &target_stream); |
66 | ::std::print!("{}" , buffer) |
67 | } else { |
68 | use std::io::Write as _; |
69 | |
70 | let mut stream = $crate::stdout(); |
71 | match ::std::write!(&mut stream, $($arg)*) { |
72 | Err(e) if e.kind() != ::std::io::ErrorKind::BrokenPipe => { |
73 | ::std::panic!("failed printing to stdout: {e}" ); |
74 | } |
75 | Err(_) | Ok(_) => {} |
76 | } |
77 | } |
78 | }}; |
79 | } |
80 | |
81 | /// Prints to [`stdout`][crate::stdout], with a newline. |
82 | /// |
83 | /// On all platforms, the newline is the LINE FEED character (`\n`/`U+000A`) alone |
84 | /// (no additional CARRIAGE RETURN (`\r`/`U+000D`)). |
85 | /// |
86 | /// This macro uses the same syntax as [`format!`], but writes to the standard output instead. |
87 | /// See [`std::fmt`] for more information. |
88 | /// |
89 | /// **NOTE:** The `println!` macro will lock the standard output on each call. If you call |
90 | /// `println!` within a hot loop, this behavior may be the bottleneck of the loop. |
91 | /// To avoid this, lock stdout with [`AutoStream::lock`][crate::AutoStream::lock]: |
92 | /// ``` |
93 | /// # #[cfg (feature = "auto" )] { |
94 | /// use std::io::Write as _; |
95 | /// |
96 | /// let mut lock = anstream::stdout().lock(); |
97 | /// writeln!(lock, "hello world" ).unwrap(); |
98 | /// # } |
99 | /// ``` |
100 | /// |
101 | /// Use `println!` only for the primary output of your program. Use |
102 | /// [`eprintln!`] instead to print error and progress messages. |
103 | /// |
104 | /// **NOTE:** Not all `println!` calls will be captured in tests like [`std::println!`] |
105 | /// - Capturing will automatically be activated in test binaries |
106 | /// - Otherwise, only when the `test` feature is enabled |
107 | /// |
108 | /// # Panics |
109 | /// |
110 | /// Panics if writing to `stdout` fails for any reason **except** broken pipe. |
111 | /// |
112 | /// Writing to non-blocking stdout can cause an error, which will lead |
113 | /// this macro to panic. |
114 | /// |
115 | /// # Examples |
116 | /// |
117 | /// ``` |
118 | /// # #[cfg (feature = "auto" )] { |
119 | /// use anstream::println; |
120 | /// |
121 | /// println!(); // prints just a newline |
122 | /// println!("hello there!" ); |
123 | /// println!("format {} arguments" , "some" ); |
124 | /// let local_variable = "some" ; |
125 | /// println!("format {local_variable} arguments" ); |
126 | /// # } |
127 | /// ``` |
128 | #[cfg (feature = "auto" )] |
129 | #[macro_export ] |
130 | macro_rules! println { |
131 | () => { |
132 | $crate::print!(" \n" ) |
133 | }; |
134 | ($($arg:tt)*) => {{ |
135 | if cfg!(test) || $crate::_macros::FEATURE_TEST_ACTIVATED { |
136 | let target_stream = std::io::stdout(); |
137 | let buffer = $crate::_macros::to_adapted_string(&format_args!($($arg)*), &target_stream); |
138 | ::std::println!("{}" , buffer) |
139 | } else { |
140 | use std::io::Write as _; |
141 | |
142 | let mut stream = $crate::stdout(); |
143 | match ::std::writeln!(&mut stream, $($arg)*) { |
144 | Err(e) if e.kind() != ::std::io::ErrorKind::BrokenPipe => { |
145 | ::std::panic!("failed printing to stdout: {e}" ); |
146 | } |
147 | Err(_) | Ok(_) => {} |
148 | } |
149 | } |
150 | }}; |
151 | } |
152 | |
153 | /// Prints to [`stderr`][crate::stderr]. |
154 | /// |
155 | /// Equivalent to the [`print!`] macro, except that output goes to |
156 | /// `stderr` instead of `stdout`. See [`print!`] for |
157 | /// example usage. |
158 | /// |
159 | /// Use `eprint!` only for error and progress messages. Use `print!` |
160 | /// instead for the primary output of your program. |
161 | /// |
162 | /// **NOTE:** Not all `eprint!` calls will be captured in tests like [`std::eprint!`] |
163 | /// - Capturing will automatically be activated in test binaries |
164 | /// - Otherwise, only when the `test` feature is enabled |
165 | /// |
166 | /// # Panics |
167 | /// |
168 | /// Panics if writing to `stderr` fails for any reason **except** broken pipe. |
169 | /// |
170 | /// Writing to non-blocking stdout can cause an error, which will lead |
171 | /// this macro to panic. |
172 | /// |
173 | /// # Examples |
174 | /// |
175 | /// ``` |
176 | /// # #[cfg (feature = "auto" )] { |
177 | /// use anstream::eprint; |
178 | /// |
179 | /// eprint!("Error: Could not complete task" ); |
180 | /// # } |
181 | /// ``` |
182 | #[cfg (feature = "auto" )] |
183 | #[macro_export ] |
184 | macro_rules! eprint { |
185 | ($($arg:tt)*) => {{ |
186 | if cfg!(test) || $crate::_macros::FEATURE_TEST_ACTIVATED { |
187 | let target_stream = std::io::stderr(); |
188 | let buffer = $crate::_macros::to_adapted_string(&format_args!($($arg)*), &target_stream); |
189 | ::std::eprint!("{}" , buffer) |
190 | } else { |
191 | use std::io::Write as _; |
192 | |
193 | let mut stream = $crate::stderr(); |
194 | match ::std::write!(&mut stream, $($arg)*) { |
195 | Err(e) if e.kind() != ::std::io::ErrorKind::BrokenPipe => { |
196 | ::std::panic!("failed printing to stderr: {e}" ); |
197 | } |
198 | Err(_) | Ok(_) => {} |
199 | } |
200 | } |
201 | }}; |
202 | } |
203 | |
204 | /// Prints to [`stderr`][crate::stderr], with a newline. |
205 | /// |
206 | /// Equivalent to the [`println!`] macro, except that output goes to |
207 | /// `stderr` instead of `stdout`. See [`println!`] for |
208 | /// example usage. |
209 | /// |
210 | /// Use `eprintln!` only for error and progress messages. Use `println!` |
211 | /// instead for the primary output of your program. |
212 | /// |
213 | /// **NOTE:** Not all `eprintln!` calls will be captured in tests like [`std::eprintln!`] |
214 | /// - Capturing will automatically be activated in test binaries |
215 | /// - Otherwise, only when the `test` feature is enabled |
216 | /// |
217 | /// # Panics |
218 | /// |
219 | /// Panics if writing to `stderr` fails for any reason **except** broken pipe. |
220 | /// |
221 | /// Writing to non-blocking stdout can cause an error, which will lead |
222 | /// this macro to panic. |
223 | /// |
224 | /// # Examples |
225 | /// |
226 | /// ``` |
227 | /// # #[cfg (feature = "auto" )] { |
228 | /// use anstream::eprintln; |
229 | /// |
230 | /// eprintln!("Error: Could not complete task" ); |
231 | /// # } |
232 | /// ``` |
233 | #[cfg (feature = "auto" )] |
234 | #[macro_export ] |
235 | macro_rules! eprintln { |
236 | () => { |
237 | $crate::eprint!(" \n" ) |
238 | }; |
239 | ($($arg:tt)*) => {{ |
240 | if cfg!(test) || $crate::_macros::FEATURE_TEST_ACTIVATED { |
241 | let target_stream = std::io::stderr(); |
242 | let buffer = $crate::_macros::to_adapted_string(&format_args!($($arg)*), &target_stream); |
243 | ::std::eprintln!("{}" , buffer) |
244 | } else { |
245 | use std::io::Write as _; |
246 | |
247 | let mut stream = $crate::stderr(); |
248 | match ::std::writeln!(&mut stream, $($arg)*) { |
249 | Err(e) if e.kind() != ::std::io::ErrorKind::BrokenPipe => { |
250 | ::std::panic!("failed printing to stderr: {e}" ); |
251 | } |
252 | Err(_) | Ok(_) => {} |
253 | } |
254 | } |
255 | }}; |
256 | } |
257 | |
258 | /// Panics the current thread. |
259 | /// |
260 | /// This allows a program to terminate immediately and provide feedback |
261 | /// to the caller of the program. |
262 | /// |
263 | /// This macro is the perfect way to assert conditions in example code and in |
264 | /// tests. `panic!` is closely tied with the `unwrap` method of both |
265 | /// [`Option`][ounwrap] and [`Result`][runwrap] enums. Both implementations call |
266 | /// `panic!` when they are set to [`None`] or [`Err`] variants. |
267 | /// |
268 | /// When using `panic!()` you can specify a string payload, that is built using |
269 | /// the [`format!`] syntax. That payload is used when injecting the panic into |
270 | /// the calling Rust thread, causing the thread to panic entirely. |
271 | /// |
272 | /// The behavior of the default `std` hook, i.e. the code that runs directly |
273 | /// after the panic is invoked, is to print the message payload to |
274 | /// `stderr` along with the file/line/column information of the `panic!()` |
275 | /// call. You can override the panic hook using [`std::panic::set_hook()`]. |
276 | /// Inside the hook a panic can be accessed as a `&dyn Any + Send`, |
277 | /// which contains either a `&str` or `String` for regular `panic!()` invocations. |
278 | /// To panic with a value of another other type, [`panic_any`] can be used. |
279 | /// |
280 | /// See also the macro [`compile_error!`], for raising errors during compilation. |
281 | /// |
282 | /// # When to use `panic!` vs `Result` |
283 | /// |
284 | /// The Rust language provides two complementary systems for constructing / |
285 | /// representing, reporting, propagating, reacting to, and discarding errors. These |
286 | /// responsibilities are collectively known as "error handling." `panic!` and |
287 | /// `Result` are similar in that they are each the primary interface of their |
288 | /// respective error handling systems; however, the meaning these interfaces attach |
289 | /// to their errors and the responsibilities they fulfill within their respective |
290 | /// error handling systems differ. |
291 | /// |
292 | /// The `panic!` macro is used to construct errors that represent a bug that has |
293 | /// been detected in your program. With `panic!` you provide a message that |
294 | /// describes the bug and the language then constructs an error with that message, |
295 | /// reports it, and propagates it for you. |
296 | /// |
297 | /// `Result` on the other hand is used to wrap other types that represent either |
298 | /// the successful result of some computation, `Ok(T)`, or error types that |
299 | /// represent an anticipated runtime failure mode of that computation, `Err(E)`. |
300 | /// `Result` is used alongside user defined types which represent the various |
301 | /// anticipated runtime failure modes that the associated computation could |
302 | /// encounter. `Result` must be propagated manually, often with the the help of the |
303 | /// `?` operator and `Try` trait, and they must be reported manually, often with |
304 | /// the help of the `Error` trait. |
305 | /// |
306 | /// For more detailed information about error handling check out the [book] or the |
307 | /// [`std::result`] module docs. |
308 | /// |
309 | /// [ounwrap]: Option::unwrap |
310 | /// [runwrap]: Result::unwrap |
311 | /// [`std::panic::set_hook()`]: ../std/panic/fn.set_hook.html |
312 | /// [`panic_any`]: ../std/panic/fn.panic_any.html |
313 | /// [`Box`]: ../std/boxed/struct.Box.html |
314 | /// [`Any`]: crate::any::Any |
315 | /// [`format!`]: ../std/macro.format.html |
316 | /// [book]: ../book/ch09-00-error-handling.html |
317 | /// [`std::result`]: ../std/result/index.html |
318 | /// |
319 | /// # Current implementation |
320 | /// |
321 | /// If the main thread panics it will terminate all your threads and end your |
322 | /// program with code `101`. |
323 | /// |
324 | /// # Examples |
325 | /// |
326 | /// ```should_panic |
327 | /// # #![allow (unreachable_code)] |
328 | /// use anstream::panic; |
329 | /// panic!(); |
330 | /// panic!("this is a terrible mistake!" ); |
331 | /// panic!("this is a {} {message}" , "fancy" , message = "message" ); |
332 | /// ``` |
333 | #[cfg (feature = "auto" )] |
334 | #[macro_export ] |
335 | macro_rules! panic { |
336 | () => { |
337 | ::std::panic!() |
338 | }; |
339 | ($($arg:tt)*) => {{ |
340 | let target_stream = std::io::stderr(); |
341 | let buffer = $crate::_macros::to_adapted_string(&format_args!($($arg)*), &target_stream); |
342 | ::std::panic!("{}" , buffer) |
343 | }}; |
344 | } |
345 | |
346 | #[cfg (feature = "auto" )] |
347 | pub const FEATURE_TEST_ACTIVATED: bool = cfg!(feature = "test" ); |
348 | |
349 | #[cfg (feature = "auto" )] |
350 | pub fn to_adapted_string( |
351 | display: &dyn std::fmt::Display, |
352 | stream: &impl crate::stream::RawStream, |
353 | ) -> String { |
354 | use std::io::Write as _; |
355 | |
356 | let choice: ColorChoice = crate::AutoStream::choice(raw:stream); |
357 | let buffer: Vec = Vec::new(); |
358 | let mut stream: AutoStream> = crate::AutoStream::new(raw:buffer, choice); |
359 | // Ignore errors rather than panic |
360 | let _ = ::std::write!(&mut stream, " {display}" ); |
361 | let buffer: Vec = stream.into_inner(); |
362 | // Should be UTF-8 but not wanting to panic |
363 | let buffer: String = String::from_utf8_lossy(&buffer).into_owned(); |
364 | buffer |
365 | } |
366 | |