Repository: ouch-org/ouch (language: rust)

Issue:
Parallel decompression emits unaligned progress
### Version

main (1d540f5cd4a58adc4609d96c9f5b4c46a4ba68af)

### Description

It seems ouch decompresses multiple files simultaneously if it receives multiple archive. And console output does not seem to be properly synchronized.

`ouch d *.zip`

### Current Behavior

```
[INFO] ".tmprodOHc/xxx/720p/00055.ts" extracted. (763.93KiB)
[INFO] [INFO] [INFO] ".tmpzEX0FK/yyy/360p/00078.ts" extracted. (258.50KiB)
[INFO] ".tmpUxTc0M/zzz/1080p/00196.ts" extracted. (1.75MiB)
".tmpec6lgY/www/720p/00170.ts" extracted. (353.42KiB)
[INFO] ".tmpRayxtP/vvv/1080p/00016.ts" extracted. (1.63MiB)
".tmpl2XqzX/uuu/360p/00023.ts" extracted. (284.94KiB)
[INFO] ".tmp6QNijC/ttt/1080p/00266.ts" extracted. (1.83MiB)
[INFO] ".tmpzEX0FK/yyy/360p/00079.ts" extracted. (265.84KiB)
```

### Expected Behavior

```
[INFO] ".tmprodOHc/xxx/720p/00055.ts" extracted. (763.93KiB)
[INFO] ".tmpzEX0FK/yyy/360p/00078.ts" extracted. (258.50KiB)
[INFO] ".tmpUxTc0M/zzz/1080p/00196.ts" extracted. (1.75MiB)
[INFO] ".tmpec6lgY/www/720p/00170.ts" extracted. (353.42KiB)
[INFO] ".tmpRayxtP/vvv/1080p/00016.ts" extracted. (1.63MiB)
[INFO] ".tmpl2XqzX/uuu/360p/00023.ts" extracted. (284.94KiB)
[INFO] ".tmp6QNijC/ttt/1080p/00266.ts" extracted. (1.83MiB)
[INFO] ".tmpzEX0FK/yyy/360p/00079.ts" extracted. (265.84KiB)
```

### Additional Information

_No response_


Discussion / hints:

Fix patch:
diff --git a/src/macros.rs b/src/macros.rs
index 8b3f5f667..10a3ba520 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -1,5 +1,7 @@
 //! Macros used on ouch.
 
+use std::io;
+
 /// Macro that prints \[INFO\] messages, wraps [`eprintln`].
 ///
 /// There are essentially two different versions of the `info!()` macro:
@@ -19,24 +21,32 @@ macro_rules! info {
     // Accessible (short/important) info message.
     // Show info message even in ACCESSIBLE mode
     (accessible, $($arg:tt)*) => {{
-        use $crate::utils::colors::{YELLOW, RESET};
+        use ::std::io::{stderr, Write};
+
+        use $crate::{macros::stderr_check, utils::colors::{YELLOW, RESET}};
+
+        let mut stderr = stderr().lock();
 
         if $crate::accessible::is_running_in_accessible_mode() {
-            eprint!("{}Info:{} ", *YELLOW, *RESET);
+            stderr_check(write!(stderr, "{}Info:{} ", *YELLOW, *RESET));
         } else {
-            eprint!("{}[INFO]{} ", *YELLOW, *RESET);
+            stderr_check(write!(stderr, "{}[INFO]{} ", *YELLOW, *RESET));
         }
 
-        eprintln!($($arg)*);
+        stderr_check(writeln!(stderr, $($arg)*));
     }};
     // Inccessible (long/no important) info message.
     // Print info message if ACCESSIBLE is not turned on
     (inaccessible, $($arg:tt)*) => {{
-        use $crate::utils::colors::{YELLOW, RESET};
+        use ::std::io::{stderr, Write};
+
+        use $crate::{macros::stderr_check, utils::colors::{YELLOW, RESET}};
+
+        let mut stderr = stderr().lock();
 
         if !$crate::accessible::is_running_in_accessible_mode() {
-            eprint!("{}[INFO]{} ", *YELLOW, *RESET);
-            eprintln!($($arg)*);
+            stderr_check(write!(stderr, "{}[INFO]{} ", *YELLOW, *RESET));
+            stderr_check(writeln!(stderr, $($arg)*));
         }
     }};
 }
@@ -45,14 +55,22 @@ macro_rules! info {
 #[macro_export]
 macro_rules! warning {
     ($($arg:tt)*) => {{
-        use $crate::utils::colors::{ORANGE, RESET};
+        use ::std::io::{stderr, Write};
+
+        use $crate::{macros::stderr_check, utils::colors::{ORANGE, RESET}};
+
+        let mut stderr = stderr().lock();
 
         if $crate::accessible::is_running_in_accessible_mode() {
-            eprint!("{}Warning:{} ", *ORANGE, *RESET);
+            stderr_check(write!(stderr, "{}Warning:{} ", *ORANGE, *RESET));
         } else {
-            eprint!("{}[WARNING]{} ", *ORANGE, *RESET);
+            stderr_check(write!(stderr, "{}[WARNING]{} ", *ORANGE, *RESET));
         }
 
-        eprintln!($($arg)*);
+        stderr_check(writeln!(stderr, $($arg)*));
     }};
 }
+
+pub fn stderr_check(result: io::Result<()>) {
+    result.expect("failed printing to stderr");
+}


Test patch: