Skip to content

Commit cc470de

Browse files
authored
Print Cargo logs with SpinnerBar::println (#1337)
fix #1336
1 parent 499bca2 commit cc470de

File tree

3 files changed

+60
-6
lines changed

3 files changed

+60
-6
lines changed

utils/scarb-ui/src/components/spinner.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use std::time::Duration;
22

3-
use indicatif::{ProgressBar, ProgressStyle};
3+
use indicatif::{ProgressBar, ProgressDrawTarget, ProgressStyle, WeakProgressBar};
44

5-
use crate::Widget;
5+
use crate::{Widget, WidgetHandle};
66

77
/// Spinner widget informing about an ongoing process.
88
pub struct Spinner {
@@ -33,11 +33,17 @@ impl Drop for SpinnerHandle {
3333
}
3434
}
3535

36+
impl WidgetHandle for SpinnerHandle {
37+
fn weak_progress_bar(&self) -> Option<WeakProgressBar> {
38+
Some(self.pb.downgrade())
39+
}
40+
}
41+
3642
impl Widget for Spinner {
3743
type Handle = SpinnerHandle;
3844

3945
fn text(self) -> Self::Handle {
40-
let pb = ProgressBar::new_spinner()
46+
let pb = ProgressBar::with_draw_target(None, ProgressDrawTarget::stdout())
4147
.with_style(Spinner::default_style())
4248
.with_message(self.message);
4349
pb.enable_steady_tick(Duration::from_millis(120));

utils/scarb-ui/src/lib.rs

+42-2
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,13 @@
2222
#![warn(rust_2018_idioms)]
2323

2424
use clap::ValueEnum;
25+
use indicatif::WeakProgressBar;
2526
pub use indicatif::{
2627
BinaryBytes, DecimalBytes, FormattedDuration, HumanBytes, HumanCount, HumanDuration,
2728
HumanFloatCount,
2829
};
30+
use std::fmt::Debug;
31+
use std::sync::{Arc, RwLock};
2932

3033
pub use message::*;
3134
pub use verbosity::*;
@@ -53,10 +56,29 @@ pub enum OutputFormat {
5356
/// colour, etc.
5457
///
5558
/// All human-oriented messaging (basically all writes to `stdout`) must go through this object.
56-
#[derive(Clone, Debug)]
59+
#[derive(Clone)]
5760
pub struct Ui {
5861
verbosity: Verbosity,
5962
output_format: OutputFormat,
63+
state: Arc<RwLock<State>>,
64+
}
65+
66+
impl Debug for Ui {
67+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68+
f.debug_struct("Ui")
69+
.field("verbosity", &self.verbosity)
70+
.field("output_format", &self.output_format)
71+
.finish()
72+
}
73+
}
74+
75+
/// An encapsulation of the UI state.
76+
///
77+
/// This can be used by `Ui` to store stateful information.
78+
#[derive(Default)]
79+
#[non_exhaustive]
80+
struct State {
81+
active_spinner: WeakProgressBar,
6082
}
6183

6284
impl Ui {
@@ -65,6 +87,7 @@ impl Ui {
6587
Self {
6688
verbosity,
6789
output_format,
90+
state: Default::default(),
6891
}
6992
}
7093

@@ -103,6 +126,12 @@ impl Ui {
103126
pub fn widget<T: Widget>(&self, widget: T) -> Option<T::Handle> {
104127
if self.output_format == OutputFormat::Text && self.verbosity >= Verbosity::Normal {
105128
let handle = widget.text();
129+
if let Some(handle) = handle.weak_progress_bar() {
130+
self.state
131+
.write()
132+
.expect("cannot lock ui state for writing")
133+
.active_spinner = handle;
134+
}
106135
Some(handle)
107136
} else {
108137
None
@@ -148,9 +177,20 @@ impl Ui {
148177
}
149178

150179
fn do_print<T: Message>(&self, message: T) {
151-
match self.output_format {
180+
let print = || match self.output_format {
152181
OutputFormat::Text => message.print_text(),
153182
OutputFormat::Json => message.print_json(),
183+
};
184+
let handle = self
185+
.state
186+
.read()
187+
.expect("cannot lock ui state for reading")
188+
.active_spinner
189+
.clone();
190+
if let Some(pb) = handle.upgrade() {
191+
pb.suspend(print);
192+
} else {
193+
print();
154194
}
155195
}
156196

utils/scarb-ui/src/widget.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
1+
use indicatif::WeakProgressBar;
2+
13
/// A persistent message that is only usable for humans, for example a spinner.
24
pub trait Widget {
35
/// Allows for live interaction with the widget, and its drop is called when the widget should
46
/// be cleared.
5-
type Handle;
7+
type Handle: WidgetHandle;
68

79
/// Display the widget on the standard output, and return a handle for further interaction.
810
fn text(self) -> Self::Handle;
911
}
12+
13+
/// A handle to a widget that allows for further interaction.
14+
pub trait WidgetHandle {
15+
#[doc(hidden)]
16+
fn weak_progress_bar(&self) -> Option<WeakProgressBar>;
17+
}

0 commit comments

Comments
 (0)