Skip to content

Commit f88ec3b

Browse files
foresterredjc
authored andcommitted
Fix subtract with overflow when measuring terminal line length
If measure_text_width returns 0, the line is effectively empty, although line.is_empty() may still be false. This can for example happen when there is a line which just consists of ANSI color escape sequences.
1 parent bd320a1 commit f88ec3b

File tree

2 files changed

+27
-2
lines changed

2 files changed

+27
-2
lines changed

src/draw_target.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -502,8 +502,14 @@ impl DrawState {
502502
} else {
503503
// Calculate real length based on terminal width
504504
// This take in account linewrap from terminal
505-
real_len += (console::measure_text_width(line) as f64 / term.width() as f64).ceil()
506-
as usize;
505+
let terminal_len = (console::measure_text_width(line) as f64 / term.width() as f64)
506+
.ceil() as usize;
507+
508+
// If the line is effectively empty (for example when it consists
509+
// solely of ANSI color code sequences, count it the same as a
510+
// new line. If the line is measured to be len = 0, we will
511+
// subtract with overflow later.
512+
real_len += usize::max(terminal_len, 1);
507513
}
508514
if idx + 1 != len {
509515
term.write_line(line)?;

tests/render.rs

+19
Original file line numberDiff line numberDiff line change
@@ -981,6 +981,25 @@ s"#
981981
println!("{:?}", in_mem.contents())
982982
}
983983

984+
#[test]
985+
fn spinner_terminal_cleared_log_line_with_ansi_codes() {
986+
let in_mem = InMemoryTerm::new(10, 100);
987+
988+
let pb = ProgressBar::with_draw_target(
989+
Some(10),
990+
ProgressDrawTarget::term_like(Box::new(in_mem.clone())),
991+
);
992+
pb.set_style(ProgressStyle::default_spinner());
993+
assert_eq!(in_mem.contents(), String::new());
994+
995+
pb.finish_and_clear();
996+
// Visually empty, but consists of an ANSII code
997+
pb.println("\u{1b}[1m");
998+
999+
pb.println("text\u{1b}[0m");
1000+
assert_eq!(in_mem.contents(), "\ntext");
1001+
}
1002+
9841003
#[test]
9851004
fn multi_progress_println_terminal_wrap() {
9861005
let in_mem = InMemoryTerm::new(10, 48);

0 commit comments

Comments
 (0)