22
22
#![ warn( rust_2018_idioms) ]
23
23
24
24
use clap:: ValueEnum ;
25
+ use indicatif:: WeakProgressBar ;
25
26
pub use indicatif:: {
26
27
BinaryBytes , DecimalBytes , FormattedDuration , HumanBytes , HumanCount , HumanDuration ,
27
28
HumanFloatCount ,
28
29
} ;
30
+ use std:: fmt:: Debug ;
31
+ use std:: sync:: { Arc , RwLock } ;
29
32
30
33
pub use message:: * ;
31
34
pub use verbosity:: * ;
@@ -53,10 +56,29 @@ pub enum OutputFormat {
53
56
/// colour, etc.
54
57
///
55
58
/// All human-oriented messaging (basically all writes to `stdout`) must go through this object.
56
- #[ derive( Clone , Debug ) ]
59
+ #[ derive( Clone ) ]
57
60
pub struct Ui {
58
61
verbosity : Verbosity ,
59
62
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 ,
60
82
}
61
83
62
84
impl Ui {
@@ -65,6 +87,7 @@ impl Ui {
65
87
Self {
66
88
verbosity,
67
89
output_format,
90
+ state : Default :: default ( ) ,
68
91
}
69
92
}
70
93
@@ -103,6 +126,12 @@ impl Ui {
103
126
pub fn widget < T : Widget > ( & self , widget : T ) -> Option < T :: Handle > {
104
127
if self . output_format == OutputFormat :: Text && self . verbosity >= Verbosity :: Normal {
105
128
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
+ }
106
135
Some ( handle)
107
136
} else {
108
137
None
@@ -148,9 +177,20 @@ impl Ui {
148
177
}
149
178
150
179
fn do_print < T : Message > ( & self , message : T ) {
151
- match self . output_format {
180
+ let print = || match self . output_format {
152
181
OutputFormat :: Text => message. print_text ( ) ,
153
182
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 ( ) ;
154
194
}
155
195
}
156
196
0 commit comments