| 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 | |