Skip to content

Commit

Permalink
Fix subtract with overflow when measuring terminal line length
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
foresterre authored and djc committed Jun 3, 2023
1 parent bd320a1 commit f88ec3b
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 2 deletions.
10 changes: 8 additions & 2 deletions src/draw_target.rs
Expand Up @@ -502,8 +502,14 @@ impl DrawState {
} else {
// Calculate real length based on terminal width
// This take in account linewrap from terminal
real_len += (console::measure_text_width(line) as f64 / term.width() as f64).ceil()
as usize;
let terminal_len = (console::measure_text_width(line) as f64 / term.width() as f64)
.ceil() as usize;

// If the line is effectively empty (for example when it consists
// solely of ANSI color code sequences, count it the same as a
// new line. If the line is measured to be len = 0, we will
// subtract with overflow later.
real_len += usize::max(terminal_len, 1);
}
if idx + 1 != len {
term.write_line(line)?;
Expand Down
19 changes: 19 additions & 0 deletions tests/render.rs
Expand Up @@ -981,6 +981,25 @@ s"#
println!("{:?}", in_mem.contents())
}

#[test]
fn spinner_terminal_cleared_log_line_with_ansi_codes() {
let in_mem = InMemoryTerm::new(10, 100);

let pb = ProgressBar::with_draw_target(
Some(10),
ProgressDrawTarget::term_like(Box::new(in_mem.clone())),
);
pb.set_style(ProgressStyle::default_spinner());
assert_eq!(in_mem.contents(), String::new());

pb.finish_and_clear();
// Visually empty, but consists of an ANSII code
pb.println("\u{1b}[1m");

pb.println("text\u{1b}[0m");
assert_eq!(in_mem.contents(), "\ntext");
}

#[test]
fn multi_progress_println_terminal_wrap() {
let in_mem = InMemoryTerm::new(10, 48);
Expand Down

0 comments on commit f88ec3b

Please sign in to comment.