From d0d17d259462d3b54bf0b1f560d7324f92997ade Mon Sep 17 00:00:00 2001 From: Tatsuyuki Ishi Date: Thu, 16 Dec 2021 15:00:54 +0900 Subject: [PATCH] Implement ProgressBar::suspend --- src/progress_bar.rs | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/progress_bar.rs b/src/progress_bar.rs index 062b5939..8cd2f22b 100644 --- a/src/progress_bar.rs +++ b/src/progress_bar.rs @@ -231,11 +231,12 @@ impl ProgressBar { /// Print a log line above the progress bar /// + /// If the progress bar is hidden (e.g. when standard output is not a terminal), `println()` + /// will not do anything. If you want to write to the standard output in such cases as well, use + /// \[`suspend`\] instead. + /// /// If the progress bar was added to a [`MultiProgress`], the log line will be /// printed above all other progress bars. - /// - /// Note that if the progress bar is hidden (which by default happens if the progress bar is - /// redirected into a file) `println()` will not do anything either. pub fn println>(&self, msg: I) { let mut state = self.state.lock().unwrap(); @@ -406,6 +407,29 @@ impl ProgressBar { state.draw_target = target; } + /// Hide the progress bar temporarily, execute `f`, then redraw the progress bar. + /// Useful for external code that writes to the standard output. + /// + /// **Note:** The internal lock is held while `f` is executed. Other threads trying to print + /// anything on the progress bar will be blocked until `f` finishes. + /// Therefore, it is recommended to not do long-running operations in `f`. + /// + /// ```rust,no_run + /// # use indicatif::ProgressBar; + /// let mut pb = ProgressBar::new(3); + /// pb.suspend(|| { + /// println!("Log message"); + /// }) + /// ``` + pub fn suspend(&mut self, f: F) { + let mut state = self.state.lock().unwrap(); + let _ = state + .draw_target + .apply_draw_state(ProgressDrawState::new(vec![], true)); + f(); + let _ = state.draw(true); + } + /// Wraps an [`Iterator`] with the progress bar /// /// ```rust,no_run