From 983c8c68b7658a79343c9654003c963788843a82 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 19 Jul 2023 15:56:29 +0000 Subject: [PATCH] Only render as many lines as the terminal can actually display --- src/draw_target.rs | 32 ++-- tests/render.rs | 455 ++++++++++++--------------------------------- 2 files changed, 141 insertions(+), 346 deletions(-) diff --git a/src/draw_target.rs b/src/draw_target.rs index 57847bf4..bf2036f6 100644 --- a/src/draw_target.rs +++ b/src/draw_target.rs @@ -493,36 +493,42 @@ impl DrawState { _ => 0, }; + let term_height = term.height() as usize; + let term_width = term.width() as usize; let len = self.lines.len(); let mut real_len = 0; + let mut last_line_filler = 0; for (idx, line) in self.lines.iter().enumerate() { - if line.is_empty() { + let line_width = console::measure_text_width(line); + let diff = if line.is_empty() { // Empty line are new line - real_len += 1; + 1 } else { // Calculate real length based on terminal width // This take in account linewrap from terminal - let terminal_len = (console::measure_text_width(line) as f64 / term.width() as f64) - .ceil() as usize; + let terminal_len = (line_width 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); + usize::max(terminal_len, 1) + }; + if real_len + diff >= term_height { + break; } - if idx + 1 != len { - term.write_line(line)?; - } else { - // Don't append a '\n' if this is the last line - term.write_str(line)?; + real_len += diff; + if idx != 0 { + term.write_line("")?; + } + term.write_str(line)?; + if idx + 1 == len { // Keep the cursor on the right terminal side // So that next user writes/prints will happen on the next line - let term_width = term.width() as usize; - let line_width = console::measure_text_width(line); - term.write_str(&" ".repeat(term_width.saturating_sub(line_width)))?; + last_line_filler = term_width.saturating_sub(line_width); } } + term.write_str(&" ".repeat(last_line_filler))?; term.flush()?; *last_line_count = real_len - self.orphan_lines_count + shift; diff --git a/tests/render.rs b/tests/render.rs index 4678716d..22de375b 100644 --- a/tests/render.rs +++ b/tests/render.rs @@ -1151,10 +1151,9 @@ fn multi_progress_many_bars() { assert_eq!( in_mem.contents(), r#" -⠁ 3 -⠁ 4 -⠁ 5 -⠁ 6"# +░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0/10 +⠁ 0 +⠁ 1"# .trim_start() ); assert_eq!( @@ -1167,6 +1166,7 @@ fn multi_progress_many_bars() { "░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0/10" .into() ), + Str("".into()), NewLine, Str("⠁ 0".into()), Str( @@ -1183,8 +1183,10 @@ fn multi_progress_many_bars() { "░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0/10" .into() ), + Str("".into()), NewLine, Str("⠁ 0".into()), + Str("".into()), NewLine, Str("⠁ 1".into()), Str( @@ -1203,144 +1205,89 @@ fn multi_progress_many_bars() { "░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0/10" .into() ), + Str("".into()), NewLine, Str("⠁ 0".into()), + Str("".into()), NewLine, Str("⠁ 1".into()), - NewLine, - Str("⠁ 2".into()), - Str( - " " - .into() - ), + Str("".into()), Flush, - Up(3), - Clear, - Down(1), + Up(2), Clear, Down(1), Clear, Down(1), Clear, - Up(3), + Up(2), Str( "░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0/10" .into() ), + Str("".into()), NewLine, Str("⠁ 0".into()), + Str("".into()), NewLine, Str("⠁ 1".into()), - NewLine, - Str("⠁ 2".into()), - NewLine, - Str("⠁ 3".into()), - Str( - " " - .into() - ), + Str("".into()), Flush, - Up(4), - Clear, - Down(1), - Clear, - Down(1), + Up(2), Clear, Down(1), Clear, Down(1), Clear, - Up(4), + Up(2), Str( "░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0/10" .into() ), + Str("".into()), NewLine, Str("⠁ 0".into()), + Str("".into()), NewLine, Str("⠁ 1".into()), - NewLine, - Str("⠁ 2".into()), - NewLine, - Str("⠁ 3".into()), - NewLine, - Str("⠁ 4".into()), - Str( - " " - .into() - ), + Str("".into()), Flush, - Up(5), - Clear, - Down(1), - Clear, - Down(1), - Clear, - Down(1), + Up(2), Clear, Down(1), Clear, Down(1), Clear, - Up(5), + Up(2), Str( "░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0/10" .into() ), + Str("".into()), NewLine, Str("⠁ 0".into()), + Str("".into()), NewLine, Str("⠁ 1".into()), - NewLine, - Str("⠁ 2".into()), - NewLine, - Str("⠁ 3".into()), - NewLine, - Str("⠁ 4".into()), - NewLine, - Str("⠁ 5".into()), - Str( - " " - .into() - ), + Str("".into()), Flush, - Up(6), - Clear, - Down(1), - Clear, - Down(1), - Clear, - Down(1), - Clear, - Down(1), + Up(2), Clear, Down(1), Clear, Down(1), Clear, - Up(6), + Up(2), Str( "░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0/10" .into() ), + Str("".into()), NewLine, Str("⠁ 0".into()), + Str("".into()), NewLine, Str("⠁ 1".into()), - NewLine, - Str("⠁ 2".into()), - NewLine, - Str("⠁ 3".into()), - NewLine, - Str("⠁ 4".into()), - NewLine, - Str("⠁ 5".into()), - NewLine, - Str("⠁ 6".into()), - Str( - " " - .into() - ), + Str("".into()), Flush ] ); @@ -1350,54 +1297,32 @@ fn multi_progress_many_bars() { assert_eq!( in_mem.contents(), r#" -⠁ 3 -⠁ 4 -⠁ 5 -⠁ 6"# +██████████████████████████████████████████████████████████████████████████ 10/10 +⠁ 0 +⠁ 1"# .trim_start() ); assert_eq!( record.contents()[last_records..], [ - Up(7), - Clear, - Down(1), - Clear, - Down(1), - Clear, - Down(1), - Clear, - Down(1), - Clear, - Down(1), + Up(2), Clear, Down(1), Clear, Down(1), Clear, - Up(7), + Up(2), Str( "██████████████████████████████████████████████████████████████████████████ 10/10" .into() ), + Str("".into()), NewLine, Str("⠁ 0".into()), + Str("".into()), NewLine, Str("⠁ 1".into()), - NewLine, - Str("⠁ 2".into()), - NewLine, - Str("⠁ 3".into()), - NewLine, - Str("⠁ 4".into()), - NewLine, - Str("⠁ 5".into()), - NewLine, - Str("⠁ 6".into()), - Str( - " " - .into() - ), + Str("".into()), Flush ] ); @@ -1405,103 +1330,71 @@ fn multi_progress_many_bars() { drop(spinners); - assert_eq!(in_mem.contents(), r#""#); + assert_eq!( + in_mem.contents(), + r#"██████████████████████████████████████████████████████████████████████████ 10/10"# + ); assert_eq!( record.contents()[last_records..], [ - Up(6), - Clear, - Down(1), - Clear, - Down(1), - Clear, - Down(1), - Clear, - Down(1), - Clear, - Down(1), + Up(1), Clear, Down(1), Clear, - Up(6), + Up(1), Str("⠁ 1".into()), + Str("".into()), NewLine, Str("⠁ 2".into()), + Str("".into()), NewLine, Str("⠁ 3".into()), - NewLine, - Str("⠁ 4".into()), - NewLine, - Str("⠁ 5".into()), - NewLine, - Str("⠁ 6".into()), - Str( - " " - .into() - ), + Str("".into()), Flush, - Up(5), - Clear, - Down(1), - Clear, - Down(1), - Clear, - Down(1), + Up(2), Clear, Down(1), Clear, Down(1), Clear, - Up(5), + Up(2), Str("⠁ 2".into()), + Str("".into()), NewLine, Str("⠁ 3".into()), + Str("".into()), NewLine, Str("⠁ 4".into()), - NewLine, - Str("⠁ 5".into()), - NewLine, - Str("⠁ 6".into()), - Str( - " " - .into() - ), + Str("".into()), Flush, - Up(4), - Clear, - Down(1), - Clear, - Down(1), + Up(2), Clear, Down(1), Clear, Down(1), Clear, - Up(4), + Up(2), Str("⠁ 3".into()), + Str("".into()), NewLine, Str("⠁ 4".into()), + Str("".into()), NewLine, Str("⠁ 5".into()), - NewLine, - Str("⠁ 6".into()), - Str( - " " - .into() - ), + Str("".into()), Flush, - Up(3), - Clear, - Down(1), + Up(2), Clear, Down(1), Clear, Down(1), Clear, - Up(3), + Up(2), Str("⠁ 4".into()), + Str("".into()), NewLine, Str("⠁ 5".into()), + Str("".into()), NewLine, Str("⠁ 6".into()), Str( @@ -1517,6 +1410,7 @@ fn multi_progress_many_bars() { Clear, Up(2), Str("⠁ 5".into()), + Str("".into()), NewLine, Str("⠁ 6".into()), Str( @@ -1538,6 +1432,7 @@ fn multi_progress_many_bars() { Up(0), Clear, Up(0), + Str("".into()), Flush ] ); @@ -1590,10 +1485,9 @@ fn multi_progress_many_spinners() { assert_eq!( in_mem.contents(), r#" -⠁ 3 -⠁ 4 -⠁ 5 -⠁ 6"# +░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0/10 +⠁ 0 +⠁ 1"# .trim_start() ); @@ -1607,6 +1501,7 @@ fn multi_progress_many_spinners() { "░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0/10" .into() ), + Str("".into()), NewLine, Str("⠁ 0".into()), Str( @@ -1623,8 +1518,10 @@ fn multi_progress_many_spinners() { "░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0/10" .into() ), + Str("".into()), NewLine, Str("⠁ 0".into()), + Str("".into()), NewLine, Str("⠁ 1".into()), Str( @@ -1643,144 +1540,89 @@ fn multi_progress_many_spinners() { "░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0/10" .into() ), + Str("".into()), NewLine, Str("⠁ 0".into()), + Str("".into()), NewLine, Str("⠁ 1".into()), - NewLine, - Str("⠁ 2".into()), - Str( - " " - .into() - ), + Str("".into()), Flush, - Up(3), - Clear, - Down(1), + Up(2), Clear, Down(1), Clear, Down(1), Clear, - Up(3), + Up(2), Str( "░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0/10" .into() ), + Str("".into()), NewLine, Str("⠁ 0".into()), + Str("".into()), NewLine, Str("⠁ 1".into()), - NewLine, - Str("⠁ 2".into()), - NewLine, - Str("⠁ 3".into()), - Str( - " " - .into() - ), + Str("".into()), Flush, - Up(4), - Clear, - Down(1), - Clear, - Down(1), + Up(2), Clear, Down(1), Clear, Down(1), Clear, - Up(4), + Up(2), Str( "░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0/10" .into() ), + Str("".into()), NewLine, Str("⠁ 0".into()), + Str("".into()), NewLine, Str("⠁ 1".into()), - NewLine, - Str("⠁ 2".into()), - NewLine, - Str("⠁ 3".into()), - NewLine, - Str("⠁ 4".into()), - Str( - " " - .into() - ), + Str("".into()), Flush, - Up(5), - Clear, - Down(1), - Clear, - Down(1), - Clear, - Down(1), + Up(2), Clear, Down(1), Clear, Down(1), Clear, - Up(5), + Up(2), Str( "░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0/10" .into() ), + Str("".into()), NewLine, Str("⠁ 0".into()), + Str("".into()), NewLine, Str("⠁ 1".into()), - NewLine, - Str("⠁ 2".into()), - NewLine, - Str("⠁ 3".into()), - NewLine, - Str("⠁ 4".into()), - NewLine, - Str("⠁ 5".into()), - Str( - " " - .into() - ), + Str("".into()), Flush, - Up(6), - Clear, - Down(1), - Clear, - Down(1), - Clear, - Down(1), - Clear, - Down(1), + Up(2), Clear, Down(1), Clear, Down(1), Clear, - Up(6), + Up(2), Str( "░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0/10" .into() ), + Str("".into()), NewLine, Str("⠁ 0".into()), + Str("".into()), NewLine, Str("⠁ 1".into()), - NewLine, - Str("⠁ 2".into()), - NewLine, - Str("⠁ 3".into()), - NewLine, - Str("⠁ 4".into()), - NewLine, - Str("⠁ 5".into()), - NewLine, - Str("⠁ 6".into()), - Str( - " " - .into() - ), + Str("".into()), Flush ] ); @@ -1791,53 +1633,33 @@ fn multi_progress_many_spinners() { assert_eq!( in_mem.contents(), r#" -⠁ 2 -⠁ 4 -⠁ 5 -⠁ 6"# +░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0/10 +⠁ 0 +⠁ 1"# .trim_start() ); assert_eq!( record.contents()[last_records..], [ - Up(7), - Clear, - Down(1), - Clear, - Down(1), - Clear, - Down(1), - Clear, - Down(1), - Clear, - Down(1), + Up(2), Clear, Down(1), Clear, Down(1), Clear, - Up(7), + Up(2), Str( "░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0/10" .into() ), + Str("".into()), NewLine, Str("⠁ 0".into()), + Str("".into()), NewLine, Str("⠁ 1".into()), - NewLine, - Str("⠁ 2".into()), - NewLine, - Str("⠁ 4".into()), - NewLine, - Str("⠁ 5".into()), - NewLine, - Str("⠁ 6".into()), - Str( - " " - .into() - ), + Str("".into()), Flush, ] ); @@ -1848,48 +1670,32 @@ fn multi_progress_many_spinners() { assert_eq!( in_mem.contents(), r#" -⠁ 1 -⠁ 2 -⠁ 4 -⠁ 6"# +░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0/10 +⠁ 0 +⠁ 1"# .trim_start() ); assert_eq!( record.contents()[last_records..], [ - Up(6), - Clear, - Down(1), - Clear, - Down(1), - Clear, - Down(1), - Clear, - Down(1), + Up(2), Clear, Down(1), Clear, Down(1), Clear, - Up(6), + Up(2), Str( "░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0/10" .into() ), + Str("".into()), NewLine, Str("⠁ 0".into()), + Str("".into()), NewLine, Str("⠁ 1".into()), - NewLine, - Str("⠁ 2".into()), - NewLine, - Str("⠁ 4".into()), - NewLine, - Str("⠁ 6".into()), - Str( - " " - .into() - ), + Str("".into()), Flush ] ); @@ -1904,77 +1710,59 @@ fn multi_progress_many_spinners() { assert_eq!( record.contents()[last_records..], [ - Up(5), - Clear, - Down(1), - Clear, - Down(1), - Clear, - Down(1), + Up(2), Clear, Down(1), Clear, Down(1), Clear, - Up(5), + Up(2), Str( "░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0/10" .into() ), + Str("".into()), NewLine, Str("⠁ 1".into()), + Str("".into()), NewLine, Str("⠁ 2".into()), - NewLine, - Str("⠁ 4".into()), - NewLine, - Str("⠁ 6".into()), - Str( - " " - .into() - ), + Str("".into()), Flush, - Up(4), - Clear, - Down(1), - Clear, - Down(1), + Up(2), Clear, Down(1), Clear, Down(1), Clear, - Up(4), + Up(2), Str( "░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0/10" .into() ), + Str("".into()), NewLine, Str("⠁ 2".into()), + Str("".into()), NewLine, Str("⠁ 4".into()), - NewLine, - Str("⠁ 6".into()), - Str( - " " - .into() - ), + Str("".into()), Flush, - Up(3), - Clear, - Down(1), + Up(2), Clear, Down(1), Clear, Down(1), Clear, - Up(3), + Up(2), Str( "░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0/10" .into() ), + Str("".into()), NewLine, Str("⠁ 4".into()), + Str("".into()), NewLine, Str("⠁ 6".into()), Str( @@ -1993,6 +1781,7 @@ fn multi_progress_many_spinners() { "░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0/10" .into() ), + Str("".into()), NewLine, Str("⠁ 6".into()), Str(