From 111f42cf7b5291ba6c2ff34b64ee643c4497efb4 Mon Sep 17 00:00:00 2001 From: Mark Thomas Date: Sun, 21 Apr 2019 15:51:47 +0100 Subject: [PATCH] join lines with CRLF when fully repainting surface When repainting a surface, we optimize for the case where lines are simple text by combining the the `Change::Text` for the end of the previous line and the start of the next line into a single `Change`. The assumption about relying on automatic margins is incorrect. We can't rely on them, as they might be disabled, and in any case they are no use if the previous line was shorter than the full width of the screen. This results in the lines appearing joined together on a single line. This is evidenced in the existing tests where `"hel\nw"` becomes `"helw"` on a full repaint. The solution is to always inject a real CRLF by adding a `CursorPosition` change. This replaces any CRLF that may have been swallowed by the `Surface` when it added the original changes. --- termwiz/src/surface/mod.rs | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/termwiz/src/surface/mod.rs b/termwiz/src/surface/mod.rs index da983c219..ad4f9d712 100644 --- a/termwiz/src/surface/mod.rs +++ b/termwiz/src/surface/mod.rs @@ -614,16 +614,7 @@ impl Surface { let mut changes = line.changes(&attr); - let result_len = result.len(); - if !changes.is_empty() && result[result_len - 1].is_text() && changes[0].is_text() { - // Assumption: that the output has working automatic margins. - // We can skip the cursor position change and just join the - // text items together - if let Change::Text(mut prefix) = result.remove(result_len - 1) { - prefix.push_str(changes[0].text()); - changes[0] = Change::Text(prefix); - } - } else if idx != 0 { + if idx != 0 { // We emit a relative move at the end of each // line with the theory that this will translate // to a short \r\n sequence rather than the longer @@ -913,7 +904,12 @@ mod test { assert_eq!( &[ Change::ClearScreen(Default::default()), - Change::Text("helw".into()), + Change::Text("hel".into()), + Change::CursorPosition { + x: Position::Absolute(0), + y: Position::Relative(1), + }, + Change::Text("w".into()), Change::CursorPosition { x: Position::Absolute(1), y: Position::Absolute(1), @@ -945,7 +941,12 @@ mod test { .set_background(AnsiColor::Red) .clone() ), - Change::Text("helw".into()), + Change::Text("hel".into()), + Change::CursorPosition { + x: Position::Absolute(0), + y: Position::Relative(1), + }, + Change::Text("w".into()), Change::ClearToEndOfScreen(AnsiColor::Red.into()), Change::CursorPosition { x: Position::Absolute(1),