Skip to content

Commit 527f83f

Browse files
committed
Add View::take_captured_output
1 parent 02902ae commit 527f83f

File tree

2 files changed

+34
-17
lines changed

2 files changed

+34
-17
lines changed

src/ansi.rs

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,6 @@ pub(crate) fn insert_codes(rendered: &str, cursor_y: Option<usize>) -> (String,
6363
#[cfg(test)]
6464
mod test {
6565
use std::{
66-
mem::take,
67-
ops::DerefMut,
6866
thread::sleep,
6967
time::{Duration, Instant},
7068
};
@@ -216,10 +214,9 @@ mod test {
216214
let model = Model();
217215
let options = Options::default().destination(Destination::Capture);
218216
let view = View::new(model, options);
219-
let output = view.captured_output();
220217

221218
view.update(|_model| ());
222-
let written = output.lock().unwrap().to_owned();
219+
let written = view.take_captured_output();
223220
assert_eq!(
224221
written,
225222
MOVE_TO_START_OF_LINE.to_owned()
@@ -228,8 +225,6 @@ mod test {
228225
+ CLEAR_TO_END_OF_LINE
229226
+ ENABLE_LINE_WRAP
230227
);
231-
232-
drop(view);
233228
}
234229

235230
#[test]
@@ -245,11 +240,10 @@ mod test {
245240
.destination(Destination::Capture)
246241
.update_interval(Duration::ZERO);
247242
let view = View::new(model, options);
248-
let output = view.captured_output();
249243

250244
// Paint 0 before it's suspended
251245
view.update(|model| model.0 = 0);
252-
let written = take(output.lock().unwrap().deref_mut());
246+
let written = view.take_captured_output();
253247
assert_eq!(
254248
written,
255249
MOVE_TO_START_OF_LINE.to_owned()
@@ -262,7 +256,7 @@ mod test {
262256
// Now suspend; this clears the bar from the screen.
263257
view.suspend();
264258
view.update(|model| model.0 = 1);
265-
let written = take(output.lock().unwrap().deref_mut());
259+
let written = view.take_captured_output();
266260
assert_eq!(
267261
written,
268262
MOVE_TO_START_OF_LINE.to_owned() + CLEAR_TO_END_OF_SCREEN + ENABLE_LINE_WRAP
@@ -271,12 +265,12 @@ mod test {
271265
// * 2 is also updated into the model while the bar is suspended, but then
272266
// it's resumed, so 2 is then painted.
273267
view.update(|model| model.0 = 2);
274-
let written = take(output.lock().unwrap().deref_mut());
268+
let written = view.take_captured_output();
275269
assert_eq!(written, "");
276270

277271
// Now 2 is painted when resumed.
278272
view.resume();
279-
let written = take(output.lock().unwrap().deref_mut());
273+
let written = view.take_captured_output();
280274
assert_eq!(
281275
written,
282276
MOVE_TO_START_OF_LINE.to_owned()
@@ -289,7 +283,7 @@ mod test {
289283
// * 3 and 4 are painted in the usual way.
290284
view.update(|model| model.0 = 3);
291285
view.update(|model| model.0 = 4);
292-
let written = take(output.lock().unwrap().deref_mut());
286+
let written = view.take_captured_output();
293287
assert_eq!(
294288
written,
295289
MOVE_TO_START_OF_LINE.to_owned()
@@ -304,8 +298,9 @@ mod test {
304298
+ ENABLE_LINE_WRAP
305299
);
306300

301+
let output = view.captured_output();
307302
view.abandon();
308-
let written = take(output.lock().unwrap().deref_mut());
303+
let written = output.lock().unwrap().to_owned();
309304
assert_eq!(written, "\n");
310305
}
311306

@@ -323,16 +318,14 @@ mod test {
323318
.destination(Destination::Capture)
324319
.update_interval(Duration::ZERO);
325320
let view = View::new(Hundreds(0), options);
326-
let output = view.captured_output();
327321

328322
for i in 0..200 {
329323
// We change the model, but not in a way that will change what's displayed.
330324
view.update(|model| model.0 = i);
331325
}
332-
view.abandon();
333326

334327
// No erasure commands, just a newline after the last painted view.
335-
let written = output.lock().unwrap().to_owned();
328+
let written = view.take_captured_output();
336329
assert_eq!(
337330
written,
338331
MOVE_TO_START_OF_LINE.to_owned()
@@ -345,7 +338,6 @@ mod test {
345338
+ "hundreds=1"
346339
+ CLEAR_TO_END_OF_LINE
347340
+ ENABLE_LINE_WRAP
348-
+ "\n" // bar abandoned
349341
);
350342
}
351343
}

src/lib.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,8 @@ is welcome.
211211
#![warn(missing_docs)]
212212

213213
use std::io::{self, Write};
214+
use std::mem::take;
215+
use std::ops::DerefMut;
214216
use std::sync::{Arc, Mutex};
215217
use std::time::Instant;
216218

@@ -586,6 +588,18 @@ impl<M: Model> View<M> {
586588
pub fn captured_output(&self) -> Arc<Mutex<String>> {
587589
self.call_inner(|v| v.captured_output())
588590
}
591+
592+
/// Return a copy of the captured output, if any, and clear the captured output buffer.
593+
///
594+
/// This is intended for use in testing, so that tests can incrementally check
595+
/// the output.
596+
///
597+
/// # Panics
598+
///
599+
/// This function panics if output capture is not enabled.
600+
pub fn take_captured_output(&self) -> String {
601+
self.call_inner(|v| v.take_captured_output())
602+
}
589603
}
590604

591605
impl<M: Model> io::Write for &View<M> {
@@ -854,4 +868,15 @@ impl<M: Model> InnerView<M> {
854868
.get_or_insert_with(|| Arc::new(Mutex::new(String::new())))
855869
.clone()
856870
}
871+
872+
fn take_captured_output(&mut self) -> String {
873+
take(
874+
self.capture_buffer
875+
.as_mut()
876+
.expect("output capture is not enabled")
877+
.lock()
878+
.expect("lock capture_buffer")
879+
.deref_mut(),
880+
)
881+
}
857882
}

0 commit comments

Comments
 (0)